pvvx / ATC_MiThermometer

Custom firmware for the Xiaomi Thermometers and Telink Flasher
https://github.com/pvvx/pvvx.github.io/tree/master/ATC_MiThermometer
Other
2.75k stars 196 forks source link

Adjust battery percentage calculation to avoid integer rounding and overflowing. #524

Closed Cossid closed 1 week ago

Cossid commented 1 week ago

I am testing some LIR2032 batteries, which have a higher full capacity, around 4.02V (4020mV) [nominal ~3.7V], and as a result, I am running into an overflow. In looking into this, there is also a rounding error which is minor, which was causing some precision loss.

There were two choices to resolve this, the first is to remove the rounding error, which I chose here, so that instead of (max-min)/100 getting rounded from 7.5 to 7, we just multiply the other side by 100 instead and keep it integer based until the end. This fix should allow it to work correctly (relatively) with voltages up to around 4112mV. This issue was causing the battery percentage (which is obviously relative) to be incorrect by up to 7% and overflowing at around 3985mV.

The other option, should 4112mV not be enough would be to change the battery_level to uint16_t until the calculation is complete and then cast it back to uint8_t at the return.

Obviously this isn't a full solution to change the calculation based on different nominal voltages, but it will keep the rechargeable batteries from showing really low values when full before crossing back under the overflow and reporting 100%.

pvvx commented 1 week ago

When the power supply exceeds 3.6V, the TLSR825x chips degrade. Even a short-term excess leads to an increase in consumption by the chip in the future. You'll have to change the chip. Tested on several chips.

In the case of using LIR2032, it is necessary to supplement the circuit with a stabilizer or low-power diodes connected in series with the batteries so that the drop across them is more than 0.8V.

The LCD controller and screen will be illuminated when the power supply is more than 3.0 V. The circuit is designed to operate from 2.0 to 3.0 V. The TLSR825x chip itself has a minimum operating voltage of up to 1.8V, but for some options of built-in SPi-Flash it is advisable not to go below 1.9V.

Cossid commented 1 week ago

Noted on the degradation and adjustments needed to properly utilize LIR batteries. This change however does also make regular battery measurements more accurate, as it is currently trying to divide by 7.5 but is being integer rounded to 7, which means it's calculating a full battery at ~107% and just clamping it down to 100.

pvvx commented 1 week ago

Doesn't matter. The assigned voltage limits for conversion to percentages are conditional.

pvvx commented 1 week ago

The correction is incorrect. When multiplied by 100, a 16-bit value overflows! (3300-2200)*100=110000

Cossid commented 1 week ago

Sorry, please just revert then. I wasn't sure if it was calculating with different precision before storing the value. This is something that is technically undefined, and different platforms handle this differently, even when using uint16 types, you can sometimes calculate larger values as long as the stored result fits depending on the register size.

Edit: A hacky fix that fits within the confines of uint16_t would be to multiply the numerator by 2 and change the denominator from /100 to /50 as that would make the denominator an integer number again