A weirdly specific question: I want to make a universal library for all my projects to give a few variables to at init and then have it store/read them to/from EEPROM on command (using put()/get() - make it accept custom structures). I tried to pass it a pointer to the variable and its size (in bytes for EEPROM addressing) but then kame the problem of the variable changing its location in RAM - the pointer vas not up-to-date. Now I have another not-working version, where I pass it a function to give it the pointer right before it need to be used (in EEPROM.put()/get()).
Here is the github repo: EEpromSettings
And the code itself:
EEpromSettings.h
#ifndef LIB_H
#define LIB_H
#include "Arduino.h"
/*TODO:
- EEPROM settings, pointer problems
- CRC check?
*/
using ptr = void*;
struct settingPointer {
ptr pointer;
size_t size;
};
typedef settingPointer* (*PtrUpdater)();
class EEpromSettings {
public:
EEpromSettings(byte projID, PtrUpdater pointerUpdater, size_t settingsCount, bool overwrite = true);
~EEpromSettings();
byte getEEpromProjID();
void updatePointers(ptr settingsPointers[]);
bool save();
bool load();
// private:
byte _projID;
settingPointer* _settingPointers;
size_t _settingsCount;
PtrUpdater _pointerUpdater;
};
#endif //LIB_H
EEpromSettings.cpp
#include "EEpromSettings.h"
#include <EEPROM.h>
EEpromSettings::EEpromSettings(byte projID, PtrUpdater pointerUpdater, size_t settingsCount, bool overwrite) : _projID(projID), _settingsCount(settingsCount) {
_settingPointers = new settingPointer[settingsCount];
_pointerUpdater = pointerUpdater;
if(overwrite && EEPROM.read(0) != _projID) {
EEPROM.update(0, _projID);
save();
Serial.println("Overwritten -> Saved defaults to EEPROM");
}
};
EEpromSettings::~EEpromSettings() {
delete[] _settingPointers;
};
byte EEpromSettings::getEEpromProjID() {
return EEPROM.read(0);
}
bool EEpromSettings::save() {
if (EEPROM.read(0) == _projID) {
int adress = 1;
size_t i = 0;
_settingPointers = _pointerUpdater();
while (i < _settingsCount) {
EEPROM.put(adress, _settingPointers[i].pointer);
adress += _settingPointers[i].size;
i++;
}
Serial.println("Saved values to EEPROM");
return true;
}
Serial.println("Failed to save values to EEPROM");
return false;
};
bool EEpromSettings::load() {
if (EEPROM.read(0) == _projID) {
int adress = 1;
size_t i = 0;
while (i < _settingsCount) {
_settingPointers = _pointerUpdater();
// Serial.println((int)_settingPointers[i].pointer);
EEPROM.get(adress, _settingPointers[i].pointer);
Serial.println((int)_settingPointers[1].pointer);
adress += _settingPointers[i].size;
i++;
}
Serial.println("Loaded values from EEPROM");
Serial.println((int)_settingPointers[1].pointer);
return true;
}
Serial.println("Failed to load values from EEPROM");
return false;
};
main.cpp (example and testing)
#include <Arduino.h>
#include <EEpromSettings.h>
struct myStruct {
byte x;
char y;
};
// char a[3] = "AB";
// int b = 1;
// myStruct c = { 5, 'f' };
char a[3] = "XX";
int b = 6;
myStruct c = { 0, 'x' };
#define SETTINGS_NUM 3
settingPointer settingPointers[SETTINGS_NUM];
settingPointer* settingsPtrUpdater() {
settingPointers[0] = {&a, sizeof(a)};
settingPointers[1] = {&b, sizeof(b)};
settingPointers[2] = {&c, sizeof(c)};
return settingPointers;
}
EEpromSettings eepromSettings(1, settingsPtrUpdater, SETTINGS_NUM, false);
void setup() {
Serial.begin(115200);
Serial.println();
Serial.print("poiter to b = "); Serial.println((int)&b);
Serial.print("ProjectID: 1, eepromProjectID: "); Serial.println(eepromSettings.getEEpromProjID());
Serial.println("Default values:");
Serial.print("a = "); Serial.println(a);
Serial.print("b = "); Serial.println(b);
Serial.print("c.x = "); Serial.println(c.x);
Serial.print("c.y = "); Serial.println(c.y);
// eepromSettings.save();
if (eepromSettings.load()) {
Serial.print("a = "); Serial.println(a);
Serial.print("b = "); Serial.println(b);
Serial.print("c.x = "); Serial.println(c.x);
Serial.print("c.y = "); Serial.println(c.y);
} else {
Serial.println("Failed to load values from EEPROM - different project ID?");
}
Serial.println("b value from pointer from settingPointers:");
Serial.println((int)settingPointers[1].pointer);
Serial.println(*static_cast<int*>(settingPointers[1].pointer));
Serial.println("b value from pointer from eepromSettings._settingPointers:");
Serial.println((int)eepromSettings._settingPointers[1].pointer);
Serial.println(*static_cast<int*>(eepromSettings._settingPointers[1].pointer));
Serial.print("poiter to b = "); Serial.println((int)&b);
}
void loop() {
//loop
}
So the questions:
- Is there a library, that does something like this?
- Is there a better way of doing it?
- Could solved using the new[] operator because the address doesn't change over time? Is it a problem if I create a few (eg. up to ten) of these variables and then don't delete[] them for them to last the entire duration of the program - which is until a sudden power loss (like a global variable)? Will the get deleted because RAM is volatile or do I really need to use delete[]?
- I also found something called smart pointers from C++ standard library. What's that? Could it maybe solve my problems?
Thanks for any kind of reply, I'm clueless
TheMoonlitWolf