Storing User Parameters to EEPROM then Restoring Them upon Reset

As shown on the left, I'm new to Arduino, and developing an Aquarium Outlet Controller.

An important feature of this sketch will be to store user selected time and temperature variables in EEPROM so they can be recalled and restored in the case of a power outage or reset. I've attached the current version of the sketch.

When implemented, the EEPROM functionality should go something like:

  • Setup a means to store user settings
  • At power up or reset, check if user settings have been stored. If yes, restore them from EEPROM.
  • When a user sends settings serially, store them to EEPROM

Thank you in advance for reading and responding to this post!

AquariumOutletController_v1.3beta2.ino (18 KB)

I, Septillion, grant you hereby to do so.

Aka, there is NO question in your post :wink:

Things to do:

  • Study EEPROM stuff
  • Determine the difference between valid user data and not valid user data. What can tell you that there is user data stored? Default value of every EEPROM location is just 0xFF so it can be as simple as assuming 0xFF is no user data or to set an address to something different when user data IS stored.

Right, too focused on getting the words organized.

I included comments in the sketch to show the attempted implementation and stumbling points...

Then some tips:

  1. First try to make a simple proof of concept around EEPROM. Makes it wayyyyy easier.

  2. Don't use String....

  3. Have you heard of arrays?

  4. Have you heard of arrays?

  5. Have you heard of arrays?

  6. Have you heard of arrays? (Gets funny when you have :wink: )

  7. Use proper variable names. R1_ID2, ind1, temp1, hh1, ok etc are all terrible variable names. The name should tell EXACTLY what it is.

Thanks septillion - I do appreciate the humor. Arrays are on my learning list. And Strings (vs strings?), I've read other comments about pros and cons, but I think understanding in this area will come with time.

septillion:
Then some tips:

  1. First try to make a simple proof of concept around EEPROM. Makes it wayyyyy easier.

  2. Don't use String....

  3. Have you heard of arrays?

  4. Have you heard of arrays?

  5. Have you heard of arrays?

  6. Have you heard of arrays? (Gets funny when you have :wink: )

  7. Use proper variable names. R1_ID2, ind1, temp1, hh1, ok etc are all terrible variable names. The name should tell EXACTLY what it is.

In the mean time, here's what the sketch includes in summary. I think the use of struct is something I need to wrap my brain around to move forward, but perhaps it's even more than that :-):

//...

#include <EEPROMex.h>                                                // https://github.com/thijse/Arduino-EEPROMEx
#include <EEPROMVar.h>

//...

/* ***************************************For EEPROM (Based on an example by Thijs Elenbaas
                                          http://playground.arduino.cc/Code/EEPROMLoadAndSaveSettings */

#define CONFIG_VERSION "ls1"                                        // ID of the settings block
#define memoryBase 32                                               // Tell it where to store your config data in EEPROM
bool ok  = true;
int configAdress = 0;

struct StoreStruct {
  int r1h1, r1m1, r1s1, r1h2, r1m2, r1s2, r1h3, r1m3, r1s3, r1h4, r1m4, r1s4, R3h, R3m, R3s, r2tempHigh, r2tempLow;
  char version[4];                                                 // CONFIG_VERSION verification
}

/* ***Not really sure what's going on here. This probably makes no sense the way I've interpreted the example. I thought that this
might assign the user setting variables like hh1, mm1, etc in the structure, so hh1 would be stored/recalled as element usersettings.r1h1.
Have to say, a bit stuck in a thicket here...*/
storage = {                                                        
  hh1, mm1, ss1, hh2, mm2, ss2, hh3, mm3, ss3, hh4, mm4, ss4, R3hh, R3mm, R3ss, tempHigh, tempLow,
  CONFIG_VERSION,
};

/* Inserted these based on a YouTube video on structures, but they don't get used anywhere */
StoreStruct usersettings;
int settingsSize = sizeof(StoreStruct);
 //...


void setup()

  EEPROM.setMemPool(memoryBase, EEPROMSizeUno);                    //Set memorypool base to 32, assume Arduino Uno board
  configAdress  = EEPROM.getAddress(sizeof(StoreStruct));          // Size of config object

  ok = loadConfig();

//...

void loop()
//...
    saveConfig(); // Called once user values have been parsed and stored as ints
//...



bool loadConfig() {
  EEPROM.readBlock(configAdress, storage);

  Serial.println("Read alarm values: ");                      // Goal here is to verify some of the user values have been
  Serial.println(hh1);                                        // saved and read back correctly (debug only)
  Serial.println(mm1);
  Serial.println(ss1);
  Serial.println(hh2);
  Serial.println(mm2);
  Serial.println(ss2);
  return (storage.version == CONFIG_VERSION);
}

void saveConfig() {
  EEPROM.writeBlock(configAdress, storage);
  Serial.println("Saved to EEPROM! ");                         // Let's me know this function was called.

}

Are you currently able populate, store, and retrieve the structure? Does loadConfig() print out the right values? If not, I would back up a step, and just work independently on those tasks. If you are getting the correct values, what is the issue?

#include <EEPROMex.h>              
#include <EEPROMVar.h>

The standard EEPROM.h included with the ide now includes EEPROM.put() and EEPROM.get() which can handle all data types including your structure. I believe that you will be less confused if you use the standard library. There is a library example with a structure.

Begin by writing a small program to deal with storage and retrieval of the struct. Get comfortable with how to load values in the struct. Then work it into your program.

I am confused about the design and flow of your program. The values which wind up in the structure variable storage are coming from three different Strings of serial input and then processRelay1() ,processRelay2(), and processRelay3(). It's pretty hard to keep track of what is going on.

Do you always process three user Strings? How will initial eeprom values get into your program?

Thank you cattledog and septillion, you're point is well made: I'm moving too fast in new territory.

Regarding how the user data is parsed, the sketch looks for one of three string prefixes, "Relay1=", "Relay2=" or "Relay3=" and assigns the corresponding user values to integers (hh1, mm1, ss1, ...). To safeguard those values, the sketch would store them into EEPROM and retrieve at POR.

I went with Thijs Elenbaas's library because, at first blush, it appeared to be pretty straightforward. But I have more homework to do :slight_smile:

cattledog:
Are you currently able populate, store, and retrieve the structure? Does loadConfig() print out the right values? If not, I would back up a step, and just work independently on those tasks. If you are getting the correct values, what is the issue?

#include <EEPROMex.h>              

#include <EEPROMVar.h>




The standard EEPROM.h included with the ide now includes EEPROM.put() and EEPROM.get() which can handle all data types including your structure. I believe that you will be less confused if you use the standard library. There is a library example with a structure.

Begin by writing a small program to deal with storage and retrieval of the struct. Get comfortable with how to load values in the struct. Then work it into your program.

I am confused about the design and flow of your program. The values which wind up in the structure variable storage are coming from three different Strings of serial input and then processRelay1() ,processRelay2(), and processRelay3(). It's pretty hard to keep track of what is going on. 

Do you always process three user Strings? How will initial eeprom values get into your program?

In the past that was a good choice but with put() and get() as default part of the library that's even easier.

And as for as arrays, just have a look. To start using them here there is just not that much to learn :smiley:

byte relayPins[] = {5, 3, 8};
//instead of
relayPin1 = 5;
relayPin2 = 3;
relayPin3 = 8;

//and use them like
digitalWrite(relayPins[0], HIGH);
//just remember to start at 0

OK, simplifying did the trick. Using the EEPROM.h library with EEPROM.update and EEPROM.read and all is going smoothly. And I've started using arrays :slight_smile:

OK, simplifying did the trick. Using the EEPROM.h library with EEPROM.update and EEPROM.read and all is going smoothly. And I've started using arrays :slight_smile:

Nice work getting this sorted.

Another place to start using arrays is to replace the Strings (objects, with a capital S) with strings(null terminated character arrays, lower case s) like you were going to in this post. :slight_smile:

http://forum.arduino.cc/index.php?topic=460879.msg3165851#msg3165851