Warning: Undefined array key "HTTP_ACCEPT_LANGUAGE" in /customers/9/b/5/fun-tech.se/httpd.www/FunTechHouse/class.page.php on line 126
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
}




