Hi @carlrowan,
I’d like to drag this topic back into the light.
I’m using the RAK4631-R RUI3 on a 19007 base, and see a similar scaling requirement of around 1.07 (thanks @Batto) when near a fully charged state. With a single reference point I don’t know what part is linear scaling and what part is offset.
Is RAK able to provide any guidance on getting accurate reliable voltage measurements out of the system call return value?
(I know the original post was about the 3172, but the 4631 is referenced and it’s really the same issue. I thought it better to keep the questions together rather than start a new thread.)
Edit:
I’ve been down this rabbit hole some more.
In the function service_battery_get_batt_level from file “service_battery.c”, in amongst all the “if defined”, “ifdef” and “ifndef” that have accumulated, are the following lines:
for (int i = 0 ; i < get_batt_table_size() ; i++) {
*bat_lvl = batt_table[i].batt_vol;
if (adc_value < batt_table[i].adc_val) {
break;
}
}
This steps through a 40 element table to find a not greater than match for the ADC value and exports a battery voltage rounded to 0.1V. The result of this linear search is then immediately overwritten unless you have a RAK3372+RAK5005-0_V1.0 defined. With a RAK11720 or RAK5010 it is overwritten again. I hope the compiler is smart enough to remove the dead code that the preprocessed source provides.
In the end, the relevant section is this:
#ifndef RAK3372+RAK5005-O_V1.0
*bat_lvl = ref_over_gain*(((float)adc_value)/max)*(5.0f)/(3.0f);
#endif
The ADC value is a 10bit value, and max is correctly chosen 1024.0. (*)
The 5.0/3.0 factor (correctly) represents the 1meg0/1meg5 resistor divider.
udrv_adc_get_mode() has (incorrectly?) returned UDRV_ADC_MODE_DEFAULT (0)
so ref_over_gain was set to 3.6V rather than 3.3V. (3.6/3.3 = 1.09)
I suspect that was where @Batto’s 1.07 comes from.
(* The variant.h file for RAK4631 should trigger 14bit ADC. Why this doesn’t happen is a topic for another rabbit hole)