Different values in GW and other recieve node with node-to-node communication
-
I am trying to use the EnergyMeter sketch to send the watt value both to my GW (to my Vera Edge) and to another node sensor (Energy Display).
I have used the EnergyMeter sketch for a year before now only receiving the data in Vera and it has been working fine.When I now try to add code to make it send the data also to my new Energy Display node some strange things happens.
The data still is correct in my Vera but I get false values to my Energy Display node. I am using the same parameter and the EnergyMeter node seems to send the correct data to both the GW and the Energy Display node. But still I receive different values in the GW and the other node.
Here is how the output looks in the Energy Display node:
send: 15-15-0-0 s=255,c=0,t=17,pt=0,l=5,sg=0,st=ok:1.5.1
send: 15-15-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,st=ok:0
read: 0-0-15 s=255,c=3,t=6,pt=0,l=1,sg=0:M
sensor started, id=15, parent=0, distance=1
send: 15-15-0-0 s=255,c=3,t=11,pt=0,l=12,sg=0,st=ok:Watt Display
send: 15-15-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,st=ok:1.1
send: 15-15-0-0 s=1,c=0,t=25,pt=0,l=0,sg=0,st=ok:
send: 15-15-0-0 s=255,c=3,t=1,pt=0,l=0,sg=0,st=ok:
Clear Screen
read: 0-0-15 s=255,c=3,t=1,pt=0,l=10,sg=0:1487507660
read: 7-0-15 s=1,c=1,t=17,pt=5,l=4,sg=0:233 (163 in Vera)
Received last watt value from node 7:233
Update Watt-value
35
read: 7-0-15 s=1,c=1,t=17,pt=5,l=4,sg=0:361 (164 in Vera)
Received last watt value from node 7:361Update Watt-value
36
read: 7-0-15 s=1,c=1,t=17,pt=5,l=4,sg=0:816 (165 in Vera)
Received last watt value from node 7:816Update Watt-value
37
read: 7-0-15 s=1,c=1,t=17,pt=5,l=4,sg=0:172 (165 in Vera)
Received last watt value from node 7:172
I have added the correct values that is presented thru my GW (in Vera).
Here is the code in the EntergyMeter (sending) node:
#include <SPI.h> #include <MySensor.h> #include <MyTransportNRF24.h> #include <MyHwATMega328.h> #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR 1000 // Nummber of blinks per KWH of your meeter #define SLEEP_MODE false // Watt-value can only be reported when sleep mode is false. #define MAX_WATT 15000 // Max watt value to report. This filetrs outliers. #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) #define CHILD_ID 1 // Id of the sensor child #define RF24_PA_LEVEL_GW RF24_PA_MAX unsigned long SEND_FREQUENCY = 30000; // Minimum time between send (in milliseconds). We don't want to spam the gateway. // NRFRF24L01 radio driver (set to max transmit power) MyTransportNRF24 radio(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW); MyHwATMega328 hw; // Select AtMega328 hardware profile MySensor gw(radio, hw); double ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour boolean pcReceived = false; volatile unsigned long pulseCount = 0; volatile unsigned long lastBlink = 0; volatile unsigned long watt = 0; unsigned long oldPulseCount = 0; unsigned long oldWatt = 0; double oldKwh; unsigned long lastSend; MyMessage wattMsg(CHILD_ID,V_WATT); MyMessage kwhMsg(CHILD_ID,V_KWH); MyMessage pcMsg(CHILD_ID,V_VAR1); MyMessage wattMsgLCD(CHILD_ID,V_WATT); // Message to Entergy Display sensor void setup() { gw.begin(incomingMessage, 7, false); // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("Energy Meter", "1.7"); // Register this device as power sensor gw.present(CHILD_ID, S_POWER); // Fetch last known pulse count value from gw gw.request(CHILD_ID, V_VAR1); attachInterrupt(INTERRUPT, onPulse, RISING); lastSend=millis(); wattMsgLCD.setDestination(15); // Set sensor ID 15 for Energy Display sensor } void loop() { gw.process(); unsigned long now = millis(); // Only send values at a maximum frequency or woken up from sleep bool sendTime = now - lastSend > SEND_FREQUENCY; if (pcReceived && (SLEEP_MODE || sendTime)) { // New watt value has been calculated if (!SLEEP_MODE && watt != oldWatt) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (watt<((unsigned long)MAX_WATT)) { gw.send(wattMsg.set(watt)); // Send watt value to gw gw.send(wattMsgLCD.set(watt)); // Send watt value to energy display } Serial.print("Watt:"); Serial.println(watt); oldWatt = watt; } // Pulse count has changed if (pulseCount != oldPulseCount) { gw.send(pcMsg.set(pulseCount)); // Send pulse count value to gw double kwh = ((double)pulseCount/((double)PULSE_FACTOR)); oldPulseCount = pulseCount; if (kwh != oldKwh) { gw.send(kwhMsg.set(kwh, 4)); // Send kwh value to gw oldKwh = kwh; } } lastSend = now; } else if (sendTime && !pcReceived) { // No count received. Try requesting it again gw.request(CHILD_ID, V_VAR1); lastSend=now; } if (SLEEP_MODE) { gw.sleep(SEND_FREQUENCY); } } void incomingMessage(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount = oldPulseCount = message.getLong(); Serial.print("Received last pulse count from gw:"); Serial.println(pulseCount); pcReceived = true; } } void onPulse() { if (!SLEEP_MODE) { unsigned long newBlink = micros(); unsigned long interval = newBlink-lastBlink; if (interval<10000L) { // Sometimes we get interrupt on FALLING return; } watt = (3600000000.0 /interval) / (ppwh * 2); lastBlink = newBlink; } pulseCount++; }
Here is the code from the Energy Display (receiving) node:
#include <U8glib.h> #include <MySensor.h> #include <SPI.h> #include <Wire.h> #include <Time.h> #include <MyTransportNRF24.h> #include <MyHwATMega328.h> #define CHILD_ID 1 U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); MyTransportNRF24 radio(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW); // NRFRF24L01 radio driver MyHwATMega328 hw; // Select AtMega328 hardware profile MySensor gw(radio, hw); boolean timeReceived = false; unsigned long lastTimeUpdate=0, lastRequest=0; int min_value[60] = {0}; unsigned long watt = 0; void setup() { gw.begin(incomingMessage, 15, false, 0); Wire.begin(); // init I2C // Send the sketch version information to the gateway and Controller gw.sendSketchInfo("Watt Display", "1.1"); gw.present(CHILD_ID, S_SCENE_CONTROLLER); // Request time from controller. gw.requestTime(receiveTime); // Flip screen u8g.setRot180(); Serial.println("Clear Screen"); clearScreen(); gw.wait(2000); } void loop() { // Serial.println("Loop"); gw.process(); unsigned long now = millis(); u8g.firstPage(); do { // Serial.println("Display Watt"); displayWatt(); // Serial.println("Display kWh"); displaykWh(); } while( u8g.nextPage() ); // rebuild the picture after some delay gw.wait(4000); // Serial.println("Clear Screen"); clearScreen(); gw.wait(1000); // If no time has been received yet, request it every 10 second from controller // When time has been received, request update every hour if ((!timeReceived && now-lastRequest > (unsigned long)10*1000) || (timeReceived && now-lastRequest > (unsigned long)60*1000*60)) { // Request time from controller. Serial.println("requesting time"); gw.requestTime(receiveTime); lastRequest = now; } // Update watt-value every minute if (timeReceived && now-lastTimeUpdate > (unsigned long)1000*60) { //Update minute-watt-value. Serial.println("Update Watt-value"); int var_minute = minute(); Serial.println(var_minute); min_value[var_minute] = watt; lastTimeUpdate = now; } } // This is called when a new watt value is received void incomingMessage(const MyMessage &message) { if (message.type==V_WATT) { Serial.print("Received last watt value from node 7:"); Serial.println(message.getULong()); // Check that we dont get unresonable large watt value. if (message.getULong()<((unsigned long)15000)) { watt = message.getULong(); } } } // This is called when a new time value is received void receiveTime(unsigned long time) { // Ok, set incoming time setTime(time); timeReceived = true; } void clearScreen() { u8g.firstPage(); do { } while( u8g.nextPage() ); } void displayWatt() { char buf[15]; dtostrf(watt, 5, 0, buf); // u8g.setFont(u8g_font_freedoomr25n); u8g.setFont(u8g_font_unifont); // Serial.println("Draw string Watt"); u8g.drawStr( 0, 10, buf); u8g.drawStr( 50, 10, "Watt"); } void displaykWh() { float kWh_value = 0; for (int i = 0; i < 60; i++) { kWh_value = kWh_value + min_value[i]; // Serial.print("kWh_value: "); // Serial.println(kWh_value); // Serial.print("min_value[i]: "); // Serial.println(min_value[i]); } // Serial.print("kWh_value: "); // Serial.println(kWh_value); float kWh_hour = (kWh_value / (float)60000.0); // Serial.print("kWh_hour: "); // Serial.println(kWh_hour); char buf2[15]; dtostrf(kWh_hour, 6, 3, buf2); u8g.setFont(u8g_font_unifont); // Serial.println("Draw string kWh"); u8g.drawStr( 0, 30, buf2); u8g.drawStr( 50, 30, "kWh/h"); }
Can anyone tell me what is wrong here?
Br
Henrik
-
I do not check all your code, but you have got some weird things there.
For example in function displayWatt() "watt" is unsigned long and you use dtostrf(watt, 5, 0, buf);
double to string, not ulong to string ?!?
-
Thanks kimot!
I will change that.
But perhaps that isn't the root cause to the problem. The display always shows the same value as in the console, that the sensor is receiving, so the conversion seems to work even that it is double to string.
-
Hi again!
I have now had more time to test and it showed that there wasn't anything wrong with the code.
I put a longer cable (5 meters) on the light (IR) sensor so that I could place the arduino with antenna further away from the electricity meter, and then everything started working as it should.
Perhaps the problem was electrical interference/magnetic fields or something like that.
So now I have a display in the house that shows how much electricity that is consumed in real time (updates every 30 sec).
Here is now also one more example of code for node-to-node communication. It took me some time to find how to do that so hopefully this can help someone else. ; )
-
Did you use the IR receiver on a red LED and it works?
-
@gohan
No my electricity meter has a IR led.
But during my tests I actually used a regular red led and that worked too with the Light/IR receiver I use. : )
https://www.aliexpress.com/item/5-pcs-LM393-Light-Sensor-Photosensitive-Sensitivity-light-Sensor-Module-For-Arduino-Smart-Car/1729424221.html