Sketch kills batteries in 2-3 days



  • Greetings All,

    I suspect the issue I have is with my sketch and not hardware. I've had this issue on two different sensors with the same result. Also, I noticed that the status LED remains lit. I don't see this with my other sketches. I basically tried to combine a door sensor with battery metering using the examples. Perhaps someone can point out where I went wrong?

    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    #define MY_NODE_ID 8
    #define MY_PARENT_NODE_ID 0
    #define MY_PARENT_NODE_IS_STATIC
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    
    #include <SPI.h>
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #define CHILD_ID 1
    #define BUTTON_PIN  2  // Arduino Digital I/O pin for button/reed switch
    
    Bounce debouncer = Bounce(); 
    int oldValue=-1;
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    uint32_t SLEEP_TIME = 900000;  // sleep time between reads (seconds * 1000 milliseconds)
    int oldBatteryPcnt = 0;
    
    // Change to V_LIGHT if you use S_LIGHT in presentation below
    MyMessage msg(CHILD_ID,V_TRIPPED);
    
    void setup()  
    {  
        // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
        analogReference(INTERNAL1V1);
    #else
        analogReference(INTERNAL);
    #endif
    
      // Setup the button
      pinMode(BUTTON_PIN,INPUT);
      // Activate internal pull-up
      digitalWrite(BUTTON_PIN,HIGH);
    
      // After setting up the button, setup debouncer
      debouncer.attach(BUTTON_PIN);
      debouncer.interval(5);
    
    }
    
    void presentation() {
      // Register binary input sensor to gw (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(CHILD_ID, S_DOOR);  
      sendSketchInfo("Front Door", "1.0");
    }
    
    
    //  Check if digital input has changed and send in new value
    void loop() 
    {
      debouncer.update();
      // Get the update value
      int value = debouncer.read();
    
      if (value != oldValue) {
         // Send in the new value
         send(msg.set(value==HIGH ? 1 : 0));
         oldValue = value;
           // get the battery Voltage
         int sensorValue = analogRead(BATTERY_SENSE_PIN);
         Serial.println(sensorValue);
         int batteryPcnt = sensorValue / 10;
         sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
      }
    }
    

  • Hardware Contributor

    Hello @shadex12, I don't see any call to the sleep method ?



  • @Nca78 Oh right!. Makes sense. If I recall correctly I think I removed that because I was having issues with door sensor not interrupting the loop to send the status update.I forgot to add it back in. I will play around tonight and see if I can get it working with sleep included again.

    I am not very experienced coding this stuff so I appreciate the help!



  • So this has been an interesting journey. It turns out that you cannot use bounce with sleep, or so I read. This is what I eventually came up with for the sketch. So far it seems to be working well.

    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    #define MY_NODE_ID 213
    #define MY_PARENT_NODE_ID 0
    #define MY_PARENT_NODE_IS_STATIC
    
    // Enable and select radio type attached
    #define MY_RADIO_RF24
    
    #include <SPI.h>
    #include <MySensors.h>
    
    #define DIGITAL_INPUT_SENSOR 2   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
    #define CHILD_ID_DOOR 1  
    
    // Force sending an update of the temperature after n sensor reads, so a controller showing the
    // timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
    // the value didn't change since;
    // i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
    static const uint8_t FORCE_UPDATE_N_READS = 10;
    
    int oldValue=-1;
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    uint32_t SLEEP_TIME = 900000;  // sleep time between reads (seconds * 1000 milliseconds)
    int oldBatteryPcnt = 0;
    bool metric = true;
    
    MyMessage msg(CHILD_ID_DOOR, V_TRIPPED);
    
    void presentation() 
    {
      // Send the sketch version information to the gateway
      sendSketchInfo("Closet Door", "3.0");
    
      // Register all sensors to gw (they will be created as child devices)
      present(CHILD_ID_DOOR, S_DOOR);  
      metric = getControllerConfig().isMetric;
    }
    
    void setup()  
    {  
        // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
        analogReference(INTERNAL1V1);
    #else
        analogReference(INTERNAL);
    #endif
    
      // Setup the button
      pinMode(DIGITAL_INPUT_SENSOR,INPUT);
      // Activate internal pull-up
      digitalWrite(DIGITAL_INPUT_SENSOR,HIGH);
    
    }
    
    
    void loop() 
    {
    
           // get the battery Voltage
         int sensorValue = analogRead(BATTERY_SENSE_PIN);
         Serial.println(sensorValue);
         int batteryPcnt = sensorValue / 10;
         sendBatteryLevel(batteryPcnt);
         oldBatteryPcnt = batteryPcnt;
    
      // Read digital motion value
        bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
    
        Serial.println(tripped);
        send(msg.set(tripped?"1":"0"));  // Send tripped value to gw
    
      // Sleep until interrupt comes in on motion sensor. Send update every two minute.
      sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME); 
      
    }```

  • Hardware Contributor

    @shadex12 said in Sketch kills batteries in 2-3 days:

    It turns out that you cannot use bounce with sleep

    If you have problem now you have removed the debouncing, you can just add a (very) short wait after waking up from interrupt, so the button has the time to settle.
    Of you can use a small capacitor in parallel to the button so whatever the bouncing looks like, voltage will increase in a progressive way on the pin and trigger the interrupt only once.



  • Well.

    1. I would power A0 (ADC)through a digital pin. This way it reads voltage only when needed, not always connected to battery and draining power.
    2. Besides powering the nrf radio through a pin (transistor) is a good idea as well.
    3. Putting the mcu To sleep sure will add few more days to the life of the battery.
      Battery in correct connections should live more than couple of years, I had ultrasonic distance reader project connected with nrf and pro mini. That lived months without a noticed drop in battery

  • Hardware Contributor

    @wahid said in Sketch kills batteries in 2-3 days:

    Besides powering the nrf radio through a pin (transistor) is a good idea as well.

    This is only useful when in search of extra long battery life with extremely low capacity battery. Else MySensors put the nrf into sleep mode when sleeping the cpu and power consumption of the radio is in the range of 1uA.


  • Admin

    @wahid

    As an example, I have 4 sensebender micros, which has been deployed since june 2015, I have not changed batteries in them yet, and they still report temperature / humidity (that's more than 4 years battery life!). The batteries are cheap AA alkaline types (2 pieces)..

    I'm not doing anything special (hardware wise) to power off the radio, or any other peripherals on the board. Only using standard software powerdown where available.


 

167
Online

8.8k
Users

9.6k
Topics

100.3k
Posts