Sofirn SP10 Pro Voltage Correction Factor Issue

The Voltage Correction Factor on my "Sofirn SP10 Pro" with Anduril Version "2022 04 18 0631" adjusts the voltage reported by the Battery Check Function in increments of "0.1 volts" instead of increments of "0.05 volts" as documented in ToyKeeper's Manual at:

http://toykeeper.net/torches/fsm/anduril2/anduril-manual.txt

The Voltage Correction Factor Increment can be verified using the difference reported by the Battery Check Function between the two extreme Voltage Correction Factor settings.

For example on my SP10 Pro:

With a "Battery Charged to 3.73 Volts" and the Voltage Correction Factor set to "1 Click" (which normally is a "-0.30 offset") the Battery Check Function reported "3.1".

With a "Battery Charged to 3.73 Volts" and the Voltage Correction Factor set to "13 Clicks" (which normally is a "+0.30 offset") the Battery Check Function reported "4.3".

The difference reported by the Battery Check Function between these two extremes was "4.3 - 3.1 = 1.2 Volts" (due to a 0.1 increment) but normally is only "2 x 0.30 = 0.6 Volts" (with a 0.05 increment).

I noticed this issue while calibrating the Voltage Correction Factor using the method documented in thread:

https://budgetlightforum.com/t/easy-method-for-setting-the-anduril-2-voltage-correction-factor/69798

which is:

"There will be two adjacent Voltage Correction Factor settings that allow the Battery Check Function to blink out 3.7 for a battery charged to 3.73 Volts. Choose the one that can be selected with the least amount of clicks."

tl;dr version: I think the manual is wrong

I’ve never actually used the Voltage Correction Factor feature. I also didn’t mess with it in my build; I left it the way TK designed it. In looking at her code, I’m pretty sure it’s designed to make adjustments in 0.1V increments despite what the manual says.

static inline uint8_t calc_voltage_divider(uint16_t value) {
    // use 9.7 fixed-point to get sufficient precision
    uint16_t adc_per_volt = ((ADC_44<<5) - (ADC_22<<5)) / (44-22);
    // shift incoming value into a matching position
    uint8_t result = ((value>>1) / adc_per_volt)
                     + VOLTAGE_FUDGE_FACTOR
                     #ifdef USE_VOLTAGE_CORRECTION
                     + voltage_correction - 7
                     #endif
                     ;
    return result;
}

This function looks at the ADC reading and computes/returns volts. Well, it’s actually volts*10. So for 3.7 volts, the function returns 37. You can see that it’s adding the voltage_correction setting and subtracting 7 (since the correction amount is zero’ed at 7). Keeping with the 3.7 volt example… If you have the correction at the default of 7 (no adjustment), it’s going to be 37 + 7 - 7 = 37. Let’s say you change the correction setting to 13, that give you 37 + 13 - 7 = 43 (4.3 volts). So maybe she was thinking that doing 0.05V increments would be good to do, but then coded it differently? I dunno for sure.

Thanks for your reply gchart.

Besides the Sofirn SP10 Pro, I have three other Anduril-2 lights (Sofirn IF25A, Lumintop FWAA, & Wurkkos TS10) and each of those uses a Voltage Correction Factor increment of 0.05 volts as verified using the difference reported by the Battery Check Function between the two extreme Voltage Correction Factor settings.

I don't understand the code, but did enjoy seeing it. Hopefully ToyKeeper can clarify why some lights use a 0.05 increment and others use a 0.1 increment for the Voltage Correction Factor.


As a Side Note:

Thanks to all who made the SP10 Pro a reality. The ability to use multiple battery chemistries is both practical and impressive. Also, the SP10 Pro's capabilities along with some NiMH batteries and a wall outlet charger will be the perfect special gift for responsible children that may be a little too young for Li-ion batteries but are inquisitive enough to enjoy Anduril.

Ah hah, I found it! The clue about other lights that actually were 0.05V increments helped.

The difference is that the SP10 Pro uses a “voltage divider” to read the battery voltage. Essentially, it reads voltage through some resistors attached to the MCU instead of reading that voltage coming into the MCU directly for power. Boost drivers (and a few other) have to read voltage from a pin because of how they work electrically.

These are coded differently. For lights with a voltage divider, the correction factor is added on and that’s the end of the calculation. But for drivers that read voltage from the power input, the code basically doubles the reading, adds the correction factor, and then divides the result in half. Hence the 0.05 resolution.

I’m kinda surprised this is the first time this has been brought up. I’m not sure whether this should be considered a bug or just an observation on how things work.

Also, you’re welcome! :smiley:

Sounds like this is a bug in the voltage divider code. It should be 0.05V on all lights.

To fix it, I think it can simply right-shift after adding instead of before.

Edit: Fixed.

Thanks TK! I was just testing the exact same patch. I flashed it onto my SP10 Pro and confirm it’s now properly doing 0.05V increments. I’ve also went ahead and merged in all updates from your branch (there weren’t many, mostly just breaking out D1V2 and DM11 into 3 versions each).

For those that have a UPDI flashing rig, an updated hex file can be found here