Skip to content
  • 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. General Discussion
  3. ISR Pulse Meter Question
  • Getting Started
  • Controller
  • Build
  • Hardware
  • Download/API
  • Forum
  • Store

ISR Pulse Meter Question

Scheduled Pinned Locked Moved General Discussion
12 Posts 4 Posters 1.1k Views 2 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.
  • mfalkviddM mfalkvidd

    @killerfreek welcome to the forum :-)
    attachinterrupt connects the ISR with the interrupt. Sleep is called without interrupt, so sleep will not return until the set amount of time.

    It is possible to call sleep so it wakes up for every pulse. See https://www.mysensors.org/download/sensor_api_20#sleeping for documentation.

    K Offline
    K Offline
    killerfreek
    wrote on last edited by
    #3

    @mfalkvidd Many thanks!

    1 Reply Last reply
    1
    • B Offline
      B Offline
      barrydou
      wrote on last edited by barrydou
      #4

      Hello

      I'm asking exactly the same question.
      I mixed this sketch with another one for battery measurement (and added fonction to resend last volume for updating domoticz, software debounce, but that's not the main point).

      Each time I have a pulse, the loop start again, even if it was sleeping.

      I have also tried this simple code

      
      // Enable debug prints to serial monitor
      #define MY_DEBUG
      
      // Enable and select radio type attached
      #define MY_RADIO_RF24
      
      #include <MySensors.h>
      
      #define DIGITAL_INPUT_SENSOR 3                  // The digital input you attached your sensor.  (Only 2 and 3 generates interrupt!)
      
      #define CHILD_ID 1                              // Id of the sensor child
      
      unsigned long SEND_FREQUENCY =  60000;           // Minimum time between send (in milliseconds). We don't want to spam the gateway.
      
      volatile uint32_t pulseCount = 0;
      uint32_t oldPulseCount = 0;
      
      
      
      void setup()
      {
        // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion)
        pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP);
        pulseCount = oldPulseCount = 0;
        attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, FALLING);
      }
      
      void presentation()
      {
        // Send the sketch version information to the gateway and Controller
        sendSketchInfo("TEST", "1.1");
        // Register this device as Water flow sensor
        present(CHILD_ID, S_GAS);
      }
      
      void loop()
      {
      
        // Pulse count has changed
        if ((pulseCount != oldPulseCount)) {
          oldPulseCount = pulseCount;
      
          Serial.print("pulsecount:");
          Serial.println(pulseCount);
        } else {
          Serial.println("pulsecount not changed");
      
        }
      
        sleep(SEND_FREQUENCY);
      
      }
      
      void onPulse()
      {
        pulseCount++;
      }
      
      

      And here is the log

      18:33:44.593 -> 3229 MCO:BGN:INIT OK,TSP=1
      18:33:44.593 -> pulsecount not changed
      18:33:44.593 -> 3233 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
      18:33:44.593 -> 3239 TSF:TDI:TSL
      18:34:48.589 -> 3241 MCO:SLP:WUP=-1
      18:34:48.589 -> 3244 TSF:TRI:TSB
      18:34:48.635 -> pulsecount not changed
      18:34:48.635 -> 3250 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
      18:34:48.635 -> 3258 TSF:TDI:TSL
      18:34:57.719 -> 3260 MCO:SLP:WUP=-1
      18:34:57.719 -> 3262 TSF:TRI:TSB
      18:34:57.763 -> pulsecount:159
      18:34:57.763 -> 3270 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
      18:34:57.763 -> 3276 TSF:TDI:TSL
      18:34:58.212 -> 3280 MCO:SLP:WUP=-1
      18:34:58.212 -> 3282 TSF:TRI:TSB
      18:34:58.212 -> pulsecount:364
      18:34:58.212 -> 3289 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
      18:34:58.212 -> 3295 TSF:TDI:TSL
      18:35:04.813 -> 3299 MCO:SLP:WUP=-1
      18:35:04.813 -> 3301 TSF:TRI:TSB
      18:35:04.813 -> pulsecount:380
      18:35:04.813 -> 3307 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
      18:35:04.861 -> 3313 TSF:TDI:TSL
      18:35:05.211 -> 3315 MCO:SLP:WUP=-1
      18:35:05.211 -> 3319 TSF:TRI:TSB
      18:35:05.211 -> pulsecount:394
      18:35:05.211 -> 3325 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
      18:35:05.211 -> 3332 TSF:TDI:TSL
      18:35:10.827 -> 3334 MCO:SLP:WUP=-1
      18:35:10.827 -> 3336 TSF:TRI:TSB
      18:35:10.827 -> pulsecount:402
      18:35:10.827 -> 3344 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
      18:35:10.827 -> 3350 TSF:TDI:TSL
      18:36:14.864 -> 3352 MCO:SLP:WUP=-1
      18:36:14.864 -> 3354 TSF:TRI:TSB
      18:36:14.864 -> pulsecount not changed
      18:36:14.864 -> 3360 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
      18:36:14.864 -> 3368 TSF:TDI:TSL
      

      As you can see with timestamp, you don't get value every minute, but every minute AND each time ISR is run. The main loop continue don't wait the end of the time to continue. What do I miss ?

      Thank you for your help

      mfalkviddM 1 Reply Last reply
      0
      • B barrydou

        Hello

        I'm asking exactly the same question.
        I mixed this sketch with another one for battery measurement (and added fonction to resend last volume for updating domoticz, software debounce, but that's not the main point).

        Each time I have a pulse, the loop start again, even if it was sleeping.

        I have also tried this simple code

        
        // Enable debug prints to serial monitor
        #define MY_DEBUG
        
        // Enable and select radio type attached
        #define MY_RADIO_RF24
        
        #include <MySensors.h>
        
        #define DIGITAL_INPUT_SENSOR 3                  // The digital input you attached your sensor.  (Only 2 and 3 generates interrupt!)
        
        #define CHILD_ID 1                              // Id of the sensor child
        
        unsigned long SEND_FREQUENCY =  60000;           // Minimum time between send (in milliseconds). We don't want to spam the gateway.
        
        volatile uint32_t pulseCount = 0;
        uint32_t oldPulseCount = 0;
        
        
        
        void setup()
        {
          // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion)
          pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP);
          pulseCount = oldPulseCount = 0;
          attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, FALLING);
        }
        
        void presentation()
        {
          // Send the sketch version information to the gateway and Controller
          sendSketchInfo("TEST", "1.1");
          // Register this device as Water flow sensor
          present(CHILD_ID, S_GAS);
        }
        
        void loop()
        {
        
          // Pulse count has changed
          if ((pulseCount != oldPulseCount)) {
            oldPulseCount = pulseCount;
        
            Serial.print("pulsecount:");
            Serial.println(pulseCount);
          } else {
            Serial.println("pulsecount not changed");
        
          }
        
          sleep(SEND_FREQUENCY);
        
        }
        
        void onPulse()
        {
          pulseCount++;
        }
        
        

        And here is the log

        18:33:44.593 -> 3229 MCO:BGN:INIT OK,TSP=1
        18:33:44.593 -> pulsecount not changed
        18:33:44.593 -> 3233 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
        18:33:44.593 -> 3239 TSF:TDI:TSL
        18:34:48.589 -> 3241 MCO:SLP:WUP=-1
        18:34:48.589 -> 3244 TSF:TRI:TSB
        18:34:48.635 -> pulsecount not changed
        18:34:48.635 -> 3250 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
        18:34:48.635 -> 3258 TSF:TDI:TSL
        18:34:57.719 -> 3260 MCO:SLP:WUP=-1
        18:34:57.719 -> 3262 TSF:TRI:TSB
        18:34:57.763 -> pulsecount:159
        18:34:57.763 -> 3270 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
        18:34:57.763 -> 3276 TSF:TDI:TSL
        18:34:58.212 -> 3280 MCO:SLP:WUP=-1
        18:34:58.212 -> 3282 TSF:TRI:TSB
        18:34:58.212 -> pulsecount:364
        18:34:58.212 -> 3289 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
        18:34:58.212 -> 3295 TSF:TDI:TSL
        18:35:04.813 -> 3299 MCO:SLP:WUP=-1
        18:35:04.813 -> 3301 TSF:TRI:TSB
        18:35:04.813 -> pulsecount:380
        18:35:04.813 -> 3307 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
        18:35:04.861 -> 3313 TSF:TDI:TSL
        18:35:05.211 -> 3315 MCO:SLP:WUP=-1
        18:35:05.211 -> 3319 TSF:TRI:TSB
        18:35:05.211 -> pulsecount:394
        18:35:05.211 -> 3325 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
        18:35:05.211 -> 3332 TSF:TDI:TSL
        18:35:10.827 -> 3334 MCO:SLP:WUP=-1
        18:35:10.827 -> 3336 TSF:TRI:TSB
        18:35:10.827 -> pulsecount:402
        18:35:10.827 -> 3344 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
        18:35:10.827 -> 3350 TSF:TDI:TSL
        18:36:14.864 -> 3352 MCO:SLP:WUP=-1
        18:36:14.864 -> 3354 TSF:TRI:TSB
        18:36:14.864 -> pulsecount not changed
        18:36:14.864 -> 3360 MCO:SLP:MS=60000,SMS=0,I1=255,M1=255,I2=255,M2=255
        18:36:14.864 -> 3368 TSF:TDI:TSL
        

        As you can see with timestamp, you don't get value every minute, but every minute AND each time ISR is run. The main loop continue don't wait the end of the time to continue. What do I miss ?

        Thank you for your help

        mfalkviddM Offline
        mfalkviddM Offline
        mfalkvidd
        Mod
        wrote on last edited by
        #5

        @barrydou my guess is that the interrupt causes the sleep function to believe that 8 seconds has passed (which is the maximum time for the watchdog), so it deducts 8 seconds for each pulse.

        1 Reply Last reply
        0
        • B Offline
          B Offline
          barrydou
          wrote on last edited by
          #6

          Hi

          Thank you for your response.

          Does it means that if I sleep longer, 300 sec for example, and I debounce the switch on interrupt not get a huge increase on a single event, It will sleep 300sec with no pulse, 292 sec with one pule, 284 sec for two pulse (and so on :) )?

          Thank you again for your help and explanation

          mfalkviddM 1 Reply Last reply
          0
          • B barrydou

            Hi

            Thank you for your response.

            Does it means that if I sleep longer, 300 sec for example, and I debounce the switch on interrupt not get a huge increase on a single event, It will sleep 300sec with no pulse, 292 sec with one pule, 284 sec for two pulse (and so on :) )?

            Thank you again for your help and explanation

            mfalkviddM Offline
            mfalkviddM Offline
            mfalkvidd
            Mod
            wrote on last edited by mfalkvidd
            #7

            @barrydou almost. The sleep function will set the watchdog to 8 seconds and power down the node. When the node is woken up, sleep will assume that 8 seconds has passed.

            If the interrupt happens 7.999 seconds after the node powered down, assuming 8 seconds will yield an error of 0.001 seconds.

            If the interrupt happens 0.2 seconds after the node powered down, assuming 8 seconds will yield an error of 7.8 seconds.

            So it depends on how quickly the interrupts come. In your log you had about 16 pulses per second. That should yield an error of 8-1/16 seconds which is 7.9375 per pulse.

            1 Reply Last reply
            0
            • B Offline
              B Offline
              barrydou
              wrote on last edited by
              #8

              Ok thank you very much for all the informations.

              The high rate of interrupts is due to the way I generate the interrupt for the test : with a breadboard jumper manually connected on the pin, so it generates a lot of bounces.

              In a normal behaviour, I will have a reed switch for my gas counter. So it should not occur so much.

              I have not realised that the sleep function "hide" WDT for sleeping (but it's quite logic).
              In fact, in my example, my high rate of interrupts causes the loop to start again. With one event and 6 bounces (so 7 interrupts), the wait period is considered elapsed, even if it was sleeping only from a few seconds.

              I never realised that before :)

              zboblamontZ 1 Reply Last reply
              0
              • B barrydou

                Ok thank you very much for all the informations.

                The high rate of interrupts is due to the way I generate the interrupt for the test : with a breadboard jumper manually connected on the pin, so it generates a lot of bounces.

                In a normal behaviour, I will have a reed switch for my gas counter. So it should not occur so much.

                I have not realised that the sleep function "hide" WDT for sleeping (but it's quite logic).
                In fact, in my example, my high rate of interrupts causes the loop to start again. With one event and 6 bounces (so 7 interrupts), the wait period is considered elapsed, even if it was sleeping only from a few seconds.

                I never realised that before :)

                zboblamontZ Offline
                zboblamontZ Offline
                zboblamont
                wrote on last edited by
                #9

                @barrydou I admit confusion, it sounds as if your objective is to derive a flow rate at the gas meter, which you will then pass to Domoticz, but puzzled why? Process monitoring rather than domestic consumption?
                An RTC is the only sure way to get time accuracy, but a standard domestic gas meter reed pulses every 10 litres.
                I just checked Domoticz log on a heating cycle, fastest single pulse would be somewhere around 21 secs, but this Node only sends in every 5 pulses to extend battery life.
                The sketch used here sleeps the loop indefinitely (sleep=0) until triggered by the Reed.
                One caution - I got crazy readings initially despite a debounce circuit, and eventually found the reed closes ca 5 seconds on a typical run, solved by a subroutine check for reed reset before going to sleep.
                The physical and Domoticz meters are still in perfect sync, and the Node on the same 2AA after well over a year. I might go back to single pulses later for greater accuracy, but only out of curiosity.
                The standard Domoticz Gas Meter groups readings into hourly and daily totals. For your own puzzle, the readings come in on timestamps, so perhaps NodeRed might be an alternative way to go to derive a flow rate...

                1 Reply Last reply
                1
                • B Offline
                  B Offline
                  barrydou
                  wrote on last edited by barrydou
                  #10

                  No no, my intention is just to send the pulse count, every 10 or 15 minutes, with battery powered sensor (and resend the last value even if it not change, due to domoticz not reporting heartbeat, but that is another story :) )

                  Hourly and daily value are ok for me.

                  I was using this sketch as an example just to see how it work and if it could directly do the job.
                  I enabled sleep_mode.
                  I was doing that with a testing arduino, directly connected to radio with jumper, and using jumper to simulate reed.
                  Each time I was doing a pulse that way, the node send the information directly. I was not understanding why. So I run a minimal sketch to try to understand, and I found this thread ...

                  Finally with all those informations, i think i'll do something like that:

                  • The loop sleeps for 1 minute, or for the reed interrupt.
                  • When the loop restart, it checked if the reed interrupt occured with the return value of sleep
                    -- if yes, it increments pulse count, waits a few ms for debounce, and continues
                    -- if no it continues
                  • every 10 loops, a msg is send with the pulse count
                  • every 60 loops, the battery level is checked
                  • and then it sleeps again for 1 minute or if the reed interrupt occurs

                  Thank you again for this great help

                  zboblamontZ 1 Reply Last reply
                  1
                  • B barrydou

                    No no, my intention is just to send the pulse count, every 10 or 15 minutes, with battery powered sensor (and resend the last value even if it not change, due to domoticz not reporting heartbeat, but that is another story :) )

                    Hourly and daily value are ok for me.

                    I was using this sketch as an example just to see how it work and if it could directly do the job.
                    I enabled sleep_mode.
                    I was doing that with a testing arduino, directly connected to radio with jumper, and using jumper to simulate reed.
                    Each time I was doing a pulse that way, the node send the information directly. I was not understanding why. So I run a minimal sketch to try to understand, and I found this thread ...

                    Finally with all those informations, i think i'll do something like that:

                    • The loop sleeps for 1 minute, or for the reed interrupt.
                    • When the loop restart, it checked if the reed interrupt occured with the return value of sleep
                      -- if yes, it increments pulse count, waits a few ms for debounce, and continues
                      -- if no it continues
                    • every 10 loops, a msg is send with the pulse count
                    • every 60 loops, the battery level is checked
                    • and then it sleeps again for 1 minute or if the reed interrupt occurs

                    Thank you again for this great help

                    zboblamontZ Offline
                    zboblamontZ Offline
                    zboblamont
                    wrote on last edited by
                    #11

                    @barrydou Ok, went through much the same head-scratching, even if I still didn't fully understand the detail then, it pretty much worked.
                    There really is no need to insert a time element, Domoticz makes 5 minute accumulations then hourly then daily.
                    If you leave the loop to ONLY activate on a reed pulse, send in after X pulses (if you wish), and send in battery after YxX pulses, you should be good to go with long battery life.
                    Only issue I fell over was holding the reading originally as an INT caused chaos in Domoticz when it rolled over to a minus.
                    From memory changing it to a LONG worked but left trailing digits on the live meter update in Domoticz, but I ignored them anyway. One day I might look at it again, but it accurately records otherwise.

                    Looked back for the sketch, it is so early in the learning curve the sketch name doesn't bear the Node Number like the rest.

                    #include <T2WhisperNode.h>
                    
                    /**
                     * The MySensors Arduino library handles the wireless radio link and protocol
                     * between your home built sensors/actuators and HA controller of choice.
                     * The sensors forms a self healing radio network with optional repeaters. Each
                     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
                     * network topology allowing messages to be routed to nodes.
                     *
                     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
                     * Copyright (C) 2013-2015 Sensnology AB
                     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
                     *
                     * Documentation: http://www.mysensors.org
                     * Support Forum: http://forum.mysensors.org
                     *
                     * This program is free software; you can redistribute it and/or
                     * modify it under the terms of the GNU General Public License
                     * version 2 as published by the Free Software Foundation.
                     *
                     *******************************
                     *
                     * DESCRIPTION
                     *
                     * Interrupt driven binary switch example with dual interrupts
                     * Author: Patrick 'Anticimex' Fallberg
                     * Connect one button or door/window reed switch between
                     * digitial I/O pin 3 (BUTTON_PIN below) and GND and the other
                     * one in similar fashion on digital I/O pin 2.
                     * This example is designed to fit Arduino Nano/Pro Mini
                     *
                     */
                    
                    #include <MyConfig.h>
                    // Enable debug prints to serial monitor
                    //#define MY_DEBUG //Comment out once all working saving memory
                    
                    // Enable and select radio type attached
                    ////#define MY_RADIO_NRF24
                    #define MY_RADIO_RFM69
                    #define MY_RFM69_FREQUENCY RF69_433MHZ  // Define for frequency setting. Needed if you're radio module isn't 868Mhz (868Mhz is default in lib)
                    
                    #define MY_RFM69_NETWORKID 101  // Default is 100 in lib. Uncomment it and set your preferred network id if needed
                    #define MY_NODE_ID 4  //Manually set the node ID here. Comment out to auto assign
                    //A define should be added to provide minimum power output to provide decent RSSI to the Gateway if ATC not available
                    #include <SPI.h>
                    #include <MySensors.h>
                    #define SN "Gas"
                    #define SV "1"
                    #define FIRST_CHILD_ID 1
                    //#define SECOND_CHILD_ID 2
                    #define THIRD_CHILD_ID 3
                    #define REED_PIN 3   // Arduino Digital I/O pin for button/reed switch
                    #define BatteryOn 14
                    #define BatteryIn A6
                    
                    
                    // Change to V_LIGHT if you use S_LIGHT in presentation below
                    MyMessage msg(FIRST_CHILD_ID, V_VOLUME);
                    //MyMessage msg2(SECOND_CHILD_ID, V_VOLUME);
                    MyMessage msg3(THIRD_CHILD_ID, V_VOLTAGE);
                    
                    int GasCycle=0;
                    int batteryread=0;
                    long gasunit=906867L;
                    
                    unsigned long SLEEP_TIME = 0; // Sleep time between reports (in milliseconds)
                    
                    void setup(){
                      // Setup the buttons
                     pinMode(REED_PIN, INPUT);
                     pinMode(BatteryOn, OUTPUT);
                     pinMode(BatteryIn, INPUT);
                     analogReference(INTERNAL);
                    }
                    
                    void presentation(){
                      // Send the sketch version information to the gateway and Controller
                      sendSketchInfo(SN, SV);
                    
                      // Register binary input sensor to sensor_node (they will be created as child devices)
                      // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage.
                      // If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
                      present(FIRST_CHILD_ID, S_GAS);
                    //  present(SECOND_CHILD_ID, S_GAS);
                      present(THIRD_CHILD_ID, S_MULTIMETER);
                    }
                    
                    // Loop will respond then wait for interrupt to reloop
                    void loop(){ //Wait for Reed to release from closed
                      while(digitalRead(REED_PIN)==LOW){
                        sleep(1000);
                      }
                      
                      //Battery Read
                     if(batteryread==0){
                      digitalWrite(BatteryOn, HIGH);
                      int voltread = analogRead(BatteryIn);
                      float voltage = (7.272 * voltread) / 1024;
                      sleep(5);
                      digitalWrite(BatteryOn, LOW);
                      send(msg3.set(voltage,2));
                      batteryread=-100; 
                      sleep(50);
                    }
                    
                     //Increment variables
                      batteryread++;
                    //  gastotal++;
                      gasunit++;
                      GasCycle++;
                     
                    
                      if(GasCycle>=5){
                        // Short delay to allow setup to properly settle
                      sleep(5);
                        send(msg.set(gasunit));
                    //    send(msg2.set(gastotal));
                     sleep(100);
                     GasCycle=0;
                     }
                     sleep(100);// Time to settle down
                      // Sleep until something happens with the sensor
                      sleep(digitalPinToInterrupt(REED_PIN),LOW, SLEEP_TIME);
                    
                    }
                    

                    It still needs tidied, but butcher away with it if it helps. Good luck ;)

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      barrydou
                      wrote on last edited by
                      #12

                      Hello

                      Here is my last code for my gas meter. If it could help somebody

                      /*
                       * The MySensors Arduino library handles the wireless radio link and protocol
                       * between your home built sensors/actuators and HA controller of choice.
                       * The sensors forms a self healing radio network with optional repeaters. Each
                       * repeater and gateway builds a routing tables in EEPROM which keeps track of the
                       * network topology allowing messages to be routed to nodes.
                       *
                       * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
                       * Copyright (C) 2013-2018 Sensnology AB
                       * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
                       *
                       * Documentation: http://www.mysensors.org
                       * Support Forum: http://forum.mysensors.org
                       *
                       * This program is free software; you can redistribute it and/or
                       * modify it under the terms of the GNU General Public License
                       * version 2 as published by the Free Software Foundation.
                       *
                       *******************************
                       *
                       * REVISION HISTORY
                       * Version 1.0 - Henrik Ekblad
                       * Version 1.1 - GizMoCuz
                       *
                       * DESCRIPTION
                       * Use this sensor to measure volume and flow of your house water meter.
                       * You need to set the correct pulsefactor of your meter (pulses per m3).
                       * The sensor starts by fetching current volume reading from gateway (VAR 1).
                       * Reports both volume and flow back to gateway.
                       *
                       * Unfortunately millis() won't increment when the Arduino is in
                       * sleepmode. So we cannot make this sensor sleep if we also want
                       * to calculate/report flow.
                       * http://www.mysensors.org/build/pulse_water
                       */
                      
                      // Enable debug prints to serial monitor
                      #define MY_DEBUG
                      
                      // Enable and select radio type attached
                      #define MY_RADIO_RF24
                      
                      #include <MySensors.h>
                      
                      #define DIGITAL_INPUT_SENSOR 3                  // The digital input you attached your sensor.  (Only 2 and 3 generates interrupt!)
                      #define CHILD_ID 1                              // Id of the sensor child
                      
                      unsigned long loopNumber = 0;
                      unsigned long lastLoopSend = 0;
                      
                      MyMessage volumeMsg(CHILD_ID, V_VOLUME);
                      MyMessage lastCounterMsg(CHILD_ID, V_VAR1);
                      
                      volatile uint32_t pulseCount = 0;
                      bool pcReceived = false;
                      double volume = 0;
                      
                      //=========================
                      // BATTERY MEASURER
                      // VOLTAGE DIVIDER SETUP
                      // 1M, 470K divider across battery and using internal ADC ref of 1.1V
                      // Sense point is bypassed with 0.1 uF cap to reduce noise at that point
                      // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
                      // 3.44/1023 = Volts per bit = 0.003363075
                      #define VBAT_PER_BITS 0.003363075
                      #define VMIN 2.2                                  //  Vmin (radio Min Volt)=1.9V (564v)
                      #define VMAX 3.2                                  //  Vmax = (2xAA bat)=3.0V (892v)
                      int batteryPcnt = 0;                              // Calc value for battery %
                      int batLoop = 0;                                  // Loop to help calc average
                      int batArray[4];                                  // Array to store value for average calc.
                      int BATTERY_SENSE_PIN = A0;                       // select the input pin for the battery sense point
                      //=========================
                      
                      
                      void setup() {
                        // initialize our digital pins internal pullup resistor so one pulse switches from high to low (less distortion)
                        pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP);
                      
                        pulseCount = 0;
                      
                        // Fetch last known pulse count value from gw
                        request(CHILD_ID, V_VAR1);
                      
                        //Battery
                        analogReference(INTERNAL);
                        Serial.print("With Battery VMax (100%) = "); Serial.print(VMAX); Serial.print("volts and Vmin (0%) = "); Serial.print(VMIN); Serial.println(" volts");
                        Serial.print("Battery Percent 25%/50%/75% calculates to: "); Serial.print(((VMAX - VMIN) / 4) + VMIN); Serial.print("/"); Serial.print(((VMAX - VMIN) / 2) + VMIN); Serial.print("/"); Serial.println(VMAX - ((VMAX - VMIN) / 4));
                        delay(1000);
                        int sensorValue = analogRead(BATTERY_SENSE_PIN);
                        delay(50);
                        float Vbat  = sensorValue * VBAT_PER_BITS;
                        int batteryPcnt = static_cast<int>(((Vbat - VMIN) / (VMAX - VMIN)) * 100.);
                        Serial.print("Current battery are measured to (please confirm!): "); Serial.print(batteryPcnt); Serial.print(" % - Or "); Serial.print(Vbat); Serial.println(" Volts");
                      
                      
                      }
                      
                      void presentation()
                      {
                        // Send the sketch version information to the gateway and Controller
                        sendSketchInfo("Gas Meter", "2.0");
                      
                        // Register this device as Water flow sensor
                        present(CHILD_ID, S_GAS);
                      }
                      
                      //=========================
                      // BATTERY MEASURER
                      void MeasureBattery() //The battery calculations
                      {
                        delay(500);
                        // Battery monitoring reading
                        int sensorValue = analogRead(BATTERY_SENSE_PIN);
                        delay(500);
                      
                        // Calculate the battery in %
                        float Vbat  = sensorValue * VBAT_PER_BITS;
                        int batteryPcnt = static_cast<int>(((Vbat - VMIN) / (VMAX - VMIN)) * 100.);
                        Serial.print("Battery percent: "); Serial.print(batteryPcnt); Serial.print(" %"); Serial.print("Battery Voltage: "); Serial.print(Vbat); Serial.println(" Volts");
                      
                        // Add it to array so we get an average of 3 (3x20min)
                        batArray[batLoop] = batteryPcnt;
                      
                        if (batLoop > 2) {
                          batteryPcnt = (batArray[0] + batArray[1] + batArray[2] + batArray[3]);
                          batteryPcnt = batteryPcnt / 4;
                      
                          if (batteryPcnt > 100) {
                            batteryPcnt = 100;
                          }
                          Serial.print("Battery Average (Send): "); Serial.print(batteryPcnt); Serial.println(" %");
                          sendBatteryLevel(batteryPcnt);
                          batLoop = 0;
                        }
                        else
                        {
                          batLoop++;
                        }
                      }
                      
                      void loop() {
                        if (!pcReceived) {
                          //Last Pulsecount not yet received from controller, request it again
                          request(CHILD_ID, V_VAR1);
                          wait(1000);
                          return;
                        }
                        Serial.print("loopNumer=");
                        Serial.println(loopNumber);
                      
                        if (loopNumber % 60 == 0) {
                          Serial.println("Measuring Battery");
                          //=========================
                          // BATTERY MEASURER
                          MeasureBattery();
                          //=========================
                        }
                        if (loopNumber % 10 == 0) {
                          Serial.println("Sending pulse Count");
                          volume = ((double)pulseCount / ((double)1000));
                          send(volumeMsg.set(volume,4));
                          send(lastCounterMsg.set(pulseCount));
                        }
                        Serial.println("I'm sleeping");
                        int8_t cause = sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), FALLING, 60000);
                        Serial.print("WakeUp , cause:");
                        Serial.print(cause);
                        Serial.print("(pin interrupt :");
                        Serial.print(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR));
                        Serial.println(";-1=timer)");
                      
                        if (cause == digitalPinToInterrupt(DIGITAL_INPUT_SENSOR)) {
                          pulseCount++;
                          wait(100);
                        }
                        Serial.print("Pulsecount=");
                        Serial.println(pulseCount);
                      
                        loopNumber++;
                      
                      }
                      
                      void receive(const MyMessage &message)
                      {
                          if (message.type==V_VAR1) {
                              uint32_t gwPulseCount=message.getULong();
                              pulseCount += gwPulseCount;
                              Serial.print("Received last pulse count from gw:");
                              Serial.println(pulseCount);
                              pcReceived = true;
                          }
                      }```
                      1 Reply Last reply
                      1
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      16

                      Online

                      11.7k

                      Users

                      11.2k

                      Topics

                      113.0k

                      Posts


                      Copyright 2019 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
                      • OpenHardware.io
                      • Categories
                      • Recent
                      • Tags
                      • Popular