RAKWireless / WisBlock

Quickstart, tutorials and examples for the RAKwireless WisBlock product line.
https://www.rakwireless.com
MIT License
161 stars 117 forks source link

Battery level code uses too short sample (TACQ) time #45

Closed danak6jq closed 2 years ago

danak6jq commented 2 years ago

In examples/RAK4630/power/RAK4630_Battery_Level_Detect/Read_Battery_Level)/Read_Battery_Level.ino the output of the ADC for battery sense is multiplied by a mysterious number that's commented as depending on the board:

image

I'd expect the conversion of ADC value to be: ADC_Value VBAT_MV_PER_LSB DIVIDER_FACTOR, where DIVIDER_FACTOR is 1 / 0.6 -> 1.6666667 (aka 5/3).

But there's this magical 1.73 instead of the expected 1.666667. I'm guessing when this code was written, this conversion was reliably giving a slightly too-low value of battery voltage - so the developer externally measured the battery voltage and calculated the 1.73 factor.

The actual problem here is that the ADC is not initialized correctly for the high series resistance of the battery divider (600k). Using the spec of 2.5pF (typical) input capacitance to the ADC with 600k gives an RC time of 1.5uS. The default sample time is 3uS, so the sample capacitor does not completely charge in 2 RC, thus resulting in too low measurements. The minimum sample time is 5 RC and it doesn't hurt to go longer. (see https://www.electronics-tutorials.ws/rc/rc_1.html for details of RC time constants).

Given that ADC sample capacitor value will vary from part to part, this introduces a source of inaccuracy.

Suggest initializing the SAADC to a minimum of 10uS sample time and correcting the ADC conversion math.

I've tested with 40uS sample time and correct conversion math and see 0.3% error against externally measured.

danak6jq commented 2 years ago

This also impacts the LoRaWAN examples for GetBatteryLevel().

beegee-tokyo commented 2 years ago

It is written as an example, you are welcome to submit a pull-request with improvements.