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.
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.
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.