Go Down

Topic: Getting initial values into EEPROM (Read 5536 times) previous topic - next topic


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.



Mar 12, 2009, 10:47 pm Last Edit: Mar 12, 2009, 10:49 pm by BroHogan Reason: 1
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](Written before preceding post.)[/edit]

"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll


Mar 13, 2009, 03:03 am Last Edit: Mar 13, 2009, 03:10 am by MYX Reason: 1
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.  :)

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.
Code: [Select]

#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);


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

Code: [Select]

byte thisVal;
thisVal = EEPROM_readAnything(beep);
thisVal = EEPROM_readAnything(beepPitch);
thisVal = EEPROM_readAnything(lcdBright);
thisVal = EEPROM_readAnything(lcdDim);

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.


Mar 23, 2009, 05:09 pm Last Edit: Mar 23, 2009, 05:12 pm by halley Reason: 1
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.

Code: [Select]

byte beepPitch;  // the current pitch value

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

void loop() {


   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?


Mar 23, 2009, 06:54 pm Last Edit: Mar 23, 2009, 06:54 pm by mem Reason: 1
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.


Mar 23, 2009, 07:33 pm Last Edit: Mar 23, 2009, 07:40 pm by halley Reason: 1
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, 1), 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...

Code: [Select]

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

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.

Code: [Select]

void yesNoMenu() { // Menu Type 2 Sets up for Simple yes no answer.
byte yesNoVal;
   pullMain(); // Preform the string pull
   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 ...
Code: [Select]

       case 5:  // Enter
             EEPROM_writeAnything(PromAddress, pullString);
               thisMenu = prevMen;
               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.


Mar 23, 2009, 09:28 pm Last Edit: Mar 23, 2009, 09:38 pm by MYX Reason: 1
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...
Code: [Select]

// 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 = );
EEPROM_readAnything(0x4B, thisVal);  //  beepPitch
Serial.print(beepPitch value = );
EEPROM_readAnything(0x50, thisVal);  //  lcdBright
Serial.print(lcdBright value = );
EEPROM_readAnything(0x55, thisVal);  //  lcdDim
Serial.print(lcdDim value = );

Go Up