Monitoring 2 x 18650 batteries
-
Hi Guys,
I have been playing around with the Battery Powered Sensor sketch, trying to get it to report correctly the level of 2x 18650 batteries. I am not a programmer and am getting a bit lost with the sketch. I have a voltage divider of 2.2Meg and 330K, So in my calculations 2 x 18650 batteries give me a max voltage of 8.4vdc fully charged, therefore with that divider Vout should be 1.096vdc or around that. So I have calculated that my Vmax is 1.100007332 and my Volts per bit for the sketch should be 0.001075275.
But when I run the sketch I am getting around 1vdc on the serial monitor, when the voltmeter is reading 7.90vdcHeres the Loop part of my sketch, can some one point out my mistakes please?
void loop() { // get the battery Voltage int sensorValue = analogRead(BATTERY_SENSE_PIN); #ifdef MY_DEBUG Serial.println(sensorValue); #endif // 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 int batteryPcnt = sensorValue / 10; #ifdef MY_DEBUG float batteryV = sensorValue * 0.001075275; Serial.print("Battery Voltage: "); Serial.print(batteryV); Serial.println(" V"); Serial.print("Battery percent: "); Serial.print(batteryPcnt); Serial.println(" %"); #endif if (oldBatteryPcnt != batteryPcnt) { // Power up radio after sleep sendBatteryLevel(batteryPcnt); oldBatteryPcnt = batteryPcnt; } sleep(SLEEP_TIME); }Thanks
-
@crumpy10 do you have analogReference(INTERNAL); in setup()?
Are you using a 3.3 or 5V device?@mfalkvidd I have left the analogReference as it was in the original like this-:
void setup() { // use the 1.1 V internal reference #if defined(__AVR_ATmega2560__) analogReference(INTERNAL1V1); #else analogReference(INTERNAL); #endif } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Battery Meter", "1.0"); }Just for learning about battery monitoring, I am using a Nano with two 18650's in series to power it. in my final project I will be using a Pro Mini. Unfortunately the ultrasonic sensor I need to use is a 5v sensor and needs a good supply. Hence learning about monitoring the 18650's.
Cheers.Thanks for the reply.
-
I did the calculations and got the same result as you, so that part seems ok.
No sure what else to check :(@mfalkvidd Well thanks for looking at it, at least my maths is still working ok! Perhaps someone else may know whats going on...
The strange thing is if I use this line-:
float batteryV = sensorValue * 8.6 / 1023;I can get close. I found another thread where @TimO was using 7.2v with this in his sketch-:
float batteryV = sensorValue * 6.1 / 1023;So I just increased the 6.1 slowly until my read value was close to my multimeter voltage. But I dont understand what the 6.1 in this line of code is doing, or where it comes from...
-
@mfalkvidd Well thanks for looking at it, at least my maths is still working ok! Perhaps someone else may know whats going on...
The strange thing is if I use this line-:
float batteryV = sensorValue * 8.6 / 1023;I can get close. I found another thread where @TimO was using 7.2v with this in his sketch-:
float batteryV = sensorValue * 6.1 / 1023;So I just increased the 6.1 slowly until my read value was close to my multimeter voltage. But I dont understand what the 6.1 in this line of code is doing, or where it comes from...
-
@mfalkvidd said in Monitoring 2 x 18650 batteries:
@crumpy10 maybe double-check that the resistors have the values you think they have?
That + imprecision of the voltage reference. If I remember well, it's stable over time, but not precisely at 1.1V.
-
@mfalkvidd said in Monitoring 2 x 18650 batteries:
@crumpy10 maybe double-check that the resistors have the values you think they have?
That + imprecision of the voltage reference. If I remember well, it's stable over time, but not precisely at 1.1V.
@nca78 Correct, easily verified and corrected for however...
-
My way for monitoring battery.
Usually I have not got precise resistor with tolerance +-0.5% etc. for correct calculation, so I build resistor divider with what I approximately found.
Load my device with simple sketch, which reads data from ADC and write this raw ADC data to serial port.
I make notice, that for example 1009 corresponds to 6041mV with fresh battery measured with multimeter.
In my final sketch then using "magic" map Arduino function:int raw_volt = analogRead(A1); int volt = map(raw_volt, 0, 1009, 0, 6041);Not very useful for "mass production", but for my prototyping it is ok.
-
You mentioned your two resistors, but how they are placed? So which one is connected to gnd and which one to the batteries?
-
@mfalkvidd been there already but thanks.
-
My way for monitoring battery.
Usually I have not got precise resistor with tolerance +-0.5% etc. for correct calculation, so I build resistor divider with what I approximately found.
Load my device with simple sketch, which reads data from ADC and write this raw ADC data to serial port.
I make notice, that for example 1009 corresponds to 6041mV with fresh battery measured with multimeter.
In my final sketch then using "magic" map Arduino function:int raw_volt = analogRead(A1); int volt = map(raw_volt, 0, 1009, 0, 6041);Not very useful for "mass production", but for my prototyping it is ok.
@kimot said in Monitoring 2 x 18650 batteries:
My way for monitoring battery.
Usually I have not got precise resistor with tolerance +-0.5% etc. for correct calculation, so I build resistor divider with what I approximately found.
Load my device with simple sketch, which reads data from ADC and write this raw ADC data to serial port.
I make notice, that for example 1009 corresponds to 6041mV with fresh battery measured with multimeter.
In my final sketch then using "magic" map Arduino function:int raw_volt = analogRead(A1); int volt = map(raw_volt, 0, 1009, 0, 6041);Not very useful for "mass production", but for my prototyping it is ok.
For "mass production", you would run a config script, with known vcc applied to the board, and save measured value in EEPROM. Then you just have to reload this value to pass to the map function.
-
What is the value you read from the analog port, when the battery is 8.4v? So the value before calculating the voltage.
@electrik Not sure what it would be at 8.4v because that would be two fully charged 18650's and the two I have on test are currently giving 7.80v on the multimeter and returning about 870 on the serial monitor, reporting battery at 0.94v and 86%
I would need to fully recharge two batteries later to tell what the max would be.
-
@electrik Not sure what it would be at 8.4v because that would be two fully charged 18650's and the two I have on test are currently giving 7.80v on the multimeter and returning about 870 on the serial monitor, reporting battery at 0.94v and 86%
I would need to fully recharge two batteries later to tell what the max would be.
@crumpy10 Am a bit rusty on this, but would an ADC reading 870 on a 7.8v supply not translate to an ADC reading of 1023 and 9.17v.?
Replacing the 6.1 factor in "float batteryV = sensorValue * 6.1 / 1023;" with 9.17 will derive the true voltage.
As to the weird results, it suggests the INTERNAL reference is not latching, perhaps remark out the #if define... etc lines to leave "analogReference(INTERNAL);" entirely on it's own. -
A few "reality checks" with ADCs :
- The precision of the ADC is limited to 0.1% at full scale (1024). This means that when measuring smaller values, it's less precise. For example, when measuring 1/10 of the reference, your precision is down to 1% already.
- Analog noise is usually in the range of 10mV is your circuit is carefully designed. Similar to above, it has a bigger effect on small values, but also on smaller references (1.1V is 3x more sensible to noise than 3.3V). Add a 10nF capacity in parallel to your 330k for better resilience.
- ADC is slow and needs time to calculate. Wait enough time between changing parameters and reading value (the Ardunio routines don't).
I'd suggest you do a for() loop of 20x reading your ADC, and see the variation : mean(), std() and trend (for example last 5 - first 5). It could learn you a few things.