diff --git a/thermidity-avr/bitmaps.c b/thermidity-avr/bitmaps.c index 28b015d..bddbee1 100644 --- a/thermidity-avr/bitmaps.c +++ b/thermidity-avr/bitmaps.c @@ -11,65 +11,113 @@ #include "utils.h" const uint8_t BAT_0PCT_DATA[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, - 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, + 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x3c, 0x30, 0x00, 0x00, 0x3c, - 0x30, 0x00, 0x00, 0x3c, 0x30, 0x00, 0x00, 0x3c, + 0x30, 0x00, 0x00, 0x3c, 0x30, 0x00, 0x00, 0x3c, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const uint8_t BAT_13PCT_DATA[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x3c, 0x00, 0x00, 0x30, 0x3c, 0x00, 0x00, 0x30, + 0x3c, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x3c, + 0x3c, 0x00, 0x00, 0x3c, 0x3c, 0x00, 0x00, 0x3c, + 0x3c, 0x00, 0x00, 0x30, 0x3c, 0x00, 0x00, 0x30, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const uint8_t BAT_25PCT_DATA[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, - 0x3f, 0xc0, 0x00, 0x30, 0x3f, 0xc0, 0x00, 0x30, - 0x3f, 0xc0, 0x00, 0x3c, 0x3f, 0xc0, 0x00, 0x3c, - 0x3f, 0xc0, 0x00, 0x3c, 0x3f, 0xc0, 0x00, 0x3c, - 0x3f, 0xc0, 0x00, 0x30, 0x3f, 0xc0, 0x00, 0x30, + 0x3f, 0x80, 0x00, 0x30, 0x3f, 0x80, 0x00, 0x30, + 0x3f, 0x80, 0x00, 0x3c, 0x3f, 0x80, 0x00, 0x3c, + 0x3f, 0x80, 0x00, 0x3c, 0x3f, 0x80, 0x00, 0x3c, + 0x3f, 0x80, 0x00, 0x30, 0x3f, 0x80, 0x00, 0x30, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const uint8_t BAT_38PCT_DATA[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x3f, 0xf0, 0x00, 0x30, 0x3f, 0xf0, 0x00, 0x30, + 0x3f, 0xf0, 0x00, 0x3c, 0x3f, 0xf0, 0x00, 0x3c, + 0x3f, 0xf0, 0x00, 0x3c, 0x3f, 0xf0, 0x00, 0x3c, + 0x3f, 0xf0, 0x00, 0x30, 0x3f, 0xf0, 0x00, 0x30, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const uint8_t BAT_50PCT_DATA[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, - 0x3f, 0xff, 0x00, 0x30, 0x3f, 0xff, 0x00, 0x30, - 0x3f, 0xff, 0x00, 0x3c, 0x3f, 0xff, 0x00, 0x3c, - 0x3f, 0xff, 0x00, 0x3c, 0x3f, 0xff, 0x00, 0x3c, - 0x3f, 0xff, 0x00, 0x30, 0x3f, 0xff, 0x00, 0x30, + 0x3f, 0xfe, 0x00, 0x30, 0x3f, 0xfe, 0x00, 0x30, + 0x3f, 0xfe, 0x00, 0x3c, 0x3f, 0xfe, 0x00, 0x3c, + 0x3f, 0xfe, 0x00, 0x3c, 0x3f, 0xfe, 0x00, 0x3c, + 0x3f, 0xfe, 0x00, 0x30, 0x3f, 0xfe, 0x00, 0x30, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const uint8_t BAT_63PCT_DATA[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x3f, 0xff, 0xc0, 0x30, 0x3f, 0xff, 0xc0, 0x30, + 0x3f, 0xff, 0xc0, 0x3c, 0x3f, 0xff, 0xc0, 0x3c, + 0x3f, 0xff, 0xc0, 0x3c, 0x3f, 0xff, 0xc0, 0x3c, + 0x3f, 0xff, 0xc0, 0x30, 0x3f, 0xff, 0xc0, 0x30, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const uint8_t BAT_75PCT_DATA[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, - 0x3f, 0xff, 0xf8, 0x30, 0x3f, 0xff, 0xf8, 0x30, + 0x3f, 0xff, 0xf8, 0x30, 0x3f, 0xff, 0xf8, 0x30, 0x3f, 0xff, 0xf8, 0x3c, 0x3f, 0xff, 0xf8, 0x3c, - 0x3f, 0xff, 0xf8, 0x3c, 0x3f, 0xff, 0xf8, 0x3c, + 0x3f, 0xff, 0xf8, 0x3c, 0x3f, 0xff, 0xf8, 0x3c, 0x3f, 0xff, 0xf8, 0x30, 0x3f, 0xff, 0xf8, 0x30, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const uint8_t BAT_88PCT_DATA[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x3f, 0xff, 0xff, 0x30, 0x3f, 0xff, 0xff, 0x30, + 0x3f, 0xff, 0xff, 0x3c, 0x3f, 0xff, 0xff, 0x3c, + 0x3f, 0xff, 0xff, 0x3c, 0x3f, 0xff, 0xff, 0x3c, + 0x3f, 0xff, 0xff, 0x30, 0x3f, 0xff, 0xff, 0x30, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const uint8_t BAT_100PCT_DATA[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, - 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfc, - 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfc, + 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, - 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, + 0x3f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const Bitmap bitmaps[] PROGMEM = { {32, 16, BAT_0PCT_DATA}, + {32, 16, BAT_13PCT_DATA}, {32, 16, BAT_25PCT_DATA}, + {32, 16, BAT_38PCT_DATA}, {32, 16, BAT_50PCT_DATA}, + {32, 16, BAT_63PCT_DATA}, {32, 16, BAT_75PCT_DATA}, + {32, 16, BAT_88PCT_DATA}, {32, 16, BAT_100PCT_DATA} }; diff --git a/thermidity-avr/bitmaps.h b/thermidity-avr/bitmaps.h index 34dfb4c..951b8d4 100644 --- a/thermidity-avr/bitmaps.h +++ b/thermidity-avr/bitmaps.h @@ -11,10 +11,14 @@ #include #define BAT_0PCT 0 -#define BAT_25PCT 1 -#define BAT_50PCT 2 -#define BAT_75PCT 3 -#define BAT_100PCT 4 +#define BAT_13PCT 1 +#define BAT_25PCT 2 +#define BAT_38PCT 3 +#define BAT_50PCT 4 +#define BAT_63PCT 5 +#define BAT_75PCT 6 +#define BAT_88PCT 7 +#define BAT_100PCT 8 /** * A bitmap with its width and height, and data. diff --git a/thermidity-avr/meter.c b/thermidity-avr/meter.c index f394304..a04f58e 100644 --- a/thermidity-avr/meter.c +++ b/thermidity-avr/meter.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -18,7 +19,6 @@ #include "dejavu.h" #include "bitmaps.h" #include "display.h" -#include "usart.h" #include "utils.h" static uint32_t avgADCTmp = -1; @@ -98,11 +98,15 @@ * @param vBatx10 * @return index */ -static uint8_t bitmapBat(int8_t vBatx10) { - if (vBatx10 < 32) return BAT_0PCT; - if (vBatx10 < 36) return BAT_25PCT; - if (vBatx10 < 40) return BAT_50PCT; - if (vBatx10 < 44) return BAT_75PCT; +static uint8_t bitmapBat(int8_t vBatx10) { + if (vBatx10 < 31) return BAT_0PCT; + if (vBatx10 < 33) return BAT_13PCT; + if (vBatx10 < 35) return BAT_25PCT; + if (vBatx10 < 37) return BAT_38PCT; + if (vBatx10 < 39) return BAT_50PCT; + if (vBatx10 < 41) return BAT_63PCT; + if (vBatx10 < 43) return BAT_75PCT; + if (vBatx10 < 45) return BAT_88PCT; return BAT_100PCT; } @@ -119,6 +123,10 @@ return buf; } +int16_t getMVBat(void) { + return (avgMVBat >> EWMA_BS); +} + void measureValues(void) { avgADCTmp = convert(AREF_AVCC, PIN_TMP, true, avgADCTmp); avgADCRh = convert(AREF_AVCC, PIN_RH, true, avgADCRh); @@ -162,10 +170,10 @@ writeBitmap(0, 216, bitmapBat(vBatx10)); // temperature with label writeString(1, 0, dejavu, formatTmp(tmpx10)); - writeString(5, 152, unifont, "Temperature"); + writeString(5, 144, unifont, "Temperature"); // humidity with label writeString(8, 0, dejavu, formatRh(rh)); - writeString(12, 152, unifont, "Humidity"); + writeString(12, 144, unifont, "Humidity"); // update display doDisplay(); -} \ No newline at end of file +} diff --git a/thermidity-avr/meter.h b/thermidity-avr/meter.h index eddaae4..1baa718 100644 --- a/thermidity-avr/meter.h +++ b/thermidity-avr/meter.h @@ -30,9 +30,15 @@ #define RH_ADC_100 3225 // Vout = Vsupply * 0.7875 #define RH_ADC RH_ADC_100 - RH_ADC_0 +/** Battery cutoff voltage in millivolts */ +#define BAT_LOW 3000 + /** Weight of the exponential weighted moving average as bit shift */ #define EWMA_BS 4 +/** Returns the battery voltage in millivolts divided by 5 */ +int16_t getMVBat(void); + /** * Measures temperature, relative humidity and battery voltage and updates * the average values. diff --git a/thermidity-avr/pins.h b/thermidity-avr/pins.h index 8964f23..56eefa2 100644 --- a/thermidity-avr/pins.h +++ b/thermidity-avr/pins.h @@ -10,7 +10,7 @@ #include -/* Vref and Sensors */ +/* Sensors */ #define DDR_SENS DDRC #define PORT_SENS PORTC #define PIN_PWR PC1 diff --git a/thermidity-avr/thermidity.c b/thermidity-avr/thermidity.c index 2459215..e283002 100644 --- a/thermidity-avr/thermidity.c +++ b/thermidity-avr/thermidity.c @@ -33,7 +33,7 @@ #include "utils.h" #include "usart.h" -/* Measure and average temperature and relative humidity every 32 seconds */ +/* Measure and average temperature and relative humidity every ~32 seconds */ #define MEASURE_SECS 32 /* Display should not be updated more frequently than once every 180 seconds */ #define DISP_UPD_SECS 288 @@ -54,7 +54,7 @@ DDR_SENS |= (1 << PIN_PWR); // drive sensor power pin low PORT_SENS &= ~(1 << PIN_PWR); - + // set MOSI and SCK as output pin DDR_SPI |= (1 << PIN_MOSI); DDR_SPI |= (1 << PIN_SCK); @@ -78,7 +78,7 @@ // set display BUSY pin as input pin (default) DDR_DISP &= ~(1 << PIN_BUSY); - + // pull all unused pins high/set to defined level to reduce current // consumption when not in sleep mode PORTB |= (1 << PB6); @@ -161,6 +161,16 @@ PRR |= (1 << PRTWI) | (1 << PRTIM0) | (1 << PRTIM1) | (1 << PRTIM2) | (1 << PRUSART0); } +/** + * Disables global interrupts and the watchdog to stop measuring + * and updating the display when batteries are too weak, to limit + * discharging below cutoff voltage. + */ +static void powerDown(void) { + cli(); + wdt_disable(); +} + int main(void) { reducePower(); @@ -178,7 +188,7 @@ ATOMIC_BLOCK(ATOMIC_FORCEON) { secsCopy = secs; } - + if (secsCopy % MEASURE_SECS == 0) { powerOnSensors(); // give the humidity sensor time to settle @@ -192,11 +202,16 @@ ATOMIC_BLOCK(ATOMIC_FORCEON) { secs = 0; } - - displayValues(); + + // measured battery voltage is /5 by voltage divider + if (getMVBat() < BAT_LOW / 5) { + powerDown(); + } else { + displayValues(); + } } } - + set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_mode(); }