Getting initial values into EEPROM

Hey all, if we are using the eeprom to save RAM, how do we load the initial values into the eeprom memory without calling them into memory first. I have thought about writing a simple ROM load script that has one function which is to load up all the EEPROM values within the program. then once that is done, load the sketch. Or should there be a sub routine that is like a "restore factory defaults" type of thing which runs through and loads up or restores all the base values? Then once the sketch is loaded, run that once and all the values are loaded.

If the intention of using EEPROM is to save flash and/or RAM, you must create and upload a separate sketch to initialize the EEPROM.

If you have a hardware programmer you can use that with AVRDUDE to directly write or read to EEPROM memory without using a sketch or the IDE.

Lefty

The simplest way to load the EEPROM is with the separate sketch as you and skumlerud point out. (Assuming you want to save flash or RAM)

FWIW, An alternative is to have a routine that uses serial to read a data from a file and load it byte by byte into EEPROM. The routine can be triggered by waiting for a connection at startup. Of course you have to make the ap or script on the other end, and you will also pay the price for adding serial. I only mention this because for some applications it is preferable than loading a new sketch and reloading the working sketch. It is also possible that only one "load sketch" will not have enough RAM to do the job, and you will need multiple load sketches. edit[/edit]

Most of the EEPROM usage is for in system value calls which can all be modified modified by the user. But I was running up on a wall on how to get the first set in without making a hard coded set of constants that can get pulled in, that live in the system. I also thought about perhaps makinig an array that could live in PROGMEM which a counter could loop through? I would like to have a universal reset, but I do not want to load up RAM to keep it available.

It is a think still in process. :slight_smile:

Yes, I do have a hardware programmer too, stk600 and an JTAG ICE mkII but didn’t head that way because honestly, I hadn’t thought of it and am only toe deep into true AVR.

I think the bootloader itself can accept eeprom values and put them in the right places, but our IDE/tools do not yet support that. I think the ultimate plan is to support an EEMEM storage macro akin to the PROGMEM macro magic, that will assign the right storage flags in the .elf which can then in turn make the right entries in the .hex for this to all happen automagically.

What comes to my mind is the magic word: EEMEM.
Have a look at http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1202157667
because I am not sure if this is supported yet.

Ok, a couple of questions…
I will stop down and take a closer look as the direct write through avrdude afterwards. In my reading of this thread and the one that bohne mentioned, it reads as if you can not nativly read/write to eeprom as suggested in the learning section of the arduino site. Am I reading to different timelines? Was this a previous issue, now solved? Because they mention v13 and v14 in the EEMEM thread, the thread is sounding current. Or, is this strictly referring to accessing the eeprom directly via the IDE?

Most situations I have found about eeprom storage, people are sweeping through their eeproms via a counter, not by calling specific memory locations. This is for system settings which the user can modify, so I am trying to choose specific addresses. I am doing it in 5’s because I always seem to think of something that should have been in a lower location, so for organization sake, I am spacing them out. I can tighten it up later.

Part 2, before I hit the brakes on the EEPROM thing for reasons mentioned above…I I had a little bit of a panic…
I made a little loader (see below). I did it in a sketch so I can keep moving forward with this project (I have a habit of getting side tracked so I am trying to stay focused). The thing I had a little gulp about was that after the sketch had been loaded, I realized that if the EEPROM was written in WAY less than a second (only about 30 items to be written) and it is a loop. So, did I just burn up all 100,000 write cycles in 1 shot? I had the arduino plugged in and was still working not thinking about the the fact that it was running the thing continuously.(Yeah…The things you think about after the fact).
Or, is a write cycle, write / erase / write, or each command to write?

Plus I am not sure I wrote it correctly to begin with. It compiled and loaded without error, but this does not mean it actually worked. I tried to add a read anything line and do a serial read of the eeprom locations but the ide told me there was no method of accomplishing what I was asking.
Here is a small section of my EEPROM loader.

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

////////////////////  EEPROM Read / Write Anything Templates  /////////////////////////////////

template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
    const byte* p = (const byte*)(const void*)&value;
    int i;
    for (i = 0; i < sizeof(value); i++)
        EEPROM.write(ee++, *p++);
    return i;
}

template <class T> int EEPROM_readAnything(int ee, T& value)
{
    byte* p = (byte*)(void*)&value;
    int i;
    for (i = 0; i < sizeof(value); i++)
        *p++ = EEPROM.read(ee++);
    return i;
}


///////////////// Data Locations /////////////////
const boolean beep = 0x46;
const byte beepPitch = 0x4B;
const byte lcdBright = 0x50;
const boolean lcdDim = 0x55;

void setup(){
}

void loop(){
EEPROM_writeAnything(beep, 0);
EEPROM_writeAnything(beepPitch, 1);
EEPROM_writeAnything(lcdBright, 2);
EEPROM_writeAnything(lcdDim, 1);

delay(2000);
}

And here is the read stuff that did not seem to work…

byte thisVal;
thisVal = EEPROM_readAnything(beep);
Serial.println(thisVal);
delay(1000);
thisVal = EEPROM_readAnything(beepPitch);
Serial.println(thisVal);
delay(1000);
thisVal = EEPROM_readAnything(lcdBright);
Serial.println(thisVal);
delay(1000);
thisVal = EEPROM_readAnything(lcdDim);
Serial.println(thisVal);
delay(1000);

BTW, I did have all the serial setup stuff in the code when I was trying to read it.

As far as why the IDE was throwing errors, I think it is is because I am trying to call different types of data types off of 1 type of variable. I will keep working with it though. I just need to know if I burnt up those previous locations… in other words a chip swap.

The routines are designed to save and restore values found in variables. You don’t assign the locations to the variables, you give the locations in the calls to the routines.

byte beepPitch;  // the current pitch value

void setup(){
    EEPROM_readAnything(0x4B, beepPitch);
    // now beepPitch contains the pitch value from previous run
}

void loop() {

    do_something_with_current_value(beepPitch);

    beepPitch = calculate_some_new_value();

    if (digitalRead(SAVE_BUTTON) == HIGH)
        EEPROM_writeAnything(0x4B, beepPitch);
}

Of course, do_something_with_current_value() and calculate_some_new_value() are stand-ins for whatever tasks you’re doing with those values.

Also, as you say, putting EEPROM writes in your loop() is slightly dangerous: make sure you’re only writing when the user wants them written. If you save every millisecond, or even every couple seconds, you are risking wearing out your built-in EEPROM. If you only ran your test a dozen times, and it always had that delay(2000) in it, you are probably still fine, but I suggest you do it only when someone pushes a button or on some other similar signal.

Unfortunately, I loaded the eeprom loader sketch and left it plugged in. The write command was the loop. The delay was put in place before all my read commands I had in there previously. I should have put a button start on it so it would just run only one time. I left it plugged in because I was working on other stuff, so, it probably was on for a couple of hours. Well, I will replace the chip tonight. I can still use the old one somewhere else that does not need the EEPROM.

You said "You don't assign the locations to the variables, you give the locations in the calls to the routines."

Yeah, I was fighting the semantics on this. I tried a number of variations. I thought I had to place the location as the variable because that word would always be the value for that location. But wait, you said that by writing the locations... So, if I wrote it as seen in the code (posted earlier), would the program be able to write anything at all because it was a null variable? There really is no way to check the condition of those eeprom locations, is there?

BTW, I do not see a quote button. How does one pull quotes on this forum aside from the way I did above?

Most of your EEPROM may be ok, just don’t use the locations you were hammering.

How does one pull quotes on this forum aside from the way I did above?

copy the text you want to quote and paste it between the quote tokens:

your quote goes here[/quote} ← replace curly bracket with closing square bracket

Thanks mem!

EEPROM_readAnything(0x4B, beepPitch);

Hey halley, so I define the variable right there? I do not have to have the whole formal thisVal = EEPROM_readAnything(beepPitch);, or this this one of those either way will work sort if things? I like your writing of it as it seems cleaner to read. Just making sure before I go and recode everything.

MYX, that's the way of it. To be completely accurate, you don't define it there, you name it there. These routines expect the name of a variable in the second argument, and they can even modify the contents of the variable you name there. (This isn't usually the case for C program arguments, so I understand your confusion. C++ has some magic tricks there.) If you give a constant value, like your earlier code, EEPROM_readAnything(something, [u]1[/u]), it would be completely flummoxed as to what to do with it.

Ok, I am bumping into another wall and I think this was also leading me to the previous line of how to name stuff. Here is the application and perhape (if you don't mind) help see me through this. I am filtering input through a switch / case set. In one of the lines in the cases I was trying to load up a variable with a eeprom / hex location. The last functional line (not including the break) is a call to another subroutine in which the value would actually be looked up, modified, then saved. I am trying to write a total of 4 master sub routines for each kind of menu. So, if is a yes / no menu, the case would be like this...

case 34: // Utility - Beep  On                                                                                                                                                            
byte PromAddress = 0x46 ;  //EEPROM Input Number  - 70 - HEX Val - 0x46                                                                                                                                                            
prevMen = 33;                                                                                                                                                            
prevPos = 1;                                                                                                                                                            
delay(150);                                                                                                                                                            
yesNoMenu(); // Menu Type = 3 - Replace if needed.                                                                                                                                                            
break;

Then in the yesNoMenu() there would be a call to the address location to retrieve the data. This is stored in a variable "yesNoVal" which is called for this routine only, thus eliminating the need for a bunch of variables when they will only be used for this one moment. PromAddress and yesNoVal are like master bytes (waits for chuckles) Sorry, it was there. ;D The problem is that if I name the variable in the case, then it gets sent to the yesNoMenu(), then it gets to the end of the yesNoMenu() Where the new value would be saved but there would be no position to send it to. This would result in having to write a separate routine for each location which is not a fun idea at all.

void yesNoMenu() { // Menu Type 2 Sets up for Simple yes no answer.
byte yesNoVal;
    pullMain(); // Preform the string pull
    lcd.clear();
    lcd.printIn( buffer );  // Print it to Line 1
    lcd.cursorTo(2, 0);
    yesNoVal = EEPROM_readAnything(PromAddress); // place EEPROM Call for this menuValue
                 if (yesNoVal = 1){pullString=31;}  //str_31[] PROGMEM = "Yes";
                else if(yesNoVal = 0){pullString=32;}  //str_32[] PROGMEM = "No";
    
    pullMain(); // Preform the string pull
    char inSet[2] =">";
    lcd.printIn( inSet );
    lcd.printIn( buffer ); // Print it to Line 2

Then there is a switch / case structure that works on button input. This allows the user to change from yes, to no, and back again (if they like). BTW for easier reading, pullString is the carrier of the strings from PROGMEM. If option 5 is selected, then ...

        case 5:  // Enter
              EEPROM_writeAnything(PromAddress, pullString);
                thisMenu = prevMen;
                menuLookup();
                break;} // End of Switch

menuLookup is the call to the original switch / case set which is based around the thisMenu var. So, if this is not all total jibberish, then hopefully you will see where I am heading.

Sorry, more confusion, but, I thought that with the EEPROM_writeanything you had to tell it what type of variable you are writing for the initial load of the EEPROM. Once it is in the system and the sketch is loaded, then as you described, it will take care of it's self, but for the initial load, how does it know what the data type is so it can load them properly?

Updated with your suggestions...

// Libraries Templates and all that
byte beep;
byte beepPitch;
byte lcdBright;
byte lcdDim;
long bigBeep; // I do not really have this, but if I wanted a Long or even an int, it will take more than a single byte space in EEPROM

//setup stuff()

//main void loop()

EEPROM_writeAnything(0x46, 0);
EEPROM_writeAnything(0x4B, 1);
EEPROM_writeAnything(0x50, 2);
EEPROM_writeAnything(0x55, 1);

/*
EEPROM_readAnything(0x46, thisVal);  //  beep
Serial.print(beep value = );
Serial.println(thisVal);
delay(1000);
EEPROM_readAnything(0x4B, thisVal);  //  beepPitch
Serial.print(beepPitch value = );
Serial.println(thisVal);
delay(1000);
EEPROM_readAnything(0x50, thisVal);  //  lcdBright
Serial.print(lcdBright value = );
Serial.println(thisVal);
delay(1000);
EEPROM_readAnything(0x55, thisVal);  //  lcdDim
Serial.print(lcdDim value = );
Serial.println(thisVal);
delay(1000);
*/

MYX, you can't give a constant in writeAnything either. The second argument works the same way: you name a variable, it works with the contents of that variable. It's only through the naming of an actual variable that the routine knows what data type it's working with, and where to get or put the value.

http://www.arduino.cc/playground/Code/EEPROMWriteAnything

If you wonder how to get the initial value into EEPROM, start reading at the top of the thread, where others explained that you either (1) write a different sketch that just writes to EEPROM, and replace it with your reading sketch afterwards; or (2) you deal with the fact that the EEPROM can't tell you if it's never been written, and you detect and fix invalid values for your settings when you read them.

MYX, you can't give a constant in writeAnything either. The second argument works the same way: you name a variable, it works with the contents of that variable. It's only through the naming of an actual variable that the routine knows what data type it's working with, and where to get or put the value.

I do understand this. I don't think I was doing any constants except for the first run of code posted earlier yesterday. I think I am confusing the matter by asking too many different questions all at the same time. More so, I am probably not asking the right questions and or not asking them correctly. Please understand I am asking all this respectfully, and truly not trying to frustrate you. (although I would believe that I am doing a good job of it) But, hear me say thank you none the less. I appreciate your time.

Where I stand... I do understand that I need two (possibly 3) different sketches, one to load the EEPROM, possibly one to read just to verify, then the actual program sketch that the EEPROM will be used for. I get that.

I get that I need to name the variable and assign it a type. int gum = 6; means I named an integer named gum the value of 6. I get that.

I have read the writeanything example page more times than I want to admit to. It talks about in system writes and reads not the initial write. In the last couple posts, I was trying to explain what I wanted to have happen in the working program sketch, not the loading sketch, not necessarily how one should go about doing it. I was trying to ask how to do the general concept. Then the second piece I was asking about the actual load sketch. I have now separated the initial write and verify sketches into 2. One for read, one for write.

I will focus strictly on the loader until I have that right, then I will go to the other issue later. Unfortunately, I left my kit at the house today so I can't work on it. But I will push the loader around a bit more tonight.

Loader/Verifier Script

#define CONFIG_EE_BEGINS 0x30
#define CONFIG_EE_OVERFLOW 0x1FF  // depends on ATmega model

long validConfiguration = 0xAAAAFEED;
byte lcdBright = 255;
long bigBeep = 44100;
static int fontData = { 0x88, 0xAA, 0x8A, /* ... */ 0xFF };

void setup()
{
    Serial.begin(9600);

    // does the chip already have a valid config?
    // take this out if you want to FORCE an overwrite of configuration
    long currentConfiguration = 0;
    EEPROM_readAnything(CONFIG_EE_BEGINS, currentConfiguration);
    if (currentConfiguration == validConfiguration)
    {
        Serial.println("Existing user configuration appears valid.");
        return;
    }

    Serial.println("Saving factory configuration... do not disconnect!");
    int address = CONFIG_EE_BEGINS;
    address += EEPROM_writeAnything(address, validConfiguration);
    address += EEPROM_writeAnything(address, lcdBright);
    address += EEPROM_writeAnything(address, bigBeep);
    address += EEPROM_writeAnything(address, fontData);
    if (address > CONFIG_EE_OVERFLOW)
    {
        Serial.println("EEPROM OVERRUN ERROR - TOO MUCH DATA!");
        for (;;) { ; }
    }
}

void loop()
{
    Serial.println("Now safe to disconnect. All values saved.");
    delay(1000);
}

User Script

#define CONFIG_EE_BEGINS 0x30
#define CONFIG_EE_OVERFLOW 0x1FF  // depends on ATmega model

long validConfiguration;
byte lcdBright;
long bigBeep;
int fontData;

void setup()
{
    Serial.begin(9600);

    Serial.println("Loading initial configuration... do not disconnect!");
    int address = CONFIG_EE_BEGINS;
    address += EEPROM_readAnything(address, validConfiguration);
    address += EEPROM_readAnything(address, lcdBright);
    address += EEPROM_readAnything(address, bigBeep);
    address += EEPROM_readAnything(address, fontData);

    if (currentConfiguration != 0xAAAAFEED || address > CONFIG_EE_OVERFLOW)
    {
        Serial.println("Configuration appears corrupt. Please return to factory.");
        for (;;) { ; }
    }
}

void loop()
{
    Serial.println("Now safe to disconnect. All values saved.");
    delay(1000);
}

Suhhhhhweeeeeet! Thanks

Cheers for the info in this thread, I have managed to use it to add a save and load setting feature to my script.