Reads power consumption from a Electricity meter via the meters puls output, and publishes the results on a MQTT server.
A rising reading of how much has been used since. Every time the device is restarted the reading restarts with 0.
data syntax is "energy=XX.XXX kWh", where XX.XXX is the reading in kWh.
example:
"18:57:12" "FunTechHouse/Energy/meter01" "energy=59.549 kWh"
"19:00:22" "FunTechHouse/Energy/meter01" "energy=59.554 kWh"
"19:03:32" "FunTechHouse/Energy/meter01" "energy=59.558 kWh"
"18:57:12" "FunTechHouse/Energy/meter02" "energy=46.440 kWh"
"19:00:22" "FunTechHouse/Energy/meter02" "energy=46.440 kWh"
"19:03:32" "FunTechHouse/Energy/meter02" "energy=46.501 kWh"
This project does not subscribe to any data.
Name | Link | Desc |
---|---|---|
Arduino Uno | arduino.cc - Arduino Uno | |
Arduino Ethernet Shield | arduino.cc - Arduino Ethernet Shield | |
Iskra WS1102 | Datasheet Iskra WS1102 | A energy meter with a pulse output, 1000 impl/kWh |
Name | Desc |
---|---|
github.com - FunTechHouse_ElectricityMeter | The main Arduino program |
arduino.cc - arduino-1.0.1 | The Arduino environment |
Arduino Client for MQTT / (github) | The mqtt client code included in the main app. |
The setup tells that we would like to connect interrupt function onPulse1 to pin 2 and onPulse2 on pin 3. Also to start ethernet and send a stupid message to the mqtt server that we had a restart, a little hello.
Filename: setup.part.c
void setup() { // KWH interrupt attached to IRQ 0 = pin2 attachInterrupt(0, onPulse1, FALLING); // KWH interrupt attached to IRQ 1 = pin3 attachInterrupt(1, onPulse2, FALLING); Ethernet.begin(mac, ip); if (client.connect(project_name)) { client.publish(topic_meter01, "#Hello world"); client.publish(topic_meter02, "#Hello world"); //client.subscribe("inTopic"); } }
Then every time we get a interrupt from the energy meter we know he has measured 1 Wh, so we add 1Wh to the counter. However to avoid overflow to fast I splitted the counter into two variables, so when we hit 1kWh we increase that one.
Filename: onPulse1.part.c
void onPulse1() { //pulseCounter pulseCount1_Wh++; if(pulseCount1_Wh == 1000) { pulseCount1_Wh = 0; pulseCount1_kWh++; } }
And every 10s or so we run the loop function. But to avoid to much data, we only send data to the server every 3-4min or so.
Filename: loop.part.c
void loop() { //Talk with the server so he dont forget us. if(client.loop() == false) { client.connect(project_name); } //But only send data every minute or so // 6 -> 6*10s = 60s = 1min //12 -> 2*6*10s = 120s = 2min //18 -> 3*6*10s = 180s = 3min //BUT since the delay is not that accurate, // 18 is more like 3.5 to 4 minutes in real life... if(updateCount > 18) { updateCount = 0; char str[30]; snprintf(str, 30, "energy=%u.%03u kWh", pulseCount1_kWh, pulseCount1_Wh); if(client.connected()) { client.publish(topic_meter01, str); } snprintf(str, 30, "energy=%u.%03u kWh", pulseCount2_kWh, pulseCount2_Wh); if(client.connected()) { client.publish(topic_meter02, str); } } updateCount++; delay(10000); // 10*1000ms = 10s }
And the entire code looks like this.
Filename: FunTechHouse_ElectricityMeter.ino
#include <SPI.h> #include <Ethernet.h> #include "PubSubClient.h" // Update these with values suitable for your network. byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0x02 }; byte ip[] = { 192, 168, 0, 32 }; byte server[] = { 192, 168, 0, 64 }; char project_name[] = "FunTechHouse_ElectricityMeter"; char topic_meter01[] = "FunTechHouse/Energy/meter01"; char topic_meter02[] = "FunTechHouse/Energy/meter02"; //Number of pulses, used to measure energy. volatile unsigned int pulseCount1_Wh = 0; volatile unsigned int pulseCount1_kWh = 0; volatile unsigned int pulseCount2_Wh = 0; volatile unsigned int pulseCount2_kWh = 0; volatile unsigned int updateCount = 0; void callback(char* topic, byte* payload,unsigned int length) { // handle message arrived } // The interrupt routine void onPulse1() { //pulseCounter pulseCount1_Wh++; if(pulseCount1_Wh == 1000) { pulseCount1_Wh = 0; pulseCount1_kWh++; } } // The interrupt routine void onPulse2() { //pulseCounter pulseCount2_Wh++; if(pulseCount2_Wh == 1000) { pulseCount2_Wh = 0; pulseCount2_kWh++; } } PubSubClient client(server, 1883, callback); void setup() { // KWH interrupt attached to IRQ 0 = pin2 attachInterrupt(0, onPulse1, FALLING); // KWH interrupt attached to IRQ 1 = pin3 attachInterrupt(1, onPulse2, FALLING); Ethernet.begin(mac, ip); if (client.connect(project_name)) { client.publish(topic_meter01, "#Hello world"); client.publish(topic_meter02, "#Hello world"); //client.subscribe("inTopic"); } } void loop() { //Talk with the server so he dont forget us. if(client.loop() == false) { client.connect(project_name); } //But only send data every minute or so // 6 -> 6*10s = 60s = 1min //12 -> 2*6*10s = 120s = 2min //18 -> 3*6*10s = 180s = 3min //BUT since the delay is not that accurate, // 18 is more like 3.5 to 4 minutes in real life... if(updateCount > 18) { updateCount = 0; char str[30]; snprintf(str, 30, "energy=%u.%03u kWh", pulseCount1_kWh, pulseCount1_Wh); if(client.connected()) { client.publish(topic_meter01, str); } snprintf(str, 30, "energy=%u.%03u kWh", pulseCount2_kWh, pulseCount2_Wh); if(client.connected()) { client.publish(topic_meter02, str); } } updateCount++; delay(10000); // 10*1000ms = 10s }