5 #define BATTERY_ADC_SHIFT 6
6 #define RESISTOR_HI 1500 // kOhm
7 #define RESISTOR_LO 100 // kOhm
9 * The internal 1.1V reference has tolerance from 1.0 to 1.2V
10 * (datasheet, section 19.6). We have to measure the actual value
13 #define AREF_1100MV 1060 // mV
15 static volatile uint16_t battery_adcval;
16 volatile unsigned char battery_critical;
24 void battery_adc(uint16_t adcval)
26 if (battery_adcval == 0) {
27 battery_adcval = adcval << BATTERY_ADC_SHIFT;
28 } else { // running average
29 battery_adcval += (adcval
30 - (battery_adcval >> BATTERY_ADC_SHIFT));
34 unsigned char battery_100mv()
37 * This is tricky: we need to maintain precision, so we first
38 * multiply adcval by as big number as possible to fit uint16_t,
39 * then divide to get the final value,
40 * and finally type-cast it to unsigned char.
41 * We don't do running average, as the required precision
44 return (unsigned char)
46 (battery_adcval >> BATTERY_ADC_SHIFT)
48 * (RESISTOR_HI+RESISTOR_LO)/RESISTOR_LO // resistor ratio
49 / 4)) >> 8); // divide by 1024
52 /* convert value in mV to value of ADC shifted by BATTERY_ADC_SHIFT */
53 #define MV_TO_ADC(x) \
54 ((uint16_t)(((uint32_t)(x) * 1024 * (1 << BATTERY_ADC_SHIFT)) \
55 / ((uint32_t) AREF_1100MV \
56 * ((RESISTOR_HI+RESISTOR_LO)/RESISTOR_LO))))
58 /* convert value in mV to upper 8 bits of ADC value << BATTERY_ADC_SHIFT */
59 #define MV_TO_ADC8(x) ((unsigned char)(MV_TO_ADC(x) >> 8))
62 * Returns number from 1 to 10 (1 = battery almost empty, 10 = full)
63 * Lithium cells have voltage from about 2.9V to 4.1V. We consider battery
64 * above 4V full, and under 3.2V critically low. We guess whether
65 * the battery has two or three cells - voltages above 8.6V are considered
66 * from three-cell battery.
68 unsigned char battery_gauge()
70 unsigned char b8 = battery_adcval >> 8;
73 if (b8 < MV_TO_ADC8(2 * 3200)) {
75 } else if (b8 < MV_TO_ADC8(2 * 3475)) {
77 } else if (b8 < MV_TO_ADC8(2 * 3577)) {
79 } else if (b8 < MV_TO_ADC8(2 * 3620)) {
81 } else if (b8 < MV_TO_ADC8(2 * 3741)) {
83 } else if (b8 < MV_TO_ADC8(2 * 3775)) {
85 } else if (b8 < MV_TO_ADC8(2 * 3844)) {
87 } else if (b8 < MV_TO_ADC8(2 * 3930)) {
89 } else if (b8 < MV_TO_ADC8(2 * 4000)) {
91 } else if (b8 < MV_TO_ADC8(2 * 4300)) {
93 } else if (b8 < MV_TO_ADC8(3 * 3200)) { // three-cell battery
95 } else if (b8 < MV_TO_ADC8(3 * 3475)) {
97 } else if (b8 < MV_TO_ADC8(3 * 3577)) {
99 } else if (b8 < MV_TO_ADC8(3 * 3620)) {
101 } else if (b8 < MV_TO_ADC8(3 * 3741)) {
103 } else if (b8 < MV_TO_ADC8(3 * 3775)) {
105 } else if (b8 < MV_TO_ADC8(3 * 3844)) {
107 } else if (b8 < MV_TO_ADC8(3 * 3930)) {
109 } else if (b8 < MV_TO_ADC8(3 * 4000)) {
116 battery_critical = 1;