Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. My Project
  3. Power/ Usage sensor - multi channel - local display

Power/ Usage sensor - multi channel - local display

Scheduled Pinned Locked Moved My Project
41 Posts 6 Posters 19.6k Views 7 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    MarkV
    wrote on last edited by
    #11

    Dawm maybe thats the problem..
    I connected the 5v as commen to the pulse + and the - to the digital inputs.

    So to be sure i need to connect the pulse + to the digitale inputs and the pulse - to gnd????

    AWIA 1 Reply Last reply
    0
    • M MarkV

      Dawm maybe thats the problem..
      I connected the 5v as commen to the pulse + and the - to the digital inputs.

      So to be sure i need to connect the pulse + to the digitale inputs and the pulse - to gnd????

      AWIA Offline
      AWIA Offline
      AWI
      Hero Member
      wrote on last edited by
      #12

      @MarkV I would depend on your S0 meters, but normal is "open collector" so you can connect '-' to ground and '+' to the input (= pull-up to Vcc).

      (another way to connect is + to vcc and - to input, but then you need external "pull down" resistors and change the sketch)

      1 Reply Last reply
      0
      • M Offline
        M Offline
        MarkV
        wrote on last edited by MarkV
        #13

        Then thats the problem with the slave arduino getting no data. I connected the pulse output like you mentioned second and didn't changed the sketch.
        Maybe i'm home tomorrow then i will give it a try.
        Or is it hard to chsnge the sketch? And what should i change?

        AWIA 1 Reply Last reply
        0
        • M MarkV

          Then thats the problem with the slave arduino getting no data. I connected the pulse output like you mentioned second and didn't changed the sketch.
          Maybe i'm home tomorrow then i will give it a try.
          Or is it hard to chsnge the sketch? And what should i change?

          AWIA Offline
          AWIA Offline
          AWI
          Hero Member
          wrote on last edited by
          #14

          @MarkV it is indicated in the sketch but you also need external resistors for pull-down. If you disable the internal pull-up resistors the levels are inverted. So you also need to'invert' the measurements or you are measuring the pulse width instead of the time between pulses.

          1 Reply Last reply
          0
          • M Offline
            M Offline
            MarkV
            wrote on last edited by
            #15

            Tonight i checked the wires and changed them and i believe your wright, the output is:
            Schermafdruk 2015-09-22 21.30.56.png

            But it keeps giving a error, so i hangt them near each other with approx. 10cm space in between, why does it stil say fail after a good startup with ok and after 10a20sec it starts saying fail..

            Is the readout correct?
            And what more could cause the fail error?

            AWIA 1 Reply Last reply
            0
            • M MarkV

              Tonight i checked the wires and changed them and i believe your wright, the output is:
              Schermafdruk 2015-09-22 21.30.56.png

              But it keeps giving a error, so i hangt them near each other with approx. 10cm space in between, why does it stil say fail after a good startup with ok and after 10a20sec it starts saying fail..

              Is the readout correct?
              And what more could cause the fail error?

              AWIA Offline
              AWIA Offline
              AWI
              Hero Member
              wrote on last edited by
              #16

              @MarkV In most of the cases "fail" is related to the power supply of the radio. Did you follow the instructions for connection of the radio?

              1 Reply Last reply
              0
              • AWIA AWI

                the code for the measurement device::

                //---------------------------------------------------------------------------------------------
                // Arduino Pulse Counting Sketch for counting pulses from up to 12 pulse output meters.
                // uses direct port manipulation to read from each register of 6 digital inputs simultaneously
                //
                // Licence: GNU GPL
                // part of the openenergymonitor.org project
                //
                // Author: Trystan Lea
                // AWI: adapted to produce JSON and error checking at client side.
                //---------------------------------------------------------------------------------------------
                //---------------------------------------------------------------------------------------------
                // Pulse Counting Class - could be placed in seperate library...
                //---------------------------------------------------------------------------------------------
                class PulseOutput
                {
                public:                                 		 //AWI: access to all
                  boolean pulse(int,int,unsigned long);                  //Detects pulses, in pulseLib.ino
                  unsigned long rate( unsigned long );                   //Calculates rate 
                
                  unsigned long count;                                   //pulse count accumulator
                  unsigned long countAccum;                              //pulse count total accumulator for extended error checking (only resets at startup)
                  unsigned long prate;                                   //pulse width in time 
                  unsigned long prateAccum;                              //pulse rate accumulator for calculating mean.
                
                private:
                  boolean ld,d;                                          //used to determine pulse edge
                  unsigned long lastTime,time;                           //used to calculate rate
                };
                
                //---------------------------------------------------------------------------------------------
                // Variable declaration
                //---------------------------------------------------------------------------------------------
                
                //CHANGE THIS TO VARY RATE AT WHICH PULSE COUNTING ARDUINO SPITS OUT PULSE COUNT+RATE DATA
                //time in seconds;
                const unsigned long printTime = 1000000;	// delay between serial outputs in us (one meter at a time)  
                const int lastMeter = 7 ; 	 	// is number of meters + 1
                
                byte curMeter = 2 ;				// current meter for serial output, wraps from 2 to lastMeter
                
                //---------------------------------------------------------------------------------------------
                PulseOutput p[14];            //Pulse output objects
                
                int a,b,la,lb;                //Input register variables
                
                unsigned long ltime, time;    //time variables
                
                void setup()
                {
                 // take care: pull-up inverses state! line 155
                	//setup input pins here with pull_up, else (default) float
                	pinMode( 2, INPUT_PULLUP);
                	pinMode( 3, INPUT_PULLUP);
                	pinMode( 4, INPUT_PULLUP);
                	pinMode( 5, INPUT_PULLUP);
                	pinMode( 6, INPUT_PULLUP);
                	pinMode( 7, INPUT_PULLUP);
                	pinMode( 8, INPUT_PULLUP);
                	pinMode( 9, INPUT_PULLUP);
                	pinMode(10, INPUT_PULLUP);
                	pinMode(11, INPUT_PULLUP);
                	pinMode(12, INPUT_PULLUP);
                	pinMode(13, INPUT_PULLUP);
                 
                 
                  Serial.begin(115200);       //standard serial
                  DDRD = DDRD | B00000000;
                  DDRB = DDRD | B00000000;
                }
                
                void loop()
                {
                
                  la = a;                    //last register a used to detect input change 
                  lb = b;                    //last register b used to detect input change
                
                  //--------------------------------------------------------------------
                  // Read from input registers
                  //--------------------------------------------------------------------
                  a = PIND >> 2;             //read digital inputs 2 to 7 really fast
                  b = PINB;                  //read digital inputs 8 to 13 really fast
                  time = micros();
                  if (la!=a || lb!=b)
                  {
                
                
                    //--------------------------------------------------------------------
                    // Detect pulses from register A
                    //--------------------------------------------------------------------
                    p[2].pulse(0,a,time);                //digital input 2
                    p[3].pulse(1,a,time);                //    ''        3
                    p[4].pulse(2,a,time);                //    ''        etc
                    p[5].pulse(3,a,time);
                    p[6].pulse(4,a,time);
                    p[7].pulse(5,a,time);
                
                    //--------------------------------------------------------------------
                    // Detect pulses from register B
                    //--------------------------------------------------------------------
                    p[8].pulse(0,b,time);                //digital input 8
                    p[9].pulse(1,b,time);                //etc
                    p[10].pulse(2,b,time);
                    p[11].pulse(3,b,time);
                    p[12].pulse(4,b,time);
                    p[13].pulse(5,b,time);
                
                  }
                
                  //--------------------------------------------------------------------
                  // Spit out data every printTime sec (time here is in microseconds)
                  //--------------------------------------------------------------------
                  // build JSON: for all counters print Count (W), Count Accum(W), Average ms
                  // Format {"m":meter,"c":count,"r":rate, "cA":countAccum}
                  if ((time-ltime)>(printTime))    
                  {
                    ltime = time;                          	//Print timer
                    
                    {
                      Serial.print("{\"m\":"); 
                      Serial.print(curMeter-1);           	//Print meter number
                      Serial.print(",\"c\":"); 
                      Serial.print(p[curMeter].count);    	//Print pulse count
                      Serial.print(",\"r\":"); 
                      Serial.print(p[curMeter].rate(time));	//Print pulse rate
                	  p[curMeter].countAccum += p[curMeter].count;	//Increment and print count accumulator to allow for error checking at client side;
                	  Serial.print(",\"cA\":"); 
                      Serial.print(p[curMeter].countAccum); 
                      Serial.println("}");
                      p[curMeter].count = 0;                //Reset count (we just send count increment)
                      p[curMeter].prateAccum = 0;       	//Reset accum so that we can calculate a new average
                    }
                	curMeter++ ;							
                	if (curMeter > lastMeter){				// wrap a around if passed last meter
                		curMeter = 2;} 
                  }
                }
                
                // library for pulse, originally in separate file 
                
                //-----------------------------------------------------------------------------------
                //Gets a particular input state from the register binary value
                // A typical register binary may look like this:
                // B00100100
                // in this case if the right most bit is digital pin 0
                // digital 2 and 5 are high
                // The method below extracts this from the binary value
                //-----------------------------------------------------------------------------------
                #define BIT_TST(REG, bit, val)( ( (REG & (1UL << (bit) ) ) == ( (val) << (bit) ) ) )
                
                //-----------------------------------------------------------------------------------
                // Method detects a pulse, counts it, finds its rate, Class: PulseOutput
                //-----------------------------------------------------------------------------------
                boolean PulseOutput::pulse(int pin, int a, unsigned long timeIn)
                {
                   ld = d;                                    //last digital state = digital state
                   
                   if (BIT_TST(a,pin,1)) d = 1; else d = 0;   //Get current digital state from pin number
                   
                   // if (ld==0 && d==1)                      // no internal pull_up if state changed from 0 to 1: internal pull-up inverts state
                	if (ld==1 && d==0)                         //pull_up f state changed from 0 to 1: internal pull-up inverts state
                   {
                     count++;                                 //count the pulse
                     
                     // Rate calculation
                     lastTime = time;           
                     time = timeIn ;						// correction to allow for processing
                     prate = (time-lastTime);// - 400;          //rate based on last 2 pulses
                                                                //-190 is an offset that may not be needed...??
                     prateAccum += prate - 2000;                     //accumulate rate for average calculation
                     
                     return 1;
                   }
                   return 0;
                }
                
                
                //-----------------------------------------------------------------------------------
                // Method calculates the average rate based on multiple pulses (if there are 2 or more pulses)
                //-----------------------------------------------------------------------------------
                unsigned long PulseOutput::rate(unsigned long timeIn)
                {
                 if (count > 1)
                 {
                   prate = prateAccum / count;                          //Calculate average
                 } else 
                 {
                 
                 if ((timeIn - lastTime)>(prate*2)) prate = 0;}         //Decrease rate if no pulses are received
                                                                        //in the expected time based on the last 
                                                                        //pulse width.
                 return prate; 
                }
                
                 
                
                
                
                
                
                FotoFieberF Offline
                FotoFieberF Offline
                FotoFieber
                Hardware Contributor
                wrote on last edited by
                #17

                @AWI
                Your measurement sketch is really nice. There is one line I do not understand.

                prateAccum += prate - 2000;

                Is this prateAccum needed or couldn't it be left away? What is the meaning of 2000 in this context?

                Cu,
                FotoFieber

                AWIA 1 Reply Last reply
                0
                • FotoFieberF FotoFieber

                  @AWI
                  Your measurement sketch is really nice. There is one line I do not understand.

                  prateAccum += prate - 2000;

                  Is this prateAccum needed or couldn't it be left away? What is the meaning of 2000 in this context?

                  Cu,
                  FotoFieber

                  AWIA Offline
                  AWIA Offline
                  AWI
                  Hero Member
                  wrote on last edited by
                  #18

                  @FotoFieber To be honest .. a left over from some experiments. Just leave it out... you won't notice the difference.

                  M 1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    jeti
                    wrote on last edited by jeti
                    #19

                    @AWI thanks again!
                    I am using your sketches with only one S0 Meter (the 2000pulse/kwh one).
                    *One thing i just found out, that as long as the master arduino is connected to the serial port of my pc it is running fine but when its not, it does not send.I have checked the voltage at the radio and it is the same... I also do not have any display or rotary encoder, as I do the visualisation with FHEM.
                    Do you know why this is the case? * -> Voltage was to low... but the secon question remains:

                    Any idea to use differen pulses/kwh S0 meters? for example one 2000pulse/kwh and one 800 pulse/kwh.
                    thanks in advance!

                    AWIA 1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      marten
                      wrote on last edited by
                      #20

                      Arduino: 1.6.5 (Windows 7), Board:"Arduino Nano, ATmega328"

                      sketch_oct03e:128: error: 'V_TEXT' was not declared in this scope
                      sketch_oct03e.ino: In function 'void setup()':
                      sketch_oct03e:162: error: 'S_INFO' was not declared in this scope
                      sketch_oct03e.ino: In function 'void loop()':
                      sketch_oct03e:337: error: 'V_TEXT' was not declared in this scope
                      sketch_oct03e.ino: In function 'void incomingMessage(const MyMessage&)':
                      sketch_oct03e:364: error: 'V_TEXT' was not declared in this scope
                      'V_TEXT' was not declared in this scope

                      Dit rapport zou meer informatie hebben met
                      "Tijdens de compilatie uitgebreide uitvoer weergeven"
                      ingeschakeld in Bestand > Voorkeuren.

                      M AWIA 2 Replies Last reply
                      0
                      • M marten

                        Arduino: 1.6.5 (Windows 7), Board:"Arduino Nano, ATmega328"

                        sketch_oct03e:128: error: 'V_TEXT' was not declared in this scope
                        sketch_oct03e.ino: In function 'void setup()':
                        sketch_oct03e:162: error: 'S_INFO' was not declared in this scope
                        sketch_oct03e.ino: In function 'void loop()':
                        sketch_oct03e:337: error: 'V_TEXT' was not declared in this scope
                        sketch_oct03e.ino: In function 'void incomingMessage(const MyMessage&)':
                        sketch_oct03e:364: error: 'V_TEXT' was not declared in this scope
                        'V_TEXT' was not declared in this scope

                        Dit rapport zou meer informatie hebben met
                        "Tijdens de compilatie uitgebreide uitvoer weergeven"
                        ingeschakeld in Bestand > Voorkeuren.

                        M Offline
                        M Offline
                        marten
                        wrote on last edited by
                        #21

                        this is what i'll get when trying to upload the master sketch

                        1 Reply Last reply
                        0
                        • M marten

                          Arduino: 1.6.5 (Windows 7), Board:"Arduino Nano, ATmega328"

                          sketch_oct03e:128: error: 'V_TEXT' was not declared in this scope
                          sketch_oct03e.ino: In function 'void setup()':
                          sketch_oct03e:162: error: 'S_INFO' was not declared in this scope
                          sketch_oct03e.ino: In function 'void loop()':
                          sketch_oct03e:337: error: 'V_TEXT' was not declared in this scope
                          sketch_oct03e.ino: In function 'void incomingMessage(const MyMessage&)':
                          sketch_oct03e:364: error: 'V_TEXT' was not declared in this scope
                          'V_TEXT' was not declared in this scope

                          Dit rapport zou meer informatie hebben met
                          "Tijdens de compilatie uitgebreide uitvoer weergeven"
                          ingeschakeld in Bestand > Voorkeuren.

                          AWIA Offline
                          AWIA Offline
                          AWI
                          Hero Member
                          wrote on last edited by AWI
                          #22

                          @marten You need to use the "Development" branch of MySensors until the production version gets updated -or- you can uncomment the lines with "const int ..."

                          // new V_TEXT variable type (development 20150905)
                          //const int V_TEXT = 47 ;
                          // new S_INFO sensor type (development 20150905)
                          //const int S_INFO = 36 ;
                          
                          1 Reply Last reply
                          0
                          • J Offline
                            J Offline
                            jeti
                            wrote on last edited by
                            #23
                            This post is deleted!
                            1 Reply Last reply
                            0
                            • J jeti

                              @AWI thanks again!
                              I am using your sketches with only one S0 Meter (the 2000pulse/kwh one).
                              *One thing i just found out, that as long as the master arduino is connected to the serial port of my pc it is running fine but when its not, it does not send.I have checked the voltage at the radio and it is the same... I also do not have any display or rotary encoder, as I do the visualisation with FHEM.
                              Do you know why this is the case? * -> Voltage was to low... but the secon question remains:

                              Any idea to use differen pulses/kwh S0 meters? for example one 2000pulse/kwh and one 800 pulse/kwh.
                              thanks in advance!

                              AWIA Offline
                              AWIA Offline
                              AWI
                              Hero Member
                              wrote on last edited by
                              #24

                              @jeti as mentioned in a previous post..

                              There are a few ways of getting it changed:

                              You can keep/ leave most as it is and when you send/ or display the values divide the pulses by two and double the Watt values in the routines "LCD_local_display" and "sendPowerUpdate"

                              or: make the necessary calculations when the data comes in. This is a little more complicated in routine "storeMeterJSON" but if you understand the logic (including error corrrection) should be not too hard.

                              I don't have the time at this moment to do it for you...

                              J 1 Reply Last reply
                              0
                              • AWIA AWI

                                @jeti as mentioned in a previous post..

                                There are a few ways of getting it changed:

                                You can keep/ leave most as it is and when you send/ or display the values divide the pulses by two and double the Watt values in the routines "LCD_local_display" and "sendPowerUpdate"

                                or: make the necessary calculations when the data comes in. This is a little more complicated in routine "storeMeterJSON" but if you understand the logic (including error corrrection) should be not too hard.

                                I don't have the time at this moment to do it for you...

                                J Offline
                                J Offline
                                jeti
                                wrote on last edited by
                                #25

                                @AWI: :smiley: nevermind I will start workin on it
                                Thanks again for the great work!

                                J 1 Reply Last reply
                                0
                                • J jeti

                                  @AWI: :smiley: nevermind I will start workin on it
                                  Thanks again for the great work!

                                  J Offline
                                  J Offline
                                  jeti
                                  wrote on last edited by jeti
                                  #26

                                  was not that much work :smiley:
                                  this is the modified master-sketch from AWI i am starting to use. The changes i made:
                                  -deletion of LCD and rotray part
                                  -deletion of accumulation part
                                  -modified meterType to meter800, meter1000 and meter2000 this reflects meters with 800imp/khw;1000imp/kwh;2000imp/kwh

                                  I am using this with only one meter (2000imp/kwh) for now and works pretty nicly second different meter type is on the way.

                                  As I am a beginner please be gentle with comments :-)

                                  
                                  #include <MySensor.h>                   // MySensors network
                                  #include <SPI.h>
                                  #include <Time.h> 
                                  #include <ArduinoJson.h>                // used to parse the simple JSON output of the pulse meter https://github.com/bblanchon/ArduinoJson
                                  
                                  // Constants & globals
                                  const int NO_METERS = 1 ;               // actual meters used (max 12)
                                  const int NODE_ID = 152 ;                // fixed MySensors node ID
                                  
                                  const int JSON_LENGHT = 80 ;            // Maximum json string length
                                  
                                  // new V_TEXT variable type (development 20150905)
                                  const int V_TEXT = 47 ;
                                  // new S_INFO sensor type (development 20150905)
                                  const int S_INFO = 36 ;
                                  
                                  char lastLCD1[21] = "--                  "; // LCD message line
                                  
                                  typedef enum meterTypes: int8_t {meter800, meter1000, meter2000} ;             // metertype meter800, meter1000, meter2000; 
                                  const char METER_NAMES[NO_METERS][4] = {"PC"} ; // meter names
                                  const meterTypes METER_TYPES[NO_METERS] = {meter2000};
                                  
                                  const unsigned long idleTime = 10000 ;  // Delay time for any of the states to return to idle
                                  unsigned long idleTimer ;               // Delay timer for idleTime
                                  
                                  
                                  
                                  union {                                 // used to convert long to bytes for EEPROM storage
                                      long kWhLongInt;
                                      uint8_t kWhLongByte[4];
                                      } kWhLong ;
                                  
                                  
                                  // Possible states for the state machine.
                                  // Idle: default state, show totals for in/out nett
                                  // Browse: dive into meter details 
                                  // Update: update meter value (Wh total)
                                  // Reset: reset day values
                                  enum States: int8_t {IDLE, BROWSE, UPDATE, RST} ;
                                  uint8_t State = IDLE;                   // current state machine state
                                  
                                  // meter class, store all relevant meter data (equivalent to struct)
                                  class pulseMeter              
                                  {
                                  public:                                  
                                      long UsageWh;                       // last (current) usage (in W) from pulse counter
                                      long UsageAccumWh;                  // usage accumulator (to keep in sync) from pulse counter
                                      long PowerW;                        // actual power, calculated from pulse "rate"
                                      long DayUsageWh;                    // daily usage for display
                                      meterTypes Type;                    // metertype for addition in totals: meter800, meter1000, meter2000; 
                                      char Name[4] ;                      // meter name for display
                                  };
                                  pulseMeter pulseMeters[NO_METERS] ;     // define power meters
                                  //pulseMeter meter800, meter1000, meter2000; //  pulse/kWh
                                  unsigned long tempUsageWh ;             // temporary store while manually updating (state UPDATE) 
                                  
                                  // Json parser:  define parse object: <10> = number of tokens in JSON: ~10 per m (4 * [key, value] + key_total, value_total))
                                  // example: "{\"m\":1,\"c\":12,\"r\":120000,\"cA\":12345}"
                                  char json[JSON_LENGHT] ;        // Storage for serial JSON string (init for example)
                                  
                                  // flags & counters 
                                  bool timeReceived = false;              // controller time
                                  bool newDay = false;                    // reset at 00:00:00
                                  unsigned long lastUpdate=0, lastRequest=0, lastDisplay=0, lastSyncKWH=0;  // loop timers for once in while events
                                  int updateMeter = 0;                    // current meter for update
                                  bool updateDisplayFlag = true ;         // indicate that display needs to be updated
                                  int currentMeter = 0;                   // active meter for update & check, cycles through meters (0..NO_METERS-1)
                                  int lastRotary = 0;                     // last rotary encoder position
                                  int updateIncrement = 1000 ;            // Interval multiplier for Update 
                                  int errCount = 0 ;                      // error counter
                                  // *** Definition and initialisation
                                  // define the MySensor network
                                  MySensor gw;                            // pins used RFX24(default 9,10)
                                      
                                  // Initialize messages for sensor network
                                  MyMessage powerMsg(0,V_WATT);           // message to send power in W
                                  MyMessage usageMsg(0,V_KWH);            // message to send usage in kWH
                                  MyMessage textMsg(0,V_TEXT);            // message to send/receive text
                                  
                                  
                                  
                                  // function to reset the Arduino (jump to 0 address)
                                  void(* resetFunc) (void) = 0;//declare reset function at address 0
                                  
                                  void setup(void)
                                  {
                                      gw.begin(incomingMessage, NODE_ID, false);              // this node is fixed, no repeat
                                      //Send the sensor node sketch version information to the gateway
                                      gw.sendSketchInfo("AWI-12ChannelPulse", "2.0");
                                      // Initialize the meter names
                                      
                                      // Register all Pulse counters to gw (they will be created as child devices from 0 to MAX-1)
                                      for (int x = 0; x < NO_METERS; x++){ 
                                          gw.present(x, S_POWER, METER_NAMES[x]);             // present power meters to gateway
                                          delay(10);                                          // give it some time to process
                                          }
                                      
                                      delay(100);
                                  
                                      
                                      for (int x = 0; x < NO_METERS; x++){                    // initialize previous kWh values from EEPROM and init
                                          for (int y = 0; y < 4 ; y++){                       // convert from bytes
                                              kWhLong.kWhLongByte[y]= gw.loadState(x *4 + y) ;// EEPROM position = meter number * 4 bytes
                                              }                                               // controller is updated later automatically
                                          pulseMeters[x].UsageWh = kWhLong.kWhLongInt;
                                          strcpy(pulseMeters[x].Name, METER_NAMES[x] );       // copy string for meter names
                                          pulseMeters[x].Type = METER_TYPES[x];               // Set type
                                          }
                                   }
                                  
                                  void loop(void)
                                  {
                                      // Before specific states, perform generic tasks
                                      unsigned long now = millis();                           // Timer in loop for "once in a while" events
                                      gw.process() ;                                          // process incoming messages
                                      // If no time has been received yet, request it every 10 second from controller
                                      if ((!timeReceived && (now-lastRequest > 10*1000)) ||   
                                          (now-lastRequest > 3600000UL)){                     // request update every hour to keep in sync
                                          Serial.println(F("requesting time"));               // Request time from controller. 
                                          timeReceived = false;
                                          gw.requestTime(receiveTime);  
                                          lastRequest = now;
                                      }
                                      // Check if new day has started (hour == 0) and reset day usage counters of meters
                                      if (hour()==0 && !newDay){
                                          newDay = true;
                                          for (int x = 0; x < NO_METERS; x++){ 
                                              pulseMeters[x].DayUsageWh = 0 ;                 // reset daily counters
                                              saveMeters(x);                                  // save meter values to EEPROM
                                          }   
                                      } else if(hour() != 0 && newDay)                        // reset newday flag if hour != 0
                                          { newDay = false;}
                                       
                                      // Every 10 seconds update one meter to controller to avoid traffic jams
                                      if (now-lastSyncKWH > 10000){
                                      //    printPulsemeter(updateMeter);
                                          sendPowerUpdate(updateMeter);                               // update the values for currentMeter
                                          updateMeter++ ;
                                          if (updateMeter >= NO_METERS){                              // increment and wrap current meter
                                              updateMeter = 0 ;}
                                          lastSyncKWH = now ;
                                          }
                                          
                                      // Update sensors every 10 secs
                                      if (now-lastUpdate > 10000) {
                                          // get values to be displayed from controller
                                          
                                          lastUpdate = now;
                                      }
                                      
                                      // get readings from serial (sent every 10s)
                                      // format {"m":meter,"c":count,"r":rate, "cA":countAccum}
                                      // use JSON parser to process (could be replaced by simple split routine, but this works just fine)
                                      if(readLineJSON(Serial.read(), json, JSON_LENGHT) > 0 ){        //dummySerial(), Serial.read()
                                      // if(readLineJSON(dummySerial(), json, 80) > 0 ){              //dummySerial(), Serial.read()
                                          Serial.println(json);
                                          storeMeterJSON(json);                                       //store the meter reading
                                          //calcMeterTotals();                                          // update totals
                                          }
                                  }
                                  
                                  // This is called when a new time value was received
                                  void receiveTime(unsigned long controllerTime) {
                                      // Ok, set incoming time 
                                      Serial.print(F("Time value received: "));
                                      Serial.println(controllerTime);
                                      setTime(controllerTime);                                        // set the clock to the time from controller
                                      timeReceived = true ;
                                  }
                                  
                                  // This is called when a message is received 
                                  void incomingMessage(const MyMessage &message) {
                                    // Expect few types of messages from controller, V_VAR1 for messages
                                      if (message.type==V_TEXT) {
                                          // if message comes in, update the kWH reading for meter with value since last update
                                          // Write some debug info
                                          //Serial.print("Last reading for sensor: ");
                                          //Serial.print(message.sensor);                
                                          //Serial.print(", Message: ");
                                          //Serial.println(message.getString());
                                  
                                          }
                                      }
                                  
                                  
                                  // save Meter to EEPROM when needed
                                  void saveMeters(int8_t meterNo){
                                      kWhLong.kWhLongInt = pulseMeters[meterNo].UsageWh ;                     // convert to separate bytes via struct
                                      for (int y = 0; y < 4 ; y++){
                                          gw.saveState(meterNo * 4 + y, kWhLong.kWhLongByte[y])  ;            // EEPROM position = meter number * 4 bytes
                                          }
                                      }
                                  
                                  void sendPowerUpdate(int meterNo)
                                  // Sends update to controller for current meter 
                                  {
                                      gw.send(powerMsg.setSensor(meterNo).set((long)pulseMeters[meterNo].PowerW));            // meterNo * 100 ));
                                      gw.send(usageMsg.setSensor(meterNo).set((float)pulseMeters[meterNo].UsageWh/1000L ,3)); // send in kWh!
                                  }
                                  
                                  int storeMeterJSON(char *json)
                                  /* convert JSON to values and store in corresponding meter (if used)
                                   input: JSON string (can be wrong formatted), with length
                                   output: changed meter record number or -1 if error
                                   use JsonParser 
                                  */
                                  {
                                    StaticJsonBuffer<50> jsonBuffer;                          // 4 object  -> 4 + 4*10 = 44
                                    // char njson[] = "{\"m\":1,\"c\":12,\"r\":120000,\"cA\":12345}";
                                      JsonObject& root = jsonBuffer.parseObject(json);
                                    if (!root.success())
                                      {
                                          Serial.println(F("JsonParser.parse() failed"));
                                          errCount++ ;
                                          return -1;
                                      }
                                    int m = (long)root["m"];
                                    if (m > NO_METERS){                                       // meter value out of range for used meters (m starts at 1)
                                      return -1 ;
                                    } else {                                                  // update meter values, Power is momentary, Usage is cumulative
                                      long newAccumWh = (long)root["cA"] ;
                                      long newWh = (long)root["c"] ;
                                      long diffAccumWh = newAccumWh - pulseMeters[m-1].UsageAccumWh;  // check for missed pulses by comparing cA with last stored value
                                      if (diffAccumWh >= newWh){                              // no difference or missed pulses -> correct: add difference
                                          pulseMeters[m-1].UsageWh += diffAccumWh;
                                          pulseMeters[m-1].DayUsageWh += diffAccumWh;
                                          }
                                      else {                                                  // negative diff, out of sync -> add pulses only (can be out of range or restart)
                                          pulseMeters[m-1].UsageWh += newWh;
                                          pulseMeters[m-1].DayUsageWh += newWh;
                                          }
                                      pulseMeters[m-1].UsageAccumWh = newAccumWh;             // always update sync counter (only for sync and error correction(serial))
                                      if ((long)root["r"] == 0){                              // calculate power from pulse rate (ms) and truncate to whole Watts
                                        pulseMeters[m-1].PowerW = 0;                          // if overflow assume no Usage
                                      } else if (pulseMeters[m-1].Type == meter800){
                                        pulseMeters[m-1].PowerW = long( 3600000000L / (long)root["r"]*0.8); // rate in microseconds for 800 pulse/kWh
                                        }
                                        else if (pulseMeters[m-1].Type == meter1000){
                                        pulseMeters[m-1].PowerW = long( 3600000000L / (long)root["r"]); // rate in microseconds for 1000 pulse/kWh
                                        }
                                         else if (pulseMeters[m-1].Type == meter2000){
                                         pulseMeters[m-1].PowerW = long( 3600000000L / (long)root["r"]/2); // rate in microseconds for 2000 pulse/kWh
                                        }
                                        else {
                                          Serial.println("geht nicht");
                                          }
                                      return m ;
                                    }
                                  }
                                  
                                  int readLineJSON(int readch, char *buffer, int len)
                                  /* checks for JSON and when started append char tot buffer and checks for line completion 
                                  usage:
                                    static char buffer[80];
                                    if (readline(Serial.read(), buffer, 80) > 0) { // line complete}
                                    returns simple JSON
                                    */
                                  {
                                    static int pos = 0;
                                    int rpos;
                                  
                                    if (readch > 0) {
                                      switch (readch) {
                                        case '\n':                // Ignore new-lines
                                          break;
                                        case '\r':                // Return on CR
                                          rpos = pos;
                                          pos = 0;                  // Reset position index ready for next time
                                          return rpos;
                                        default:
                                          if (pos < len-1) {
                                            buffer[pos++] = readch;
                                            buffer[pos] = 0;
                                          }
                                      }
                                    }
                                    // No end of line has been found, so return -1.
                                    return -1;
                                  }
                                  
                                  /*
                                  int dummySerial()
                                  // Acts as a dummy JSON serial character generator for debugging
                                  // input: none
                                  // output: preset JSON string
                                  {
                                    static int pos = 0;
                                    char json[] = "{\"m\":1,\"c\":12,\"r\":120000,\"cA\":12345}\r{\"m\":2,\"c\":212,\"r\":2120000,\"cA\":212345}\r{\"m\":3,\"c\":212,\"r\":2120000,\"cA\":212345}\n\r";
                                    if (pos++ >= strlen(json)){
                                      pos = 0;
                                    } 
                                    return json[pos] ;
                                    
                                  }
                                  */
                                  
                                  
                                  /*
                                  
                                  void printPulsemeter(int meter)
                                  // prints the Pulsemeter record to serial out
                                  {
                                    Serial.print("m:");
                                    Serial.print(meter);
                                    Serial.print("type:");
                                    Serial.print(pulseMeters[meter].Type);
                                    Serial.print(", power: ");
                                    Serial.print(pulseMeters[meter].PowerW);
                                    Serial.print(", usage: ");
                                    Serial.print(pulseMeters[meter].UsageWh);
                                    Serial.print(", day usage: ");
                                    Serial.println(pulseMeters[meter].DayUsageWh );
                                  //  Serial.print(", Ca: ");
                                  //  Serial.println(pulseMeters[meter].UsageAccumWh);
                                  }
                                  */
                                  
                                  1 Reply Last reply
                                  0
                                  • M Offline
                                    M Offline
                                    MarkV
                                    wrote on last edited by
                                    #27

                                    Good evening,

                                    After a couple of weeks, again i'm busy with my arduino's, but now i have a rasberry with domoticz near my arduino, so i don't need to send it wireless.
                                    Is there a possibility to connect the master or slave arduino directly to my rasberry and read out the pulse meters???

                                    1 Reply Last reply
                                    0
                                    • mfalkviddM Offline
                                      mfalkviddM Offline
                                      mfalkvidd
                                      Mod
                                      wrote on last edited by
                                      #28

                                      With MySensors version 1.6 (currently in development) you can connect the Arduino to the Raspberry Pi's USB port using a FTDI or CH340G. That type of connection is called a serial gateway. Before 1.6, the gateways do not support local sensors.

                                      1 Reply Last reply
                                      0
                                      • M Offline
                                        M Offline
                                        MarkV
                                        wrote on last edited by MarkV
                                        #29

                                        So with 1.6 i can install the master software and connect my arduino master directly through usb without the rf24''s? ?

                                        1 Reply Last reply
                                        0
                                        • mfalkviddM Offline
                                          mfalkviddM Offline
                                          mfalkvidd
                                          Mod
                                          wrote on last edited by
                                          #30

                                          I am not entirely sure what a master is, but yes, I think you can.

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          15

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.1k

                                          Posts


                                          Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • MySensors
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular