#include #include "lights.h" #define BATTERY_ADC_SHIFT 2 #define RESISTOR_HI 1500 // kOhm #define RESISTOR_LO 100 // kOhm /* * The internal 1.1V reference has tolerance from 1.0 to 1.2V * (datasheet, section 19.6). We have to measure the actual value * of our part. */ #define AREF_1100MV 1060 // mV static volatile uint16_t battery_adcval; static unsigned char initial_readings = 0; void init_battery() { battery_adcval = 0; initial_readings = 5; } unsigned char battery_100mv() { /* * This is tricky: we need to maintain precision, so we first * multiply adcval by as big number as possible to fit uint16_t, * then divide to get the final value, * and finally type-cast it to unsigned char. * We don't do running average, as the required precision * is coarse (0.1 V). */ return (unsigned char) ((uint16_t)( (battery_adcval >> BATTERY_ADC_SHIFT) * (11 // 1.1V * (RESISTOR_HI+RESISTOR_LO)/RESISTOR_LO // resistor ratio / 4)) >> 8); // divide by 1024 } void battery_adc(uint16_t adcval) { if (initial_readings) { initial_readings--; battery_adcval = adcval << BATTERY_ADC_SHIFT; } else if (battery_adcval == 0) { battery_adcval = adcval << BATTERY_ADC_SHIFT; } else { // running average battery_adcval += (adcval - (battery_adcval >> BATTERY_ADC_SHIFT)); } #if 0 log_byte(battery_100mv()); log_flush(); #endif } unsigned char battery_gauge() { unsigned char b8 = battery_100mv(); unsigned char rv; if (b8 < 70) { rv = 1; } else if (b8 < 75) { rv = 2; } else if (b8 < 80) { rv = 3; } else if (b8 < 85) { rv = 4; } else if (b8 < 90) { rv = 5; } else if (b8 < 95) { rv = 6; } else { rv = 7; } #if 0 if (rv == 1 && !initial_readings) set_error(ERR_BATTERY); #endif #if 0 log_byte(0xbb); log_byte(rv); log_flush(); #endif return rv; }