diff --git a/Firmware/src/main.cpp b/Firmware/src/main.cpp index 9099b4b..79f6b65 100644 --- a/Firmware/src/main.cpp +++ b/Firmware/src/main.cpp @@ -31,11 +31,13 @@ #include #include #include +#include #include // secconfig.h Configures RF Module, TTN Keys / RF Networks and used Sensor #include "secconfig.h" +// Create needed Variables and Objects for RF Module #ifdef RF_LORA // Include LoRaWAN #include @@ -52,7 +54,7 @@ RFM69 radio; #endif -// Sensorclass and deepsleep interval (for measurement about every 10Min) +// Create Sensor Class #ifdef HAS_BME280 #include BME280 sensor; @@ -63,7 +65,7 @@ SHT21 sensor; #endif -// Global Variable used for deep sleep +// Global Variable to Track Deep Sleep uint16_t sleep_interval; #ifdef LED_PIN @@ -129,6 +131,22 @@ int32_t readVcc() { return result; } +// Crude Wear Leveling Algorithm to Spread the EEPROM Cell Wear Over +// the first 64 Byte. Using this Method the Theoretical EEPROM Livetime +// should be around 60 Years at a 10 Minute Sending Interval +// (100000 Erase Cycles per Cell * 32 Locations / 144 Measurements a day * 365) +// +// Returns the Next EEPROM Address for Saving the Frame Counter +uint8_t calcEepromAddr(uint16_t framecounter) { + uint8_t eeprom_addr = ((framecounter%32)*sizeof(framecounter)); + if (eeprom_addr == 0) { + eeprom_addr = 62; + } else { + eeprom_addr = eeprom_addr-sizeof(framecounter); + } + return eeprom_addr; +} + void setup() { // Initialize Sleep Timer @@ -139,9 +157,34 @@ void setup() // Setup LoraWAN rfm.init(); lora.setKeys(NwkSkey, AppSkey, DevAddr); + + // Get Framecounter from EEPROM + // Check if EEPROM is initialized + if (EEPROM.read(511) != 0x42) { + // Set first 64 byte to 0x00 for the wear leveling hack to work + for (int i = 0; i < 64; i++) + EEPROM.write(i, 0x00); + // Write the magic value so we know it's initialized + EEPROM.write(511, 0x42); + } else { + // Get the Last Saved (=Highest) Frame Counter + uint16_t Frame_Counter_Sv = 0x00000000; + uint8_t eeprom_addr = 0x0000; + EEPROM.get(eeprom_addr, Frame_Counter_Sv); + while (eeprom_addr < 32*sizeof(Frame_Counter_Tx)) { + if (Frame_Counter_Sv > Frame_Counter_Tx) { + Frame_Counter_Tx = Frame_Counter_Sv; + } else { + break; + } + eeprom_addr += sizeof(Frame_Counter_Tx); + EEPROM.get(eeprom_addr, Frame_Counter_Sv); + } + } #endif #ifdef RF_RFM69 + // Setup RFM69 Module radio.initialize(RF69_433MHZ,RFM69_NODEID,RFM69_NETWORKID); #ifdef RFM69_ENCKEY radio.encrypt(RFM69_ENCKEY); @@ -216,6 +259,8 @@ void loop() lora.Send_Data((unsigned char *)&data, sizeof(data), Frame_Counter_Tx, SF7BW125, 0x01); Frame_Counter_Tx++; #endif + // Save the next FrameCounter to EEPROM + EEPROM.put(calcEepromAddr(Frame_Counter_Tx), Frame_Counter_Tx); #endif #ifdef RF_RFM69