I was interested in how the S0PCM-5 module worked and was thinking of making it myself with an Arduino. And i managed to do it
I had a look at the
Domoticz sourcecode that handles the S0PCM and it is actually quite simple, especially when i found out the description of the data that the original S0PCM spits out:
- Spoiler: show
- /a:S0 Pulse Counter V0.x
Data record (repeated every interval):
IDIM1:c:d:M2:e:f:M3:g:h:M4:i:j:M5:k:l
Legenda:
a -> Unique ID of the S0PCM
b -> interval between two telegrams in seconds
c -> number of pulses in the last interval of register 1
d -> number of pulses since the last start-up of register 1
e -> number of pulses in the last interval of register 2
f -> number of pulses since the last start-up of register 2
.... etc.... for register 3, 4, 5
Source:
http://www.smartmeterdashboard.nl/blog/ ... ects=0&d=1
So you just need to provide Domoticz with two counters (for each device), one counter that contains the counts since the start of the Arduino, and one with the counts since the last interval (=message sent to Domoticz, every 10s in default situation).
I then went on editing an Arduino sketch, it is mainly based on
this one.
I came up with the code below:
S0CounterArduino.ino
- Spoiler: show
Code: Select all
//Number of pulses, used to measure energy.
volatile unsigned int pulseCount1 = 0;
volatile unsigned int pulseCount1_sinceStart = 0;
volatile unsigned int pulseCount2 = 0;
volatile unsigned int pulseCount2_sinceStart = 0;
volatile unsigned int updateCount = 0;
volatile unsigned int reportInterval = 10; //Interval between messages being sent out (in seconds)
int PulseCounterID = 12345;
int PulseCounterVersion = 999;
// The interrupt routine
void onPulse1()
{
//pulseCounter
pulseCount1++;
pulseCount1_sinceStart++;
//Blink built-in LED on S0-pulse
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(80); // wait for a few miliseconds
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
}
// The interrupt routine
//void onPulse2()
//{
//pulseCounter
//pulseCount2++;
//pulseCount2_sinceStart++;
//}
void setup()
{
// KWH interrupt attached to IRQ 0 = pin2 (D2)
attachInterrupt(0, onPulse1, FALLING);
//KWH interrupt attached to IRQ 1 = pin3
//attachInterrupt(1, onPulse2, FALLING);
Serial.begin(9600);
Serial.print("/");
Serial.print(PulseCounterID);
Serial.print(":S0 Pulse Counter V");
Serial.println(PulseCounterVersion);
}
void loop()
{
updateCount = 0;
Serial.print("ID:");
Serial.print(PulseCounterID);
Serial.print(":I:10:M1:");
Serial.print(pulseCount1);
Serial.print(":");
Serial.print(pulseCount1_sinceStart);
Serial.print(":");
Serial.print("M2");
Serial.print(":");
Serial.print(pulseCount2);
Serial.print(":");
Serial.println(pulseCount2_sinceStart);
pulseCount1 = 0;
pulseCount2 = 0;
updateCount++;
delay(reportInterval * 1000); // Need to multiply it by 1000 because we need it in ms
}
To test it, i used a second Arduino and let it blink it's internal LED, pretending to be that it's an flashing kWh-meter LED.
A pulse should last about 30 - 100ms i found in meter datasheet.
In Domoticz i added the Arduino (presents itself as a serial COM-port) and two devices popped up. I then placed the 'kWh-faker' Arduino in front of the photodiode. After a few seconds i saw the current (fake) powerusage of ~1800-2200W, success!!!
For a schema on how to connect a S0-counter, i suppose you can just use the schema from here:
http://fun-tech.se/FunTechHouse/ElectricityMeter/
kWhSimulator.ino
- Spoiler: show
Code: Select all
/*
This sketch pretends itself as a blinkin LED on a kWh-meter for measuring electricity
*/
// Pin 13 has an LED connected on most Arduino boards.
int led = 13;
volatile unsigned int FakeConsumptionWatt = 1800; //Fill in a value (in Watts) to fake the kWh-reading device with
int PulseDuration = 50; //Most real kWh-meters seem to use values between 30 - 100ms
float TimeBetweenBlinks;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
TimeBetweenBlinks = (FakeConsumptionWatt / 3.6) * 4; //In miliseconds
}
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(PulseDuration); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(TimeBetweenBlinks); // Calculate and wait, to let the LED blink in a interval that corresponds with the given consumption
}
I quickly hacked this together, so i don't have any experience on how it performs in a production setup. It could be that you need some code like debouncing. I also have a DIN-rail kWh-meter with S0-connector that i will connect to the Arduino so i can test it with a real S0 device. But i don't have much time now, so that will be something for later. First observation: it works, but accuracy is not spot on. But could also be due to the Arduino faking the kWh, it is using 'delay' and that isn't very accurate. Using 'millis' would be better. Will test it later with a S0 meter and with my kWh-meter in the meter cabinet (has a flashing led, 2000imp/kwh).
But i just wanted to share this, so people can fiddle around with it
I am not active on this forum anymore.