My 2AA battery sensor



  • A tip for much better batterylife: burn a new bootloader for 1mhz. Now you can attach the arduino and nrf directly to the batteries and you can measure the battery with the Internal voltage meter of the 328p. If you use a dht you attach the step-up conv. And only attach the dht to it.


  • Hardware Contributor

    @sundberg84
    I've looked at your lovely drawing before and I don't see anything wrong with it except from that 0.1uF capacitor should be in parallell just with the 470k resistor, but it shouldn't matter regarding battery life time. What would be more interesting is to see your sketch. Or do you use the same as I do?

    A schematic and a few better pictures is on my to do list, but will probably come sooner now since you asked for it.


  • Hardware Contributor

    @m26872
    Pretty much the same, i have stolen majority of your code:
    Ive a array to get an average battery value each hour:

    #include <SPI.h>
    #include <MySensor.h>  
    #include <DHT.h>  
    
    //ställ in varje gång!=========================
    #define SketchName "Sovrum Uppe"
    #define SketchVer "1.0"
    #define NodeID 2
    #define VBAT_PER_BITS 0.003363075  // Calculated volts per bit from the used battery montoring voltage divider.   Internal_ref=1.1V, res=10bit=2^10-1=1023, Eg for 3V (2AA): Vin/Vb=R1/(R1+R2)=470e3/(1e6+470e3),  Vlim=Vb/Vin*1.1=3.44V, Volts per bit = Vlim/1023= 0.003363075
    #define VMIN 1.9  // Battery monitor lower level. Vmin_radio=1.9V
    #define VMAX 3.3  //  " " " high level. Vmin<Vmax<=3.44
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define HUMIDITY_SENSOR_DIGITAL_PIN 3
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    unsigned long SLEEP_TIME = 15*60000;
    //unsigned long SLEEP_TIME = 5000; //debug
    //Ställ även in gw.begin(,,,)
    //ställ in varje gång!=========================
    
    float lastTemp;
    float lastHum;
    boolean metric = true; 
    int batteryPcnt = 0;
    int batLoop = 0;
    int batArray[3];
    
    MySensor gw;
    DHT dht;
    
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    
    void setup()  
    { 
    // use the 1.1 V internal reference
      analogReference(INTERNAL);
      delay(500); // Allow time for radio if power used as reset <<<<<<<<<<<<<< Experimented with good result 
       
      gw.begin(NULL, NodeID, false);
    //incomingMessageCallback - Callback function for incoming messages from other nodes or controller and request responses. Default is NULL.
    //nodeId - The unique id (1-254) for this sensor. Default is AUTO(255) which means sensor tries to fetch an id from controller.
    //repeaterMode - Activate repeater mode. This node will forward messages to other nodes in the radio network. Make sure to call process() regularly. Default in false
      
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
    
      // Send the Sketch Version Information to the Gateway
      gw.sendSketchInfo(SketchName, SketchVer);
    
      // 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);
      
      metric = gw.getConfig().isMetric;
    }
    
    void loop()      
    {  
      int sensorValue = analogRead(BATTERY_SENSE_PIN);    // Battery monitoring reading
    delay(1000);
      delay(dht.getMinimumSamplingPeriod());
    
     
      float temperature = dht.getTemperature();
      Serial.print("Temp: "); Serial.print(temperature); Serial.println(" C");
      
     if (temperature > 0) {
       gw.send(msgTemp.set(temperature, 1));
      }
     
    delay(1000);
     
      float humidity = dht.getHumidity();
      Serial.print("Hum: "); Serial.print(humidity); Serial.println(" %");
       
       if (humidity > 0) {
        gw.send(msgHum.set(humidity, 1));
    }
    
    delay(1000);
       
       float Vbat  = sensorValue * VBAT_PER_BITS;
       int batteryPcnt = static_cast<int>(((Vbat-VMIN)/(VMAX-VMIN))*100.);   
     Serial.print("Battery percent: "); Serial.print(batteryPcnt); Serial.println(" %");  
       batArray[batLoop] = batteryPcnt;
      
       if (batLoop > 2) {
         
         batteryPcnt = (batArray[0] + batArray[1] + batArray[2] + batArray[3]);
         batteryPcnt = batteryPcnt / 4;
        Serial.print("Battery percent (Avg (4):) "); Serial.print(batteryPcnt); Serial.println(" %");
    
           gw.sendBatteryLevel(batteryPcnt);
           batLoop = 0;   
         }
         else 
         {
         batLoop = batLoop + 1;
         }
       
      gw.sleep(SLEEP_TIME); //sleep a bit
    }
    

  • Hardware Contributor

    @Sweebee
    It's already been discussed earlier in this thread (see EasyIoTs posts above), it's nevertheless a very good tip. I also have some test nodes running, but I consider it to be the next step from the "basic" design which was this threads concept. If I'll post something with this low-power-tweaked design it'll therefore be in a new thread. I should probably write something about this as an update in the first post...


  • Hardware Contributor

    @sundberg84
    I'm no code expert, and the only thing I can think of is that your "delay(1000)" will keep the power hungry radio awake. If you need delays (apart from debug) I'd prefer sleep instead. What's your battery life time look like?


  • Hardware Contributor

    UPDATE
    I've updated the first post with

    • A wiring layout.
    • Added a text about the low-power option
    • A few minor details.

  • Hardware Contributor

    Great layout/way to show your project - really nice!

    Its exactly as I do it so im getting a bit jealus here... . One node is down after a week.
    It might be the hardware or me not so good soldering so i short something out.

    I will try some more nodes now you have comfirmed I do it the right way and that should work.

    @m26872
    Thank you!


  • Hardware Contributor

    @sundberg84
    Thx, good you liked it.
    With such fast battery drain it should be easier to trace the current draw. First you'll need to measure the current. Second option is of course the good old switch-and-replace troubleshooting method.
    I've read about hardware and quality issues, but let's hope it isn't...


  • Hardware Contributor

    @m26872 What kind of pro-mini do you use?
    Im using deek robot 3.3v 8mhz and it seems like there is a problem with this: (http://forum.mysensors.org/topic/230/power-conservation-with-battery-powered-sensors) i kill them when i try to remove voltage regulator so i guess i havent suceeded yet with that.

    I dont have any good equipment to measure current... Ill have made a new sensor today - lets see how it operates.


  • Hardware Contributor

    Here are some close-up pictures of my Node 105 (which I opened with maximum care not to spoil my long term testing)
    1_IMG_1694.JPG
    2_IMG_1685.JPG
    3_IMG_1687.JPG
    4_IMG_1688.JPG
    5_IMG_1689.JPG
    6_IMG_1691.JPG
    7_IMG_1686.JPG
    8_IMG_1692.JPG
    9_IMG_1693.JPG


  • Admin

    Node 105 starts to become famous here :)
    We all follow him(?) with great excitement.


  • Hero Member

    yes, @m26872 any news ?


  • Hardware Contributor

    The news is that my Vera Lite gave up (soft-wise) after all hacking, plug-ins and un-clean factory resets, so I gave up on her (and Z-wave too, at least for a while). We've been fighting with each other for too long, so I'd say the divorce was welcome.

    Instead, in the controller jungle I decided to try Fhem, aware of the challanges as I'm not German- (nor Perl) speaking. I'm still in the sens-but-no-control-phase and have a few test nodes running, including "the" node 105. (Very easy transition btw, just one press at reset button then a node is in production with a new controller.)

    Back home today after 2w holiday I think it's looking good. The only problem now is of course that my trending is broken. If anyone knows how to merge the old trend data with the new, you're very welcome? Or just on how to rescue the Datamine data (from NAS)? If possible? I haven't researched anything yet.
    fhem_2w.PNG



  • Just an idea... I'm not sure if someone mentioned it:
    If sending consumes so much power... what about collecting sensor data every 5 minutes and then send the data (array) once per hour? Of course there would be some time calculating before logging in the controller (fhem), but this way, I can save power... What do you think?


  • Hardware Contributor

    @Meister_Petz Kind of what I already do in the test nodes 105/106 if you look at code above. Update frequencey and battery life time is a balance that can be adjusted just as you wish. Right now these node send update every 15 min and take sample for calculation 5 min before, which is about what I need. If you and your application is more interested in trending, history and data collection, I think your suggestion is excellent. If you need a fast response or action from your automation system it's not.

    But, what I think is most unneseccary with my test nodes 105/106 is that they check battery level every 15 min and send update if it has changed. Since the level typically is unstable right after the first transmission, it will generate a lot of useless transmissions. The only reason for me not to update code in node 105/106 is to keep it as an untouched study case. In my new nodes I usually set a fixed battery check/update frequency (1/week) which also works as a heartbeat signal for less active nodes.


  • Contest Winner

    Not sure if any one has had the same question. But the other day I stumbled on this little thing ;)
    https://www.adafruit.com/product/1572 It's a really small rechargeable battery. Now I don't no much about batteries. But I know that my LiOn powerd handdrill is very strong. The batteries of my handdril hardly lose power over time.

    So I was wondering if this could be used to power an Arduino and some sensors and how long it will take for the battery te become empty. It would make my 3.3V Sensors really small. I could almost install them in a small matchbox. Which I think is really cool!


  • Hardware Contributor

    @TheoL There are endless discussions about different batteries in the forum. Just search and read. I recall one issue with LiXx batteries is that max voltage is too high for the NRF24L01+ radio.



  • Ok, another thing: why not sending everything at once?

    As I understand you are using FHEM which allows a lot of coding on the controller side. So you could send batteryLevel, humidity and temperature in one go.

    Something like (this is no real code, just an idea):
    theValues = "battlvl:hum:temp"
    gw.send(msgAll.set(theValues, 1));

    and in fhem you split it at ":"

    So you have just one instead of 3 transmits.


  • Hardware Contributor

    @Meister_Petz I think it's a very good idea! It would be a nice option to have. Parsing with Perl should be simple even for a beginner like me, but to change the Mysensors core and fhem plugin is far beyond what I can. If you can do it, just go ahead and plz share.



  • ok, I did some testing and succeeded:

    This is the important part of the Arduino code:

    String allSens = String(sensor1) + " " + String(sensor2);
    gw.send(msg1.set(allSens.c_str()));
    

    This is the FHEM code:

    define Sensor MYSENSORS_DEVICE 20
    attr Sensor IODev MSGateway
    attr Sensor mapReading_brightness1 1 brightness
    attr Sensor mode node
    attr Sensor version 1.5
    attr Sensor userReadings Bat Deg
    
    # split and copy to userReadings
    define Sensor.copy at +*00:02:00 {my $a = ReadingsVal("Sensor","brightness1",1);; my @b = split(/\ /,$a);; fhem("setreading Sensor Bat $b[0]");; fhem("setreading Sensor Grad $b[1]");;}
    

    P.S.: when I had this in fhem.cfg I had to use @@ instead of only one @

    This is my complete Arduino code for a Battery Sensor with Dallas Temp:

      
    #include <MySensor.h>
    #include <SPI.h>
    
    #define SketchName "Sensor-send-all"
    #define SketchVer "1.2"
    #define NodeID 20
    
    unsigned long SleepTime = 828523; // 55234 = 1 Minute --- 828523 = 15 Minuten
      
    MySensor gw;
    
    // this is the one which sends everything
    #define SENSOR1_ID 1 // Sensor 1 - allAtOnceMessage
        
      //------------------------------------------------
      // Sensor PINS 
        #define SENSOR1_PIN  A0 // BattLevel
        #define SENSOR2_PIN  6  // Dallas
          
      // MyMessage V_TEMP, V_LIGHT_LEVEL, ... depending on Sensor Type
         MyMessage msg1(SENSOR1_ID,V_LIGHT_LEVEL); // Sensor 5 - allAtOnceMessage
    
      //------------------------------------------------
      // Dallas Temp
         #include <OneWire.h>
         #include <DallasTemperature.h>      
         OneWire oneWire(SENSOR2_PIN);
         DallasTemperature sensors(&oneWire);
         boolean receivedConfig = false;
             
         float firstRun = 1;
         boolean metric = true;
      
    void setup()  
      {  
        // use the 1.1 V internal reference
        analogReference(INTERNAL);
        delay(500); // Allow time for radio if power used as reset <<<<<<<<<<<<<< Experimented with good result 
      
        gw.begin(NULL, NodeID, false);
      
        // Send the sketch version information to the gateway and Controller
        gw.sendSketchInfo(SketchName, SketchVer);
            
        // present all Sensors to Gateway - S_TEMP, S_LIGHT_LEVEL,... depending an SENSOR type
        gw.present(SENSOR1_ID, S_LIGHT_LEVEL);     
            
        sensors.begin();  
      }
      
      
    void loop() 
      {
        gw.process();
    
           // wait some time to get all parts powered up
           if (firstRun == 1){
              delay(5000);
              firstRun = 0;
           } else {
              delay(1000);
           }
           
           //----------------------
           // Sensor1 - Battery Voltage - Part 1
              int sensorRead10 = analogRead(SENSOR1_PIN); 
    
           //----------------------
           // Sensor2 - DAL
             sensors.requestTemperatures();
             int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
             gw.sleep(conversionTime);
             float sensorRead2 = static_cast<float>(static_cast<int>((metric?sensors.getTempCByIndex(0):sensors.getTempFByIndex(0)) * 10.)) / 10.;
    
           //----------------------
           // Sensor1 - Battery Voltage - Part 2
              int sensorRead11 = analogRead(SENSOR1_PIN);
              //Volt der Battery
              
              float sensorRead1 = (sensorRead10 + sensorRead11 + sensorRead12) / 3 * 0.0033;  // should be 0.003363075 my Batteries are different
              float test = sensorRead10;
    
    
           //----------------------
           // send all to fhem
              String allComb = String(sensorRead1) + " " + String(sensorRead2);
              gw.send(msg1.set(allComb.c_str()));
    
          gw.sleep(SleepTime);
      } 
      
     
    

Log in to reply
 

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