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:361

    Update 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:816

    Update 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. ; )


  • Mod

    Did you use the IR receiver on a red LED and it works?




Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.