]> www.fi.muni.cz Git - bike-lights.git/commitdiff
battery.c: rework
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Wed, 27 Feb 2013 23:56:55 +0000 (00:56 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 28 Feb 2013 00:07:50 +0000 (01:07 +0100)
We can use values in mV instead of 100 mV. We can also provide
the battery level on scale from 1 to 10.

firmware/battery.c
firmware/lights.h

index 01337db1bb8c196fde0d0ff3efa61b1457bce7a8..d7123e95839a4af818f51c5bc1f73a8bd46a4541 100644 (file)
@@ -2,17 +2,30 @@
 
 #include "lights.h"
 
+#define BATTERY_ADC_SHIFT      6
 #define RESISTOR_HI    1500    // kOhm
 #define RESISTOR_LO     100    // kOhm
 
-volatile unsigned char battery_100mv = 0;
+static volatile uint16_t battery_adcval;
+volatile unsigned char battery_critical;
 
 void init_battery()
 {
-       battery_100mv = 0;
+       battery_adcval = 0;
+       battery_critical = 0;
 }
 
 void battery_adc(uint16_t adcval)
+{
+       if (battery_adcval == 0) {
+               battery_adcval = adcval << BATTERY_ADC_SHIFT;
+       } else { // running average
+               battery_adcval += (adcval
+                       - (battery_adcval >> BATTERY_ADC_SHIFT));
+       }
+}
+
+unsigned char battery_100mv()
 {
        /*
         * This is tricky: we need to maintain precision, so we first
@@ -22,9 +35,85 @@ void battery_adc(uint16_t adcval)
         * We don't do running average, as the required precision
         * is coarse (0.1 V).
         */
-       battery_100mv = (unsigned char)
-               ((uint16_t)(adcval * (11                   // 1.1V
+       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
 }
 
+/* convert value in mV to value of ADC shifted by BATTERY_ADC_SHIFT */
+#define MV_TO_ADC(x) \
+       ((uint16_t)(((uint32_t)(x) * 1024 * (1 << BATTERY_ADC_SHIFT)) \
+               / ((uint32_t) 1100 \
+                       * ((RESISTOR_HI+RESISTOR_LO)/RESISTOR_LO))))
+
+/* convert value in mV to upper 8 bits of ADC value << BATTERY_ADC_SHIFT */
+#define MV_TO_ADC8(x)  ((unsigned char)(MV_TO_ADC(x) >> 8))
+
+/*
+ * Returns number from 1 to 10 (1 = battery almost empty, 10 = full)
+ * Lithium cells have voltage from about 2.9V to 4.1V. We consider battery
+ * above 4V full, and under 3.2V critically low. We guess whether
+ * the battery has two or three cells - voltages above 8.6V are considered
+ * from three-cell battery.
+ */
+unsigned char battery_gauge()
+{
+       unsigned char b8 = battery_adcval >> 8;
+       unsigned char rv;
+
+       if        (b8 < MV_TO_ADC8(2 * 3200)) {
+               rv = 1;
+       } else if (b8 < MV_TO_ADC8(2 * 3475)) {
+               rv = 2;
+       } else if (b8 < MV_TO_ADC8(2 * 3577)) {
+               rv = 3;
+       } else if (b8 < MV_TO_ADC8(2 * 3620)) {
+               rv = 4;
+       } else if (b8 < MV_TO_ADC8(2 * 3741)) {
+               rv = 5;
+       } else if (b8 < MV_TO_ADC8(2 * 3775)) {
+               rv = 6;
+       } else if (b8 < MV_TO_ADC8(2 * 3844)) {
+               rv = 7;
+       } else if (b8 < MV_TO_ADC8(2 * 3930)) {
+               rv = 8;
+       } else if (b8 < MV_TO_ADC8(2 * 4000)) {
+               rv = 9;
+       } else if (b8 < MV_TO_ADC8(2 * 4300)) {
+               rv = 10;
+       } else if (b8 < MV_TO_ADC8(3 * 3200)) { // three-cell battery
+               rv = 1;
+       } else if (b8 < MV_TO_ADC8(3 * 3475)) {
+               rv = 2;
+       } else if (b8 < MV_TO_ADC8(3 * 3577)) {
+               rv = 3;
+       } else if (b8 < MV_TO_ADC8(3 * 3620)) {
+               rv = 4;
+       } else if (b8 < MV_TO_ADC8(3 * 3741)) {
+               rv = 5;
+       } else if (b8 < MV_TO_ADC8(3 * 3775)) {
+               rv = 6;
+       } else if (b8 < MV_TO_ADC8(3 * 3844)) {
+               rv = 7;
+       } else if (b8 < MV_TO_ADC8(3 * 3930)) {
+               rv = 8;
+       } else if (b8 < MV_TO_ADC8(3 * 4000)) {
+               rv = 9;
+       } else {
+               rv = 10;
+       }
+
+       if (rv == 1)
+               battery_critical = 1;
+
+#if 0
+       log_byte(0xbb);
+       log_byte(rv);
+       log_flush();
+#endif
+
+       return rv;
+}
index 753e281ca09e55bf95d5280d84b3ff2d1f2cff59..5032e1124b8633f2250a608632062192f63c536c 100644 (file)
@@ -88,9 +88,9 @@ pattern_t *buttons_setup_status0_pattern_select();
 pattern_t *buttons_setup_status1_pattern_select();
 
 /* battery.c */
-extern volatile unsigned char battery_100mv;
 void battery_adc();
 void init_battery();
+unsigned char battery_gauge();
 
 /* control.c */
 extern pattern_t on1_pattern[];