My 2AA battery sensor

  • Hardware Contributor

    @Meister_Petz Wow! Well done! I think this can be very useful.
    In theory some power should be saved. Estimation from here is that a 250kbit/s transmission of a maximum size (32 byte) packet is >1.5ms. I think at around 20mA. Massage header is 7 byte, but a normal massage just a few bytes, i.e. just 30% of a message. Startup time for radio is fast (140us), so that shouldn't be an issue. (A side note here is that wake up atmega328p from sleep takes long (6ms?).)

    Is there a reason that you wrote the Fhem sonsor.copy macro as an "at" and not a "notify" ? The intuitive way would be to copy upon a new reading.

  • @m26872 there is no special reason for "at"... I think I got it from some where and it worked 😉

  • Hardware Contributor

    Soon 11 months of production including a fair amount of too frequent battery uppdates. Most exciting is wheter the initially used batteries in 106 will make it 12 months or not.

  • Contest Winner

    @m26872 perhaps you could reduce the redundant updates by filtering. If the current sample is lower than the "next" sample ignore it. If your node does not support charging, it will never really truly read an increase in battery voltage.

  • Hardware Contributor

    @Anticimex Yes, but in this particular case its double. Conclusion from above was that frequency and magnitude of the "low spikes" gives you information of how near the end you are. On the other hand I would never run like this if it wasn't for keeping the experiment "untouched". I think my thought for future sensors is to preserve that information, but save battery, just by reducing the number of samples.

    I'm still not sure of the best filter/algorithm to predict battery end of life from present and historic data. It will probably differ a lot wheter there's a step-up or a nicer load.

  • Mod

    @m26872 Just a suggestion: once the node dies you could take the raw data and run some filtering on it like @Anticimex suggested.
    It'll give you a quick way to experiment with different filter settings.
    Once you find an optimal filter you can implement it in the node(s).

  • Hardware Contributor

    @Yveaux You're right. I expect a good correlation between "spike depth" and the load profile just prior to sample. By controling this it should be quite repeatable.

  • This post is deleted!

  • Hardware Contributor

    @mntlvr Interesting discussion but why in this thread?

  • This post is deleted!

  • Hardware Contributor

    i think it would be better to open a new thread for this, instead to discuss two topics in one thread....the 2xaa battery sensor is very interesting 😉

  • Hardware Contributor

    The 12 months target was done a few days ago. Today's status 105: 63% and 106: 27%
    I had a thought to celebrate their birthday by retrieve old Vera data and make nice plot, but that has to wait. Next, 18 months.

    Just to clarify that these are no "sleeping" nodes; they transmit 100-150 messages each every day.

  • Hardware Contributor

    Battery level status report after 18 months:
    Node 105: 51%
    Node 106 (with used batteries): Died early January.

    Next 24 months.

  • Hey @m26872 Congrats on the testing and results! Looks great! I was wondering if I could get your feedback on something. I'm trying to build a very low powered ( 2 x AA ) Battery powered 3 in 1 sensor. ( Platform is a Pro Mini 8Mhz, 3.3v, with an PIR HC-SR501, NRF24L01, and a DHT 11 Temp and Hum sensor. The sensor should also report battery power periodically ideally using the vcc library ( not implemented yet ). Because these components use power hungry devices ( PIR, DHT ), I have already moded the PIR to work at 3.3, and have removed the regulator / LED from the pro mini. Would it make sense to use a step up / down regulator, or power directly from the VCC pin? I can't decide what would be more effective in prolonging battery life? Also, in terms of reporting battery state. I'm not sure what would be best also, hence the question around the VCC library?

    Below is my sketch. It is really taken from various posts on this forum and stitched together. If you could have a peak at it, and see if it is "optimal", as I don't believe it is today. ie: Perhaps I could only report temp / hum if it changes +/- a degree? Or send everything in a single radio announcement, then "Deep Sleep"? Lots of questions, and of course I am sure there are lots of answers. I'm just trying to build the most optimal battery efficient ( 2 x AA ) powered sensor no problem right! 🙂 Below is my current code:

     #define MY_GW_ID 31
    // Enable debug prints
    #define MY_DEBUG
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    #include <SPI.h>
    #include <MySensor.h>  
    #include <DHT.h>  
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    #define SKETCH_NAME           "3 in 1 Sensor"
    #define SKETCH_VERSION        "1.0"
    #define CHILD_ID_HUM 0                    // Child id for Humidity
    #define CHILD_ID_TEMP 1                   // Child id for Temperature
    #define CHILD_ID_MOT 2                   // Id of the sensor child
    #define HUMIDITY_SENSOR_DIGITAL_PIN 7    // Where is my DHT22 data pin connected to
    #define DIGITAL_INPUT_SENSOR 3           // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
    #define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
    //Misc. variables
    uint8_t switchState = 2;
    unsigned long SLEEP_TIME = 820000;      // Sleep time between reads (in milliseconds) (close to 15')
    unsigned long SLEEP_TIME2 = 275000;     // Sleep time after int. (in milliseconds) (close to 5')
    uint8_t cycleInProgress = 0;
    uint8_t firstReportDone = 0;
    uint8_t firstReportWithZeroDone = 0;
    int oldBatteryPcnt = 0;
    MySensor gw;
    DHT dht;
    float lastTemp = 0 ;
    float lastHum = 0 ;
    boolean lastTripped = false ;
    boolean metric = true; 
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgMot(CHILD_ID_MOT, V_TRIPPED);
    void setup()  
       // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
      // Send the Sketch Version Information to the Gateway
      gw.sendSketchInfo("3 in 1 Sensor", "1.0");
     pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
      // Register all sensors to gw (they will be created as child devices)
      gw.present(CHILD_ID_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_MOT, S_MOTION);
      metric = gw.getConfig().isMetric;
    void loop()      
      float temperature = dht.getTemperature();
      float humidity = dht.getHumidity();
      if (isnan(temperature)) {
          Serial.println("Failed reading temperature from DHT");
      } else if (temperature != lastTemp) {
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        gw.send(msgTemp.set(temperature, 1));
        Serial.print("T: ");
      if (isnan(humidity)) {
          Serial.println("Failed reading humidity from DHT");
      } else if (humidity != lastHum) {
          lastHum = humidity;
          gw.send(msgHum.set(humidity, 1));
          Serial.print("H: ");
      // get the battery Voltage
       int sensorValue = analogRead(BATTERY_SENSE_PIN);
       #ifdef DEBUG
       // 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
       float batteryV  = sensorValue * 0.003363075;
       int batteryPcnt = sensorValue / 10;
       #ifdef DEBUG
       Serial.print("Battery Voltage: ");
       Serial.println(" V");
       Serial.print("Battery percent: ");
       Serial.println(" %");
      // Read digital motion value
      boolean tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH; 
      if (tripped != lastTripped ) {      
        gw.send(msgMot.set(tripped?"1":"0"));  // Send tripped value to gw 
       if (oldBatteryPcnt != batteryPcnt) {
         // Power up radio after sleep
         oldBatteryPcnt = batteryPcnt;
      // Sleep until interrupt comes in on motion sensor. Send update every two minute. 
      gw.sleep(INTERRUPT, CHANGE, 0 );

    thanks very much!

  • Hero Member

    @rhuehn It looks like you are repeating the conversation in this thread. Its better to continue the discussion there.

  • Mod

    I agree with AWI, but would like to add one thing: By using the DHT11 you are really fighting an uphill battle. There are several sensors that are more suitable for battery-powered sensors. See the study referenced by @AWI in

  • Thanks @mfalkvidd Starting to realize that..... I might swap to the HTU21D, but keep in mind I'm also using a PIR..... Is there a reliable, low voltage PIR sensor that works well? I haven't seen one yet ( 2 x AA BATT's, under 2.8 V )?


  • I have updated the original post if anyone can offer any suggestions. it is located Here

    Any feedback is greatly appreciated

  • @EasyIoT , how are your sensors doing, its been 2 years 🙂
    And also, @m26872 , the node 105. Is it alive?

  • Hardware Contributor

    @Nicklas-Starkel I've been busy for few months moving to a new house and have had my sensor network offline until now because of this. Node 105 was kept on and handled with care, but I was pretty sure it would be dead when I started my gateway yesterday. BUT, it was ALIVE ?! at 14% battery level. Amazing! 24 months with such poor and simple hardware and software. ❗ 💕 ⭐ 🎵 👯 👏 💪 Same batteries and only one restart (due to my controller change last year).
    One little remark though, it doesn't seem to send temperature och pressure, only humidity and battery level. Maybe an issue of voltage recovery time between transmissions.

Log in to reply





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