Pages: [1]   Go Down
Author Topic: proper use of EEPROMWriteAnything ?  (Read 2160 times)
0 Members and 1 Guest are viewing this topic.
Colorado, US of A
Offline Offline
Newbie
*
Karma: 0
Posts: 16
ex-know-it-all
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I need to keep some minimal config data across power cycles... searching the forums and playground, i found the following which appears that it should do exactly what i need, essentially serialize a struct and stuff it in EEPROM for later (when it can be deserialized): http://www.arduino.cc/playground/Code/EEPROMWriteAnything

However... I cannot figure out how to actually use it.  Compiling the example as shown (pasted again below for posterity), i get:
Code:
test_eepromstruct:-1: error: expected ',' or '...' before '&' token
test_eepromstruct:-1: error: ISO C++ forbids declaration of 'T' with no type
test_eepromstruct:-1: error: 'T' has not been declared

The templating business is a little beyond me at the moment... i have not been able to figure out how to actually use the thing.  Can someone please point me in the right direction?

code listing:
Code:
#include <EEPROM.h>

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;
}


/* Once your sketch has these two functions defined, you can now save and load whole arrays or structures of variables in a single call. You provide the first EEPROM address to be written, and the functions return how many bytes were transferred.
*/

struct config_t
{
    long alarm;
    int mode;
} configuration;

void setup()
{
    EEPROM_readAnything(0, configuration);
    // ...
}
void loop()
{
    // let the user adjust their alarm settings
    // let the user adjust their mode settings
    // ...

    // if they push the "Save" button, save their configuration
    if (digitalRead(13) == HIGH)
        EEPROM_writeAnything(0, configuration);
}

Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26324
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That sketch compiles correctly on 0021 on Windows.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49372
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It doesn't compile in 0022, though. The thing that you have to do in 0022 is to open a new tab, creating a file with a .h extension, and paste that code there. Add:
Code:
#include <EEPROM.h>
#include <WProgram.h>
To the top.

In the sketch, add an include statement to include the .h you created.

Then, it will compile and work.
Logged

Colorado, US of A
Offline Offline
Newbie
*
Karma: 0
Posts: 16
ex-know-it-all
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hrm... thanks Paul.  Tried your suggestion, i still cannot compile, same errors.  I am on Linux (Centos 5), perhaps avr-gcc is more strict here than on Windows?

It seems from my errors that i need to give "T" a type, but i don't know what type it would be... i am fairly new to C++, and the template business is a fairly complicated incantation.  Any syntax experts out there that can help me fix it?
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22800
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I've openend a bug ticket for this problem and the answer I got was to use the method posted by PaulS.
It seems that Arduino 0022 has changed something in the Java parser so some C/C++ structures are not well recognized.

I suggest you to use Arduino IDE 0021: it works perfectly.  smiley-wink
Logged


Colorado, US of A
Offline Offline
Newbie
*
Karma: 0
Posts: 16
ex-know-it-all
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

leo72 can you provide me a link to your bug report?  I'd like to add to it and note workaround not working on LInux + 0022.

I did confirm that going back to 0021 did work, which surprised me a bit... its a shame its not easy to tell what errors come out of avr-gcc and which come from the Java bits/preprocessor.
Logged

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hrm... thanks Paul.  Tried your suggestion, i still cannot compile, same errors. I am on Linux (Centos 5)...

It has nothing to do with Linux.  I am using avr-gcc version 4.3.4 compiled from source on Centos 5.5 Linux.  (Also  tested on Arduino 0022 distribution on Windows XP.)

Here's the deal:

Between arduino-0021 and arduino-0022, the order in which function prototypes appear in the C++ file that Arduino generates from your sketch has changed.  See Footnote.

Among other things that used to work but don't work now, it turns out that -0022 requires that template definitions be placed in a separate header file.  (That's the way that I usually organize C++ projects anyhow, so I wouldn't have noticed the difference if this problem hadn't been reported), but it would be nice if someone would spell it out on the Arduino EEPROM library page for this stuff.)

Anyhow, try the following:

Open a tab and name it "Anything.h"  (or some such thing).

Take all of the template stuff out of the main sketch and put it there.  You have to include <EEPROM.h> to get EEPROM stuff defined, and you have to include <WProgram.h> to get various Arduino types defined.

Here's what goes in the header tab:
Code:
// Header file "Anything.h" to allow EEPROM_writeAnything  and
// EEPROM_readAnything examples to compile under arduino-0022
//
// Due to the (broken) way that Arduino version 0022 collects function
// prototypes before other things in the main sketch, template
// stuff must be in a separate header
//
// davekw7x
//
#include <EEPROM.h>
#include <WProgram.h>

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;
}

The main sketch now looks like the following:
Code:
#include <EEPROM.h>
#include "Anything.h"

//
// Template stuff removed and placed in separate header file
// davekw7x

struct config_t
{
    long alarm;
    int mode;
} configuration;

void setup()
{
    EEPROM_readAnything(0, configuration);
    // ...
}
void loop()
{
    // let the user adjust their alarm settings
    // let the user adjust their mode settings
    // ...

    // if they push the "Save" button, save their configuration
    if (digitalRead(13) == HIGH)
        EEPROM_writeAnything(0, configuration);
}


Regards,

Dave

Footnote:

If you want to see what the compiler is actually presented with, after Arduino massages your sketch file(s), hold a "Shift" key down when you click the "verify" button.  It tells you the name of the temporary directory that will hold the generated C++ file.  Look at it when you have everything in the main sketch (no separate header).  Now look at the cpp file that is generated when you include the template definitions in a separate header.

If you are really interested (and if you are still awake), you can compare the way that arduino-0021 did it with the way that arduino-0022 does it.  And you can try to remember this in case you are ever in the position of "improving" a previous version of some system of programs.  There is always a reason that people do things and change things.  It may even be a "good" reason, but you always have to be ready to fix "unindented consequences."  Or at least document them.

« Last Edit: May 29, 2011, 08:06:35 am by davekw7x » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 332
Posts: 22800
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@shorted.neuron:
http://code.google.com/p/arduino/issues/detail?id=472&start=200
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's another way to write/read configuration data to EE:

#include <avr/eeprom.h>

struct settings_t {
  byte b1;
  int i1;
  float f1;
  float f2;
  float f3;
} settings = {100, 40, 85, 0.2, 10};

// write to ee
eeprom_write_block((const void*)&settings, (void*)0, sizeof(settings));

// read from ee
eeprom_read_block((void*)&settings, (void*)0, sizeof(settings));
Logged

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17294
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's another way to write/read configuration data to EE:

#include <avr/eeprom.h>

struct settings_t {
  byte b1;
  int i1;
  float f1;
  float f2;
  float f3;
} settings = {100, 40, 85, 0.2, 10};

// write to ee
eeprom_write_block((const void*)&settings, (void*)0, sizeof(settings));

// read from ee
eeprom_read_block((void*)&settings, (void*)0, sizeof(settings));


Thanks for the example. It seems simple and clean and compiles with no problems. I'll have to play with it some more later.

Lefty
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

One thing to be aware of - eeprom_write_block actually writes 1 byte at a time in a loop.  So if your structure takes up 8 bytes, for example, that's 8 writes.  It can be pretty easy to go over the 100,000 write limit if one is not careful.

William
Logged

Pages: [1]   Go Up
Jump to: