LoPy with Expansion board, How do you measure LiPo Battery up to 4.2V?
-
I am wrapping my head around measuring the battery voltage on pin 16 with the Attn set to '3'. My understanding is that pin 16 with the resistors will output a voltage of 0 to 1.4 that can be interpreted as a voltage from 0 to 3.9V in 4096 steps (attn=3). The BQ24040 on the expansion board (from TI) charges Li-ion batteries with a min and max charge voltage of 4.2V.
Maybe this is more of a math problem with a simple solution.
I am using protected 18650 batteries so they are not left to undercharge by accident, low end Voltage cut off is around 3V I think(haven't tested) and the high end at 4.2V.
If the range is 3V (0%) to 3.9V(100%), there is a 0.9V range of juice. The battery percentage would look something like:
percent_battery = ((meanADC/4096*3.548/0.3275)-3)/0.9
If I want to show a battery charged at 100% (at 4.2 volts) is that possible with the LoPy and expansion board?
Any feedback is appreciated.
-
@jmarcelino
Once again, thanks for the great feedback. I was looking for a simple way to alert when the battery needs to be recharged. Looks like some simple logic could be: if voltages gets to 3.3, alert for recharge...So many LiPo batteries have differing characteristics, even among the same model/make/capacity/manufacturer. I don't think there is real value is tracking a percentage... without extensive battery testing. Simplest thing to do is just report voltage.
From the example from HERE do you recommend using the following:
numADCreadings = const(100) def ADCloopMeanStdDev(): adc = machine.ADC(0) adcread = adc.channel(attn=1, pin='P16') samplesADC = [0.0]*numADCreadings; meanADC = 0.0 i = 0 while (i < numADCreadings): adcint = adcread() samplesADC[i] = adcint meanADC += adcint i += 1 meanADC /= numADCreadings varianceADC = 0.0 for adcint in samplesADC: varianceADC += (adcint - meanADC)**2 varianceADC /= (numADCreadings - 1) print("%u ADC readings :\n%s" %(numADCreadings, str(samplesADC))) print("Mean of ADC readings (0-1023) = %15.13f" % meanADC) print("Mean of ADC readings (0-1400 mV) = %15.13f" % (meanADC*1400/1024)) print("Variance of ADC readings = %15.13f" % varianceADC) print("10**6*Variance/(Mean**2) of ADC readings = %15.13f" % ((varianceADC*10**6)//(meanADC**2))) print("ADC reading for Voltage (0-1400 mV) = %15.4f" % (meanADC*1400/1024))
From the ACD pin 16 voltage, the voltage is the meanACD*1400/1024
Does not seem right, the output is 4966.3634.
-
The other thing is lithium batteries are notoriously difficult to estimate in percentage. You wouldn't believe some of complexity of the algorithms the industry uses to make this appear as a nice and easy value for the user.
Take this typical LiPo discharge curve for example
You'll see that it's not linear, from about 90% to 5% the voltage remains almost const and only changes by about 3-5mV per %.
A simple formula like the one you posted would show the battery quickly falling to 50%, remaining around there for a very long time and then when finally dropping to around 40% would mean in reality the device was almost about to die.
-
@ledbelly2142
First I think it helps if you use the attenuation constants, e.g. ADC.ATTN_11DB instead of arbitrary meaningless numbers like 3.With ADC.ATTN_11DB the full range of the ADC is 3.9v so ADC reading 0 mean 0 volts and 4095 means 3.9v (but this is just a numeric range, don't feed it over 3.3V!)
The voltage divider on the expansion board "divides" the input voltage so that if the battery is at 4.2v you see ~ 1.4v into the ADC. This means the maximum ADC value - at ATTN_11DB - you would ever read for the battery (when at 4.2v) is 1.4 * 4095 / 3.9 = 1470.
This isn't very good because you're only using 1/3 of the range of the of the ADC , so I'd suggest using a lower attenuation.