Resolved - 18650 battery powered temperature sensors

  • Hi Guys,
    need little bit help to refine my 18650 battery status, see below sketch, i have followed battery Battery Powered Sensors instructions. on hardware side i only removed both leds from arduino mini pro 3.3v and feeding it through raw pin, and have two resisters as per instruction as i m not electronics expert i just did lots of hit and miss but so far voltage on multimeter is 4.01 but arduino is reading it as 3.78. what i m doing wrong here????

    //PiHome Battery Powered Temperature Sensor 
    // Enable debug prints to serial monitor
    //#define MY_DEBUG 
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    // Set LOW transmit power level as default, if you have an amplified NRF-module and
    // power your radio separately with a good regulator you can turn up PA level.
    // #define MY_RF24_PA_LEVEL RF24_PA_LOW
    #define MY_RF24_PA_LEVEL RF24_PA_MAX
    //#define MY_DEBUG_VERBOSE_RF24
    // RF channel for the sensor net, 0-127
    #define RF24_CHANNEL     125
    //PiHome Node ID
    #define MY_NODE_ID 25
    //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
    #define RF24_DATARATE 	   RF24_250KBPS
    #include <SPI.h>
    #include <MySensors.h>  
    #include <DallasTemperature.h>
    #include <OneWire.h>
    // Define sensor node childs
    #define CHILD_ID_BATT 1
    #define CHILD_ID_TEMP 0
    #define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
    #define COMPARE_BVOLT 0 // Send battery voltage only if changed? 1 = Yes 0 = No
    #define ONE_WIRE_BUS 3 // Pin where dallase sensor is connected 
    #define MAX_ATTACHED_DS18B20 16
    unsigned long SLEEP_TIME = 56000; // Sleep time between reads (in milliseconds)
    // Battery related init
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    float oldBatteryV = 0;
    MyMessage msgBatt(CHILD_ID_BATT, V_VOLTAGE);
    // Dallas Temperature related init
    OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
    DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature. 
    float lastTemperature[MAX_ATTACHED_DS18B20];
    int numSensors=0;
    bool receivedConfig = false;
    bool metric = true;
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    void before()
      // Startup up the OneWire library
    void setup()  
      // requestTemperatures() will not block current thread
      // needed for battery soc
      // use the 1.1 V internal reference
      #if defined(__AVR_ATmega2560__)
    void presentation() {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Temperature Sensor", "1.33");
      // Fetch the number of attached temperature sensors  
      numSensors = sensors.getDeviceCount();
      // Present all sensors to controller
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {   
         present(i, S_TEMP);
    void loop()     
      // get the battery Voltage
      int battSensorValue = analogRead(BATTERY_SENSE_PIN);
      float batteryV  = battSensorValue * 0.003695015;
        // 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 0.0036950146627566
    	int batteryPcnt = battSensorValue / 10;
    	#ifdef MY_DEBUG
    		Serial.print("Pin Reading: ");
    		Serial.print("Battery Voltage: ");
    		Serial.println(" v");
    		//Print Battery Percentage
    		Serial.print("Battery percent: ");
    		Serial.println(" %");
    	#if COMPARE_BVOLT == 1
    		send(msgBatt.set(batteryV, 2));
    		if (oldBatteryV != batteryV) {
    			send(msgBatt.set(batteryV, 2));
    			oldBatteryV = batteryV;
      // Fetch temperatures from Dallas sensors
      // query conversion time and sleep until conversion completed
      int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
      // sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
      // Read temperatures and send them to controller 
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
        // Fetch and round temperature to one decimal
        float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;
        // Only send data if temperature has changed and no error
        #if COMPARE_TEMP == 1
        if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
        if (temperature != -127.00 && temperature != 85.00) {
          // Send in the new temperature
          // Save new temperatures for next compare

  • what are your resistor devider values ? your "Volts per bit" value sugests that the max voltage you can measure is 3.78V so I guess you have wrong division ratio. I would go for 1M and 1k ohms, then you can measure up to 12V.

  • Mod

    Look at my post about solar powered node, I explained how to measure higher input voltage

  • after changing r2 to 1k ohms and volts per bit to 1.076344086 i m getting first reading is 34.44v and then 2.15, this is even more messed up.... 😞

    float batteryV  = battSensorValue * 1.076344086;
    65 TSM:INIT
    65 TSF:WUR:MS=0
    77 TSF:SID:OK,ID=25
    79 TSM:FPAR
    116 TSF:MSG:SEND,25-25-255-255,s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=OK:
    438 TSF:MSG:READ,0-0-25,s=255,c=3,t=8,pt=1,l=1,sg=0:0
    444 TSF:MSG:FPAR OK,ID=0,D=1
    2125 TSM:FPAR:OK
    2125 TSM:ID
    2127 TSM:ID:OK
    2129 TSM:UPL
    2164 TSF:MSG:SEND,25-25-0-0,s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=OK:1
    2355 TSF:MSG:READ,0-0-25,s=255,c=3,t=25,pt=1,l=1,sg=0:1
    2365 TSM:UPL:OK
    2365 TSM:READY:ID=25,PAR=0,DIS=1
    2371 TSF:MSG:SEND,25-25-0-0,s=255,c=3,t=15,pt=6,l=2,sg=0,ft=0,st=OK:0100
    2506 TSF:MSG:READ,0-0-25,s=255,c=3,t=15,pt=6,l=2,sg=0:0100
    2514 TSF:MSG:SEND,25-25-0-0,s=255,c=0,t=17,pt=0,l=5,sg=0,ft=0,st=OK:2.1.1
    2525 TSF:MSG:SEND,25-25-0-0,s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=OK:0
    4534 TSF:MSG:SEND,25-25-0-0,s=255,c=3,t=11,pt=0,l=18,sg=0,ft=0,st=OK:Temperature Sensor
    4544 TSF:MSG:SEND,25-25-0-0,s=255,c=3,t=12,pt=0,l=4,sg=0,ft=0,st=OK:1.34
    4554 TSF:MSG:SEND,25-25-0-0,s=0,c=0,t=6,pt=0,l=0,sg=0,ft=0,st=OK:
    4562 MCO:REG:REQ
    4564 TSF:MSG:SEND,25-25-0-0,s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=OK:2
    4841 TSF:MSG:READ,0-0-25,s=255,c=3,t=27,pt=1,l=1,sg=0:1
    4847 MCO:PIM:NODE REG=1
    4849 MCO:BGN:STP
    4851 MCO:BGN:INIT OK,TSP=1
    Pin Reading: 32
    Battery Voltage: 34.44 v
    Battery percent: 3 %
    4859 TSF:MSG:SEND,25-25-0-0,s=1,c=1,t=38,pt=7,l=5,sg=0,ft=0,st=OK:34.44
    4870 TSF:MSG:SEND,25-25-0-0,s=255,c=3,t=0,pt=1,l=1,sg=0,ft=0,st=OK:3
    4878 MCO:SLP:MS=750,SMS=0,I1=255,M1=255,I2=255,M2=255
    4884 MCO:SLP:TPD
    4886 MCO:SLP:WUP=-1
    4919 TSF:MSG:SEND,25-25-0-0,s=0,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:19.7
    4927 MCO:SLP:MS=56000,SMS=0,I1=255,M1=255,I2=255,M2=255
    4933 MCO:SLP:TPD
    4935 MCO:SLP:WUP=-1
    Pin Reading: 2
    Battery Voltage: 2.15 v
    Battery percent: 0 %
    4941 TSF:MSG:SEND,25-25-0-0,s=1,c=1,t=38,pt=7,l=5,sg=0,ft=0,st=OK:2.15
    4952 TSF:MSG:SEND,25-25-0-0,s=255,c=3,t=0,pt=1,l=1,sg=0,ft=0,st=OK:0
    4960 MCO:SLP:MS=750,SMS=0,I1=255,M1=255,I2=255,M2=255
    4966 MCO:SLP:TPD
    4968 MCO:SLP:WUP=-1
    5001 TSF:MSG:SEND,25-25-0-0,s=0,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:19.5
    5009 MCO:SLP:MS=56000,SMS=0,I1=255,M1=255,I2=255,M2=255
    5015 MCO:SLP:TPD

  • Mod

    I used R1 1.22M (1M + 220K) and R2 300K in order to read a maximum of 5.57v

    ((1e6+220e3+300e3)/300e3)*1.1 = Vmax = 5.57 Volts
    5.57/1023 = Volts per bit = 0.005448028

  • Do you have 1m and 220k in series?

  • Mod

    Yes of course. Use the following link to find the most suitable divider for the resistor you have, just remember to keep output voltage to 1.1

  • @pihome sorry, I meant 100kOhm. I would suggest You to understand the theory behind the voltage divider, then you would know what you are doing and be able to solve your problem by yourself. This is just one simple formula, not magic.

  • Mod

    I started to punch in resistor values more or less randomly of various combinations of the resistors I had until I got close enough to the maximum input voltage I wanted to have

  • thank you guys for help, really appreciate this. for 18650 battery with 4.2volt in following combination would do the job for you, i m adding here so in future if some one wants reference and save some time on trial and error. @rozpruwacz i m using your idea with 1m and 100k thank you for help.

    1.1v out

    1.116v out

    1.1v out

    1.12v out

    1.194v out

    1.167v out

    1.12v out

    1.135v out

  • Mod

    Try to use the highest total resistance in order to lower the battery drain as much as possible

  • @gohan i m using 1m with 100k but second best combination would be then 620k with 220k ?

  • Mod

    Yes, but there could be also other combinations that will allow you to detect higher voltage but with an higher total resistance