From 46814f777d237d08615d0a25152d2a6288b04305 Mon Sep 17 00:00:00 2001 From: Felix Mann Date: Wed, 10 Feb 2016 19:44:30 +0100 Subject: [PATCH] Added persistent storage! Every KWH the counter is stored. Will change to a regular interval later on to reduce flash memory wear. --- README.md | 4 ++- code/oakpowerboard/eepromanything.h | 24 +++++++++++++++++ code/oakpowerboard/oakpowerboard.ino | 40 ++++++++++++++++++++-------- 3 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 code/oakpowerboard/eepromanything.h diff --git a/README.md b/README.md index e3f3210..c3e3f29 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ Done: - [X] Show (& calc) total consumption - [X] Use interrupts to get button input + pulses - [X] Use button input to switch between frames +- [X] Persistent storage of KWh counter Future wishes: -- [ ] Persistant storage of KWh counter - [ ] Add NTP time to sketch - [ ] Implement timezone offset, apply to current time - [ ] Keep track of total consumption for the day (and display this) @@ -27,12 +27,14 @@ Future wishes: - [ ] Multi-SSID - [ ] Store measurements while there is no Wi-Fi connection - [ ] Work stand-alone (without Wi-Fi connection) without switching to Config mode +- [ ] Reduce Flash memory wear by writing periodically instead of on every KWh increment ##Resources used * [SparkFun Eagle Libraries](https://github.com/sparkfun/SparkFun-Eagle-Libraries) by [SparkFun](https://github.com/sparkfun) * [TCRT5000 Eagle Library](https://github.com/mohamedpsx/Eagle-Libraries) by [mohamedpsx](https://github.com/mohamedpsx) * [esp8266-oled-ssd1306](https://github.com/squix78/esp8266-oled-ssd1306) by [squix78](https://github.com/squix78)) +* [EEPROMWriteAnything](http://playground.arduino.cc/Code/EEPROMWriteAnything) by the Arduino Community * [AirSensor Energy Monitor tutorial](http://www.airsensor.co.uk/component/zoo/item/energy-monitor.html) * [nongnu.org dtostrf](http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42) diff --git a/code/oakpowerboard/eepromanything.h b/code/oakpowerboard/eepromanything.h new file mode 100644 index 0000000..9a5299b --- /dev/null +++ b/code/oakpowerboard/eepromanything.h @@ -0,0 +1,24 @@ +#include +#include // for type definitions + +template int EEPROM_writeAnything(int ee, const T& value) +{ + const byte* p = (const byte*)(const void*)&value; + unsigned int i; + EEPROM.begin(sizeof(value)); + for (i = 0; i < sizeof(value); i++) + EEPROM.write(ee++, *p++); + EEPROM.end(); + return i; +} + +template int EEPROM_readAnything(int ee, T& value) +{ + byte* p = (byte*)(void*)&value; + unsigned int i; + EEPROM.begin(sizeof(value)); + for (i = 0; i < sizeof(value); i++) + *p++ = EEPROM.read(ee++); + EEPROM.end(); + return i; +} diff --git a/code/oakpowerboard/oakpowerboard.ino b/code/oakpowerboard/oakpowerboard.ino index 300ee54..d185e93 100644 --- a/code/oakpowerboard/oakpowerboard.ino +++ b/code/oakpowerboard/oakpowerboard.ino @@ -9,9 +9,20 @@ #include "font/roboto_thin_20.h" #include "images.h" +#include + +#include "eepromanything.h" + #define PULSES_PER_KWH 375 #define WH_PER_PULSE (1000.0F / PULSES_PER_KWH) +struct config_t +{ + int state; + float consumption_total; + int pulse_count_current_kwh; +} storage; + #define BTN_1 9 #define BTN_2 8 #define BTN_3 7 @@ -19,13 +30,12 @@ #define PULSE_PIN 5 #define DEBUG_LED 10 -int pulse_count_current_kwh; +#define EEPROM_READ_ADDR 0 -float consumption_total = 56712.0f; -char consumption_total_str[10] = "56712.00"; +char consumption_total_str[10] = "00000.00"; float consumption_current = 0.0F; -char consumption_current_str[6] = "00000"; +char consumption_current_str[6] = "Wait"; long time_since_last_pulse = millis(); @@ -80,6 +90,15 @@ void trigger_pulse() { } void setup() { + EEPROM_readAnything(EEPROM_READ_ADDR, storage); + if(storage.state != 0xF7) { + storage.state = 0xF7; + storage.consumption_total = 56712.0f; + storage.pulse_count_current_kwh = 0; + EEPROM_writeAnything(EEPROM_READ_ADDR, storage); + } + dtostrf(storage.consumption_total, 6, 2, consumption_total_str); + ui.setTargetFPS(30); ui.setActiveSymbole(activeSymbole); ui.setInactiveSymbole(inactiveSymbole); @@ -115,8 +134,6 @@ void setup() { attachInterrupt(digitalPinToInterrupt(BTN_4), toggle_b4, FALLING); } -bool btn_state = false; - void loop() { int remainingTimeBudget = ui.update(); long deadline = millis() + remainingTimeBudget; @@ -144,13 +161,14 @@ void loop() { } if(pulse_triggered == true) { - pulse_count_current_kwh++; - if(pulse_count_current_kwh == PULSES_PER_KWH) { - consumption_total++; - pulse_count_current_kwh = 0; + storage.pulse_count_current_kwh++; + if(storage.pulse_count_current_kwh == PULSES_PER_KWH) { + storage.consumption_total++; + storage.pulse_count_current_kwh = 0; + EEPROM_writeAnything(EEPROM_READ_ADDR, storage); } consumption_current = get_consumption_from_time_since_last_pulse(time_since_last_pulse); - dtostrf(consumption_total + ((((float)pulse_count_current_kwh) * WH_PER_PULSE) / 1000.0F), 6, 2, consumption_total_str); + dtostrf(storage.consumption_total + ((((float)storage.pulse_count_current_kwh) * WH_PER_PULSE) / 1000.0F), 6, 2, consumption_total_str); dtostrf(consumption_current, 4, 0, consumption_current_str); time_since_last_pulse = millis(); pulse_triggered = false;