Go Down

Topic: EEPROM Storage issue (Read 993 times) previous topic - next topic

aq_mishu

Code: [Select]
void factoryEEPROMFlush(unsigned int memLimit){
  debug.print(F("Flushing 0 to ")); Serial.print(memLimit);Serial.println(F(" address blocks with NULL value."));
  digitalWrite(13, HIGH);
  for (uint16_t i=0; i <= memLimit; i++){
    EEPROM.update(i, NULL);
    debug.print(round((float(i)/float(memLimit))*100)); debug.println(F("% completed"));
    delay(5);
  }
  digitalWrite(13, LOW);
  debug.print(F("Flushed ")); Serial.print(memLimit);Serial.println(F(" addresses"));
  debug.println(F("Please do a power cycle."));
}


This is the factory EEPROM FLASH for filling entire eeprom with NULL (format command). Works fine for me except that showing fancy % is not fully upto the mark, but can be managed, as all I need is probably some if then clauses. I will discuss that fancy part later.

Let's come back to STRUCT, as promised...

Because Now so far things are in shape... I'm posting my current configs in a different thread, because this is going to be long. 

Since initially the topic is kind of solved, here the topic is closed. Rather opening a new thread for EEPROM STRUCT issue.

aq_mishu

As promised, here is my next post, eeprom saving using struct. I'm giving my current variables, eeprom address maps, etc. This will help to discuss and improve it further by making it via STRUCT.

Code: [Select]
//EEPROPM Addressings need to be re-check for more optimization
#define eepromOffset 0 //[Address 0, reserved]
#define devSL_eepromAddr (eepromOffset + 1) //[Start at 1, used for device SL (10byte incl NULL), ends at 11]
#define optHWEn_eepromAddr (devSL_eepromAddr + sizeof(devSL)) //[Start at 1+11=12, used for 1byte, ends at 12]
#define debugEn_eepromAddr (optHWEn_eepromAddr + sizeof(optHWEn)) //[Start at 12+1=13, used for 1byte, ends at 13]
#define targetTemp_eepromAddr (debugEn_eepromAddr + sizeof(debugEn)) //[Start at 13+1=14, used for 2byte, ends at 15]
#define deltaT_eepromAddr (targetTemp_eepromAddr + sizeof(targetTemp)) //[Start at 15+2=17, used for 1byte, ends at 17]
#define opsMode_eepromAddr (deltaT_eepromAddr + sizeof(deltaT)) //[Start at 16+1=17, used for 1byte, ends at 17]
#define compressorRunTime_eepromAddr (opsMode_eepromAddr + sizeof(opsMode)) //[Start at 17+1=18, used for 1byte, ends at 18] //we may avoid it and can put this in a variable as per update.
#define defrostTime_eepromAddr (compressorRunTime_eepromAddr + sizeof(compressorRunTime)) //[Start at 18+1=19, used for 1byte, ends at 19]
#define userPassword_eepromAddr (defrostTime_eepromAddr + sizeof(defrostTime)) //[Start at 19+1=20, used for 4byte, ends at 23]

#define lastUsedeepromAddr (userPassword_eepromAddr + sizeof(userPassword)) //Keep the last address in count.


The lastUsedeepromaddr is for a tracking, where it ended.

Variables are:
Code: [Select]
//necessary variables for running config (via structure)
#define deviceSLlength 10 //10 digit including NULL char [0-9 = 10 + 1 = 11]
#define userPasswordLength 4 //4 char incl NULL [0-3 = 4 + 1 = 5]

char devSL[deviceSLlength+1]; //10 digit device SL No including NULL char [0-9 total 10 + 1]
boolean optHWEn = false;
boolean debugEn = false;
int8_t targetTemp = 4; //default
uint8_t deltaT = 4; //default Delta T = 4
int8_t opsMode = 1; //default ops mode = 1
unsigned long compressorRunTime; //default 12 hrs.
unsigned long defrostTime; //default 30 mins
char userPassword[userPasswordLength+1] = "1111"; //default user password is 1111 [4 char + 1]


then my void setup () has this at some point as initializing task.
Code: [Select]
  debug.println(F("Booting..."));
  generate_devSL(deviceSLlength); //taken care in another post.
  splashScreen(); //fancy

  PowerOnSelfTest(); //other task

  // load the running config
  loadBootConf(); //here the variables are to be populated by reading from eeprom
  printBootConf(); //show the running config, means the data read from eeprom


Hope this above is clear to all... Then to store the data in eeprom I'm using a factory_default() function that sets the initial default parameters, saved into eeprom. (like traditional, set to factory default). Apart from this, I may need to change individual elements, like delta T, or target temp, etc. But deviceSL is a one time, and this has nothing to do with struct. Means eeprom's 0 address has a # as a device initialized marker and then next 11 address is for deviceSL. so keep that part reserved and away from struct.

Code: [Select]
//The factory reset function that will reset EEROM data into default.
void factoryReset(void){
  debug.println(F("Resetting all values to factory default..."));
  digitalWrite(systemStateLED, HIGH);
  EEPROM.update(optHWEn_eepromAddr, 0);
  delay(5);
  EEPROM.update(debugEn_eepromAddr, 0);
  delay(5);
  //EEPROMWriteInt(targetTemp_eepromAddr, 4);
  EEPROM.update(targetTemp_eepromAddr, 4);
  delay(5);
  //EEPROMWriteInt(deltaT_eepromAddr, 4);
  EEPROM.update(deltaT_eepromAddr, 4);
  delay(5);
  EEPROM.update(opsMode_eepromAddr, 1);
  delay(5);
  EEPROM.update(compressorRunTime_eepromAddr, 12);
  delay(5);
  EEPROM.update(defrostTime_eepromAddr, 30);
  delay(5);
  //EEPROMWriteLong(userPassword_eepromAddr, 1111);
  userPassword[userPasswordLength] = "1111";
  eeprom_write_string(userPassword_eepromAddr, userPassword);
  delay(5);
  digitalWrite(systemStateLED, LOW);
  debug.println(F("Done!"));
  debug.println();
  loadBootConf();
  printBootConf();
  debug.print(F("Default User Password: ")); debug.println(userPassword);
  soft_reset(3000);
}


and boot conf loader, called from void setup mostly, except for few other times from void main is:
Code: [Select]
//Function for loading the conf during boot. Also the same function is used to call the runtime conf after a new conf settings changed.
void loadBootConf(void){
 
  optHWEn = EEPROM.read(optHWEn_eepromAddr);
  debugEn = EEPROM.read(debugEn_eepromAddr);
  //targetTemp = EEPROMReadInt(targetTemp_eepromAddr);
  targetTemp = EEPROM.read(targetTemp_eepromAddr);
  //deltaT = EEPROMReadInt(deltaT_eepromAddr);
  deltaT = EEPROM.read(deltaT_eepromAddr);
  opsMode = EEPROM.read(opsMode_eepromAddr);
  compressorRunTime = (EEPROM.read(compressorRunTime_eepromAddr) * 3600000); //eeprom value in hours. Hence 3600000 ms
  defrostTime = (EEPROM.read(defrostTime_eepromAddr) * 60000); //eeprom value in minutes, hence 60000 ms
  eeprom_read_string(userPassword_eepromAddr, userPassword, sizeof(userPassword));

  //*** IMPORTANT! *** the blelow part is still require more study
  switch (opsMode) {
    case 1:
      lowTempLimit = (targetTemp - (deltaT/2));
      //hiTempLimit = (targetTemp + (deltaT/2));
      hiTempLimit = (lowTempLimit + deltaT);

    case 2:
      lowTempLimit = targetTemp;
      hiTempLimit = (lowTempLimit + deltaT);

    case 3:
      lowTempLimit = (targetTemp - 1);
      hiTempLimit = (lowTempLimit + deltaT);

    default:
      lowTempLimit = (targetTemp - (deltaT/2));
      hiTempLimit = (targetTemp + (deltaT/2));
  }
 
}


Now struct part begins....

UKHeliBob

Quote
This is the factory EEPROM FLASH for filling entire eeprom with NULL
As long as the value of memLimit is correct, of course

Quote
Because Now so far things are in shape... I'm posting my current configs in a different thread, because this is going to be long.

Since initially the topic is kind of solved, here the topic is closed. Rather opening a new thread for EEPROM STRUCT issue.
I don't think that is such a good idea because all of the background to the problem is here.  Expect a new topic to be merged with this one if you start it
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

aq_mishu

As long as the value of memLimit is correct, of course
I don't think that is such a good idea because all of the background to the problem is here.  Expect a new topic to be merged with this one if you start it
Noted... since posted, here is the again posting those...

aq_mishu

As promised, here is my next post, eeprom saving using struct. I'm giving my current variables, eeprom address maps, etc. This will help to discuss and improve it further by making it via STRUCT.

Code: [Select]
//EEPROPM Addressings need to be re-check for more optimization
#define eepromOffset 0 //[Address 0, reserved]
#define devSL_eepromAddr (eepromOffset + 1) //[Start at 1, used for device SL (10byte incl NULL), ends at 11]
#define optHWEn_eepromAddr (devSL_eepromAddr + sizeof(devSL)) //[Start at 1+11=12, used for 1byte, ends at 12]
#define debugEn_eepromAddr (optHWEn_eepromAddr + sizeof(optHWEn)) //[Start at 12+1=13, used for 1byte, ends at 13]
#define targetTemp_eepromAddr (debugEn_eepromAddr + sizeof(debugEn)) //[Start at 13+1=14, used for 2byte, ends at 15]
#define deltaT_eepromAddr (targetTemp_eepromAddr + sizeof(targetTemp)) //[Start at 15+2=17, used for 1byte, ends at 17]
#define opsMode_eepromAddr (deltaT_eepromAddr + sizeof(deltaT)) //[Start at 16+1=17, used for 1byte, ends at 17]
#define compressorRunTime_eepromAddr (opsMode_eepromAddr + sizeof(opsMode)) //[Start at 17+1=18, used for 1byte, ends at 18] //we may avoid it and can put this in a variable as per update.
#define defrostTime_eepromAddr (compressorRunTime_eepromAddr + sizeof(compressorRunTime)) //[Start at 18+1=19, used for 1byte, ends at 19]
#define userPassword_eepromAddr (defrostTime_eepromAddr + sizeof(defrostTime)) //[Start at 19+1=20, used for 4byte, ends at 23]

#define lastUsedeepromAddr (userPassword_eepromAddr + sizeof(userPassword)) //Keep the last address in count.


The lastUsedeepromaddr is for a tracking, where it ended.

Variables are:
Code: [Select]
//necessary variables for running config (via structure)
#define deviceSLlength 10 //10 digit including NULL char [0-9 = 10 + 1 = 11]
#define userPasswordLength 4 //4 char incl NULL [0-3 = 4 + 1 = 5]

char devSL[deviceSLlength+1]; //10 digit device SL No including NULL char [0-9 total 10 + 1]
boolean optHWEn = false;
boolean debugEn = false;
int8_t targetTemp = 4; //default
uint8_t deltaT = 4; //default Delta T = 4
int8_t opsMode = 1; //default ops mode = 1
unsigned long compressorRunTime; //default 12 hrs.
unsigned long defrostTime; //default 30 mins
char userPassword[userPasswordLength+1] = "1111"; //default user password is 1111 [4 char + 1]


then my void setup () has this at some point as initializing task.
Code: [Select]
 debug.println(F("Booting..."));
  generate_devSL(deviceSLlength); //taken care in another post.
  splashScreen(); //fancy

  PowerOnSelfTest(); //other task

  // load the running config
  loadBootConf(); //here the variables are to be populated by reading from eeprom
  printBootConf(); //show the running config, means the data read from eeprom


Hope this above is clear to all... Then to store the data in eeprom I'm using a factory_default() function that sets the initial default parameters, saved into eeprom. (like traditional, set to factory default). Apart from this, I may need to change individual elements, like delta T, or target temp, etc. But deviceSL is a one time, and this has nothing to do with struct. Means eeprom's 0 address has a # as a device initialized marker and then next 11 address is for deviceSL. so keep that part reserved and away from struct.

Code: [Select]
//The factory reset function that will reset EEROM data into default.
void factoryReset(void){
  debug.println(F("Resetting all values to factory default..."));
  digitalWrite(systemStateLED, HIGH);
  EEPROM.update(optHWEn_eepromAddr, 0);
  delay(5);
  EEPROM.update(debugEn_eepromAddr, 0);
  delay(5);
  //EEPROMWriteInt(targetTemp_eepromAddr, 4);
  EEPROM.update(targetTemp_eepromAddr, 4);
  delay(5);
  //EEPROMWriteInt(deltaT_eepromAddr, 4);
  EEPROM.update(deltaT_eepromAddr, 4);
  delay(5);
  EEPROM.update(opsMode_eepromAddr, 1);
  delay(5);
  EEPROM.update(compressorRunTime_eepromAddr, 12);
  delay(5);
  EEPROM.update(defrostTime_eepromAddr, 30);
  delay(5);
  //EEPROMWriteLong(userPassword_eepromAddr, 1111);
  userPassword[userPasswordLength] = "1111";
  eeprom_write_string(userPassword_eepromAddr, userPassword);
  delay(5);
  digitalWrite(systemStateLED, LOW);
  debug.println(F("Done!"));
  debug.println();
  loadBootConf();
  printBootConf();
  debug.print(F("Default User Password: ")); debug.println(userPassword);
  soft_reset(3000);
}


and boot conf loader, called from void setup mostly, except for few other times from void main is:
Code: [Select]
//Function for loading the conf during boot. Also the same function is used to call the runtime conf after a new conf settings changed.
void loadBootConf(void){
  
  optHWEn = EEPROM.read(optHWEn_eepromAddr);
  debugEn = EEPROM.read(debugEn_eepromAddr);
  //targetTemp = EEPROMReadInt(targetTemp_eepromAddr);
  targetTemp = EEPROM.read(targetTemp_eepromAddr);
  //deltaT = EEPROMReadInt(deltaT_eepromAddr);
  deltaT = EEPROM.read(deltaT_eepromAddr);
  opsMode = EEPROM.read(opsMode_eepromAddr);
  compressorRunTime = (EEPROM.read(compressorRunTime_eepromAddr) * 3600000); //eeprom value in hours. Hence 3600000 ms
  defrostTime = (EEPROM.read(defrostTime_eepromAddr) * 60000); //eeprom value in minutes, hence 60000 ms
  eeprom_read_string(userPassword_eepromAddr, userPassword, sizeof(userPassword));

  //*** IMPORTANT! *** the blelow part is still require more study
  switch (opsMode) {
    case 1:
      lowTempLimit = (targetTemp - (deltaT/2));
      //hiTempLimit = (targetTemp + (deltaT/2));
      hiTempLimit = (lowTempLimit + deltaT);

    case 2:
      lowTempLimit = targetTemp;
      hiTempLimit = (lowTempLimit + deltaT);

    case 3:
      lowTempLimit = (targetTemp - 1);
      hiTempLimit = (lowTempLimit + deltaT);

    default:
      lowTempLimit = (targetTemp - (deltaT/2));
      hiTempLimit = (targetTemp + (deltaT/2));
  }
  
}


Now struct part begins....

aq_mishu

the topic will be covered in 

https://forum.arduino.cc/index.php?topic=709158

as a continuation of a problem solving

UKHeliBob

Quote
Now struct part begins....
I can't wait to see it !
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

UKHeliBob

Code: [Select]

//EEPROPM Addressings need to be re-check for more optimization
#define eepromOffset 0 //[Address 0, reserved]
#define devSL_eepromAddr (eepromOffset + 1) //[Start at 1, used for device SL (10byte incl NULL), ends at 11]
#define optHWEn_eepromAddr (devSL_eepromAddr + sizeof(devSL)) //[Start at 1+11=12, used for 1byte, ends at 12]
#define debugEn_eepromAddr (optHWEn_eepromAddr + sizeof(optHWEn)) //[Start at 12+1=13, used for 1byte, ends at 13]
#define targetTemp_eepromAddr (debugEn_eepromAddr + sizeof(debugEn)) //[Start at 13+1=14, used for 2byte, ends at 15]
#define deltaT_eepromAddr (targetTemp_eepromAddr + sizeof(targetTemp)) //[Start at 15+2=17, used for 1byte, ends at 17]
#define opsMode_eepromAddr (deltaT_eepromAddr + sizeof(deltaT)) //[Start at 16+1=17, used for 1byte, ends at 17]
#define compressorRunTime_eepromAddr (opsMode_eepromAddr + sizeof(opsMode)) //[Start at 17+1=18, used for 1byte, ends at 18] //we may avoid it and can put this in a variable as per update.
#define defrostTime_eepromAddr (compressorRunTime_eepromAddr + sizeof(compressorRunTime)) //[Start at 18+1=19, used for 1byte, ends at 19]
#define userPassword_eepromAddr (defrostTime_eepromAddr + sizeof(defrostTime)) //[Start at 19+1=20, used for 4byte, ends at 23]

#define lastUsedeepromAddr (userPassword_eepromAddr + sizeof(userPassword)) //Keep the last address in count.

You don't need any of this if you use a struct
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

UKHeliBob

Topics merged - you were warned that they would be
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

aq_mishu

Reply of #67: Hope so...
Reply of #68: I can see... lol! Anyway, so please guide me through... about creating the struct...




UKHeliBob

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

aq_mishu

See reply #2
Since i'm not expert, asking this...
using struct method, will it 
1) update ONLY what is changed? Because I will issue individual commands for updating a specific parameter like delta T ONLY. (Hope it will via eeprom.update() )
2) will it store data as char str[] for all the items or also int8_t (or int/double etc)? I mean I know it stores byte, but after reading, now it's not a big issue for me to deal with type re-casting. Most cases, I can deal on-the fly without the additional variable and conversions between data types.
[Because I'm constantly trying to 1) Reduce ROM size.   2) reduce RAM size (ohh that's really important).   3) Avoid heap generation of RAM (fragmentation of RAM, that once I suffered a lot). aka, trying to be be a good programmer.... :-p  ]

UKHeliBob

Quote
Hope it will via eeprom.update()
As I said somewhere earlier in this thread EEPROM.put(0 uses update()
See https://www.arduino.cc/en/Reference/EEPROMPut

Quote
will it store data as char str[] for all the items or also int8_t (or int/double etc)?
There is no need to cast anything either before putting it on the EEPROM or getting it back.  You can put any data type, including arrays of data, in a struct.  The data will, of course, be stored as bytes on the EEPROM but when you get it back into a struct the original data types will be created in the struct

A suggestion, why don't you write a small program to test putting ad getting data in a struct to and from the EEPROM ?  In fact, read reply #18 and revise the example sketch to test whatever data type you want
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

sevenoutpinball

this should run on any device.  but it's pretty easy just keep your addresses and values straight and you'll be fine.





Code: [Select]
//            A r d u i n o   P i n b a l l   S o f t w a r e
//RailroadPinballJul31_2019MultiCPU.ino
bool   SerialMonitor = true;
String         God16 = "1234567890abcdef";
unsigned long  GodNbr;


#include <avr/eeprom.h>
#include <EEPROM.h>

//              G E N E R A L   P R O G R A M   S T O R A G E   A R E A S
const int AtMachineStarted = 0;
const int AtGamesStarted   = 4;
const int AtGamesCompleted = 8;
const int AtInsuranceBalls = 12;
const int AtFreeBalls      = 16;
const int AtTilts          = 20;
const int AtHighestScore   = 24;
const int AtAverageScore   = 28;
const int AtHighScrResets  = 32;
const int AtCoinsIn        = 36;
unsigned long MachineStarted;
unsigned long GamesStarted;
unsigned long GamesCompleted;
unsigned long InsuranceBalls;
unsigned long FreeBalls;
unsigned long Tilts;
unsigned long HighestScore;
unsigned long AverageScore;
unsigned long HighScrResets;
unsigned long CoinsIn;

void setup() {
 
  if (SerialMonitor) {
    Serial.begin(115200);
    God16 = "eeprom read and update";
    GodOut();
    God16 = "Compiled 05/18/2019";
    GodOut();
    God16 = __DATE__;
    GodOut();
    God16 = __TIME__;
    GodOut();
    Serial.println(__FILE__);
  }
  updateprom();
  readeeprom();
}
void loop() {

}
void readeeprom() {
  God16 = " MachineStarted "; EEPROM.get(AtMachineStarted, GodNbr); GodOut();
  God16 = " GamesStarted   "; EEPROM.get(AtGamesStarted,   GodNbr); GodOut();
  God16 = " GamesCompleted "; EEPROM.get(AtGamesCompleted, GodNbr); GodOut();
  God16 = " InsuranceBalls "; EEPROM.get(AtInsuranceBalls, GodNbr); GodOut();
  God16 = " FreeBalls      "; EEPROM.get(AtFreeBalls,      GodNbr); GodOut();
  God16 = " Tilts          "; EEPROM.get(AtTilts,          GodNbr); GodOut();
  God16 = " HighestScore   "; EEPROM.get(AtHighestScore,   GodNbr); GodOut();
  God16 = " AverageScore   "; EEPROM.get(AtAverageScore,   GodNbr); GodOut();
  God16 = " HighScrResets  "; EEPROM.get(AtHighScrResets,  GodNbr); GodOut();
  God16 = " CoinsIn        "; EEPROM.get(AtCoinsIn,        GodNbr); GodOut();
}
void updateprom() {
  unsigned long Zero = 0;
  EEPROM.put(AtMachineStarted, Zero);
  EEPROM.put(AtGamesStarted,   Zero);
  EEPROM.put(AtGamesCompleted, Zero);
  EEPROM.put(AtInsuranceBalls, Zero);
  EEPROM.put(AtFreeBalls,      Zero);
  EEPROM.put(AtTilts,          Zero);
  EEPROM.put(AtHighestScore,   Zero);
  EEPROM.put(AtAverageScore,   Zero);
  EEPROM.put(AtHighScrResets,  Zero);
  EEPROM.put(AtCoinsIn,        Zero);
}
void GodOut() {
  if (SerialMonitor) {
    Serial.print(God16); Serial.print(" = "); Serial.print( GodNbr);   
    Serial.print(" hex = "); Serial.println( GodNbr, HEX);
    God16 = "                "; GodNbr = 0;   
  }
}
The smartest person can make the dumbest mistake.

UKHeliBob

How many more times can I say USE A STRUCT

Just one EEPROM.put() saves all the variables and one EEPROM.get() reads them back.  No need to have separate variables for the addresses in EEPROM for writing or reading data.  One address does it all
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Go Up