void storeCurrentReading(byte _cNum, boolean _force) { if (_cNum >= 0 && _cNum < COUNTERS_COUNT) { int _currentEEPROMValue; _currentEEPROMValue = (int)eeprom_read_word(&eeprom_addr_currentReading[_cNum]); if (_currentEEPROMValue != currentReading[_cNum] || _force) { //eeprom_write_word(&eeprom_addr_currentReading[cNum], currentReading[cNum]); EEPROM.put(eeprom_addr_currentReading[_cNum], currentReading[_cNum]); EEPROM.put(eeprom_addr_currentReading_backup1[_cNum], currentReading[_cNum]); EEPROM.put(eeprom_addr_currentReading_backup2[_cNum], currentReading[_cNum]); Serial.println(F("INFO: Saved current reading to EEPROM.")); } //storeCurrentImpulses(_cNum, false); } } void restoreLastReading(byte _cNum) { //currentReading = (int)eeprom_read_word(&eeprom_addr_currentReading); unsigned long _currentReading, _currentReading_backup1, _currentReading_backup2; uint16_t _currentImpulsesCount; EEPROM.get(eeprom_addr_currentReading[_cNum], _currentReading); EEPROM.get(eeprom_addr_currentReading_backup1[_cNum], _currentReading_backup1); EEPROM.get(eeprom_addr_currentReading_backup2[_cNum], _currentReading_backup2); bool _restoredReading = false; if (debug) { Serial.println(); Serial.println(); Serial.print(F("trying to restore last reading for C")); Serial.print(_cNum + 1); Serial.println("..."); } if (_currentReading == _currentReading_backup1 && _currentReading == _currentReading_backup2) { // all good - take the value and go currentReading[_cNum] = _currentReading; _restoredReading = true; //if(debug) Serial.println(F("All stored readings are equal")); } else if ( (_currentReading == _currentReading_backup1) ) { // OK, 2 values are identical - go on currentReading[_cNum] = _currentReading; _restoredReading = true; if (debug) Serial.println(F("INFO: stored readings 1 and 2 are equal")); } else if ( (_currentReading == _currentReading_backup2) ) { // OK, 2 values are identical - go on currentReading[_cNum] = _currentReading; _restoredReading = true; if (debug) Serial.println(F("INFO: stored readings 1 and 3 are equal")); } else if ( (_currentReading_backup1 == _currentReading_backup2) ) { // OK, 2 values are identical - go on currentReading[_cNum] = _currentReading_backup1; _restoredReading = true; if (debug) Serial.println(F("INFO: stored readings 2 and 3 are equal")); } else { // not good - all stored values are different, so we donĀ“t know which one is right Serial.print(F("ERROR: FAILED to restore last reading of C")); Serial.println(_cNum + 1); //printCurrentReading(_cNum); } if (_restoredReading) { //Serial.print(F("Restored reading: ")); //Serial.print(currentReading); //Serial.print("."); //Serial.print(currentReadingImpulses); //Serial.println(); Serial.print(F("INFO: restored reading of C")); Serial.print(_cNum + 1); Serial.print("="); Serial.println(currentReading[_cNum]); //printCurrentReading(_cNum); } } void restoreAllLastData() { for (byte i = 0; i < COUNTERS_COUNT; i++) { restoreLastSavedImpulseCount(i, false); restoreLastReading(i); } } void printAllCurrentReadings() { for (byte i = 0; i < COUNTERS_COUNT; i++) { printCurrentReading(i, 0, false); } } void saveAllCurrentData(bool _force) { for (byte i = 0; i < COUNTERS_COUNT; i++) { storeCurrentImpulses(i, false); //if (_force) storeCurrentReading(i, true); storeCurrentReading(i, false); } Serial.println(F("INFO: saved all current data.")); } void restoreLastSavedImpulseCount(byte _cNum, bool _printOnly) { uint16_t _datasets, _offset, _addr, _maxAddrOffset, _nextOffset; uint16_t _lastWriteCounter = 0; uint16_t _currentWriteCounter = 0; uint16_t _currentData = 0; uint16_t _found_writeCounter = 0; uint16_t _found_data = 0; uint16_t _found_offset = 0; bool _foundData = false; if (debug || _printOnly) { Serial.println(); Serial.println(); Serial.print(F("trying to restore last impulses count for C")); Serial.print(_cNum + 1); Serial.println("..."); } _datasets = eeprom_addr_area_length_currentReadingImpulses[_cNum] / eeprom_datasetsize_currentReadingImpulses; if (debug || _printOnly) { Serial.print("datasets: "); Serial.println(_datasets); Serial.println(F("dSet\toffset\taddr\twC\tlwC\tdata\tvalid")); } // iterate over the EEPROM data area to find the dataset with the highest writecounter for (int i = 0; i < _datasets; i++) { _offset = i * eeprom_datasetsize_currentReadingImpulses; _addr = eeprom_addr_area_start_currentReadingImpulses[_cNum] + _offset; if (debug || _printOnly) { Serial.print((_offset / eeprom_datasetsize_currentReadingImpulses) + 1); Serial.print(" \t"); Serial.print(_offset); Serial.print(" \t"); Serial.print(_addr); } if (i > 0) { _lastWriteCounter = _currentWriteCounter; } EEPROM.get(_addr, _currentWriteCounter); EEPROM.get(_addr + 2, _currentData); if (debug || _printOnly) { Serial.print(" \t"); Serial.print(_currentWriteCounter); Serial.print("\t"); Serial.print(_lastWriteCounter); Serial.print("\t"); Serial.print(_currentData); } if ( i == 0 && _currentWriteCounter > 0) { // find data in first dataset _found_offset = _offset; _found_writeCounter = _currentWriteCounter; _found_data = _currentData; _foundData = true; if (debug || _printOnly) Serial.print("\tY"); } else if (_currentWriteCounter == (_lastWriteCounter + 1)) { // this dataset holds valid data if (debug || _printOnly) Serial.print("\tY"); _found_offset = _offset; _found_writeCounter = _currentWriteCounter; _found_data = _currentData; _foundData = true; } else { // stop the for loop as we already found what we were looking for // (or did not find anything) i = _datasets + 1; if (debug || _printOnly) Serial.print("\tN"); } if (debug || _printOnly) Serial.println(); } if (!_foundData) { if (debug || _printOnly) { Serial.print(F("NOTHING FOUND - EEPROM area seems empty for C")); Serial.println(_cNum + 1); } if (!_printOnly) { eeprom_nextoffset_currentReadingImpulses[_cNum] = 0; eeprom_writecounter_currentReadingImpulses[_cNum] = 1; } } else { _maxAddrOffset = eeprom_addr_area_length_currentReadingImpulses[_cNum] - eeprom_datasetsize_currentReadingImpulses; if ((_found_offset + eeprom_datasetsize_currentReadingImpulses) > _maxAddrOffset) { _nextOffset = 0; } else _nextOffset = _found_offset + eeprom_datasetsize_currentReadingImpulses; if (!_printOnly) { eeprom_nextoffset_currentReadingImpulses[_cNum] = _nextOffset; eeprom_writecounter_currentReadingImpulses[_cNum] = _found_writeCounter; currentReadingImpulses[_cNum] = _found_data; currentReadingImpulses_saved[_cNum] = _found_data; Serial.print(F("INFO: restored impulse counter of C")); } else { if (debug || _printOnly) Serial.print(F("INFO: printing stored impulse counter of C")); } //if (debug || _printOnly) { Serial.print(_cNum + 1); Serial.print(F(": data=")); Serial.print(_found_data); if (debug || _printOnly) { Serial.print(F(", wCount=")); Serial.print(_found_writeCounter); Serial.print(F(", dSet=")); Serial.print((_found_offset / eeprom_datasetsize_currentReadingImpulses) + 1); Serial.print(F(", offset=")); Serial.print(_found_offset); Serial.print(F(", nOffset=")); Serial.println(_nextOffset); } else Serial.println(); //} } //getCurrentReading(); } void storeCurrentImpulses(byte _cNum, bool _force) { if (_force || (currentReadingImpulses_saved[_cNum] != currentReadingImpulses[_cNum])) { uint16_t _addr, _nextAddrOffset, _maxAddrOffset, _datasets; if (eeprom_writecounter_currentReadingImpulses[_cNum] == 65535) { // if this write rolls over the writecounter variable (uint16_t) // set write counter to 1 (0 is defined invalid) and write to offset 0 eeprom_writecounter_currentReadingImpulses[_cNum] = 1; eeprom_nextoffset_currentReadingImpulses[_cNum] = 0; } else { eeprom_writecounter_currentReadingImpulses[_cNum]++; } _addr = eeprom_addr_area_start_currentReadingImpulses[_cNum] + eeprom_nextoffset_currentReadingImpulses[_cNum]; if (debug) { Serial.print(F("storeCurrentImpulses: C")); Serial.print(_cNum + 1); Serial.print(F(" data=")); Serial.print(currentReadingImpulses[_cNum]); Serial.print(F(", wCount=")); Serial.print(eeprom_writecounter_currentReadingImpulses[_cNum]); Serial.print(F(", offset=")); Serial.print(eeprom_nextoffset_currentReadingImpulses[_cNum]); Serial.print(F(", dSet=")); Serial.println((eeprom_nextoffset_currentReadingImpulses[_cNum] / eeprom_datasetsize_currentReadingImpulses) + 1); } // write data first, then writecounter, in case a power failure occurs EEPROM.put(_addr + 2, currentReadingImpulses[_cNum]); EEPROM.put(_addr, eeprom_writecounter_currentReadingImpulses[_cNum]); Serial.println(F("INFO: saved current pulses count to EEPROM")); currentReadingImpulses_saved[_cNum] = currentReadingImpulses[_cNum]; pulsesLastSaved_seconds[_cNum] = seconds; //_datasets = eeprom_addr_area_length_currentReadingImpulses[_cNum] / eeprom_datasetsize_currentReadingImpulses; _nextAddrOffset = eeprom_nextoffset_currentReadingImpulses[_cNum] + eeprom_datasetsize_currentReadingImpulses; _maxAddrOffset = eeprom_addr_area_length_currentReadingImpulses[_cNum] - eeprom_datasetsize_currentReadingImpulses; if (_nextAddrOffset > _maxAddrOffset) { eeprom_nextoffset_currentReadingImpulses[_cNum] = 0; } else { eeprom_nextoffset_currentReadingImpulses[_cNum] = _nextAddrOffset; } } }