Best way to store data on EEPROM

I have a temperature and light logging program, which I want to store collected data on an eeprom. My C knowledge is minimal and I was wondering what the best way to do this is!

the data I plan to store :-

Samples UL
Temp Total UL
Light Total UL
Min Temp I
Max Temp I
Min Light I
Max Light I

This will be in 2 tables, the first will contain data for a day period (15 minute intervals currently), the second will contain a record for each day of the year.

Each record update will require the data reading and totals/max/min updating, since the EEPROM routines use bytes I was wondering what the best way to do this is?

Create a structure and use sizeof and a byte pointer to read each byte / write it, I have no problem working out where to write it (assembler experience) just not sure of the best and most efficient way to do this.

The data above is Unsigned Longs and Integers!

my EEPROM routines are

readEEPROM(0x50,address)
writeEEPROM(0x50,address,byte,127)

I am more concerned with the mechanics as I am not to sure with pointers, structures etc in C, and without being able to trace the program and watch variables it makes it difficult!

Thanks for any help

Regards

Darren

UL = unsigned long?
I = int?

Which Arduino do you have?

Dumilenove, with a 328p!

yes UL = unsigned long
and I = Int

I thought I added that in the text, but I must have got sidetracked!

Assuming I did the math correctly...

Samples       UL   4
Temp Total    UL   4
Light Total   UL   4
Min Temp      I    2
Max Temp      I    2
Min Light     I    2
Max Light     I    2
                   20

20 bytes per record.

15 Minute Periods per Hour    4
Hours per Day                24
15 Minute Periods per Day    96
Bytes per Day              1920

1920 bytes needed for the daily records.

Days per Year               365
Bytes per Year             7300

7300 bytes needed for the yearly records.

For a total storage of 9220 bytes.

How much EEPROM space is available on the 328p?

I have a 24LC256, with 32k memory (infact I have 5), and yes your calculations are correct! I planned this on a spreadsheet, so I should have plenty of room, (and more as I plan on capturing more statistics, once I get the base ones done)

except 366 days in a year!

The problem is I'm not sure of the best way to read bytes into the structure and write them back out to the EEprom using C, Ideally having a function :-

WriteStrucute(*structure,Address) ;

would solve all the problems!

Also although it does not say it explicitly it says the chip is good for 1,000,000 writes I assume this is per cell not total!

Ok still trying here to at least get the basis here is my code sofar, still struggling with the pointers to the log entry!

(note I am editing in Codeblocks, once I get the code working I will be using it in the IDE)

struct Log_Entry{
      unsigned long SamplesTaken ;
      unsigned long LightTotal ;
      unsigned long TempTotal ;
      int MinLight ;
      int MaxLight ;
      int MinTemp ;
      int MaxTemp ;
};

struct Log_Entry myLog ;

int WriteStructure(Log_Entry &structure,unsigned long Address) ;


int main() {



}
int WriteStructure(Log_Entry &structure,unsigned long Address) {

}

I am getting the following errors :-

C:\Users\Daz\MyProgramming\CProgramming\TestSyntax.c|14|error: expected ';', ',' or ')' before '&' token|
C:\Users\Daz\MyProgramming\CProgramming\TestSyntax.c|22|error: expected ';', ',' or ')' before '&' token|
||=== Build finished: 2 errors, 0 warnings ===|

I have been googling structures but not much help on calling and reading bytes from them yet!

Log_Entry is not a type. struct Log_Entry is the type to use in the function declaration/implementation.

Ok, can anybody take a look a this and see if it makes sense, I think I got it it at least compiles, I just dont want to take my logger off line to test it just yet!

Also if anybody has any suggestions on cleaning the code up it would be appreciated!

#include <Wire.h>

struct {
     unsigned long SamplesTaken ;
     unsigned long LightTotal ;
     unsigned long TempTotal ;
     int MinLight ;
     int MaxLight ;
     int MinTemp ;
     int MaxTemp ;
} 
Log_Entry ;

struct Log_Entry myLog ;

void setup() {

}
void loop() {
}

// *****************************************************************************
//                      Read Structure from EEPROM
// *****************************************************************************
int WriteStructure(struct Log_Entry structure,unsigned int Address) {

     union  {
          struct Log_Entry structure ;
          byte bytes[sizeof(Log_Entry)] ;
     } 
     Log ;

     for (int j =0 ; j<sizeof(Log_Entry); j++) {
          writeEEPROM(0x50,Address+j,Log.bytes[j]) ;
     }

}
// *****************************************************************************
//                       Write Structure to EEPROM
// *****************************************************************************
int ReadStructure(struct Log_Entry structure,unsigned int Address) {

     union  {
          struct Log_Entry structure ;
          byte bytes[sizeof(Log_Entry)] ;
     } 
     Log ;

     for (int j =0 ; j<sizeof(Log_Entry); j++) {
          Log.bytes[j] = readEEPROM(0x50,Address+j) ;
     }

}
// *****************************************************************************
//                       Write Byte to EEPROM
// *****************************************************************************
void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) {
     Wire.beginTransmission(deviceaddress);
     Wire.send((int)(eeaddress >> 8));   // MSB
     Wire.send((int)(eeaddress & 0xFF)); // LSB
     Wire.send(data);
     Wire.endTransmission();

     delay(5);
}
// *****************************************************************************
//                       Read Byte from EEPROM
// *****************************************************************************
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) {
     byte rdata = 0xFF;

     Wire.beginTransmission(deviceaddress);
     Wire.send((int)(eeaddress >> 8));   // MSB
     Wire.send((int)(eeaddress & 0xFF)); // LSB
     Wire.endTransmission();

     Wire.requestFrom(deviceaddress,1);

     if (Wire.available()) rdata = Wire.receive();

     return rdata;
}

Also any suggestions on making it more generic so I could perhaps pass any structure to the functions and have them read/write correctly?

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

Great that works BUT!

could somebody explain what the template does, and why I cant move it to the end of the code like my other subs? (code is below)

Thanks

#include <Wire.h>

template <class T> int EEPROM_writeAnything(int Address, const T& value)
{
     const byte* p = (const byte*)(const void*)&value;
     int i;
     for (i = 0; i < sizeof(value); i++)
          writeEEPROM(0x50,Address++,*p++) ;
     return i;
}

template <class T> int EEPROM_readAnything(int Address, T& value)
{
     byte* p = (byte*)(void*)&value;
     int i;
     for (i = 0; i < sizeof(value); i++)
          *p++ = readEEPROM(0x50,Address++) ;
     return i;
}

struct Log_Entry {
     unsigned long SamplesTaken ;
     unsigned long LightTotal ;
     unsigned long TempTotal ;
     int MinLight ;
     int MaxLight ;
     int MinTemp ;
     int MaxTemp ;
} 
;

struct Log_Entry myLog ;

void setup() {

     Serial.begin(9600) ;
     Wire.begin() ;
     
     myLog.SamplesTaken=0 ;
     myLog.LightTotal =0;
     myLog.TempTotal =0;
     myLog.MinLight =0;
     myLog.MaxLight =0;
     myLog.MinTemp =0;
     myLog.MaxTemp =0;
     
     EEPROM_writeAnything(0,myLog) ;
     EEPROM_readAnything(0,myLog) ;
     
     printLog() ;
     
     myLog.SamplesTaken=1234 ;
     myLog.LightTotal =2345;
     myLog.TempTotal =3456;
     myLog.MinLight =1111;
     myLog.MaxLight =2222;
     myLog.MinTemp =3333;
     myLog.MaxTemp =4444;
     
     EEPROM_writeAnything(0,myLog) ;
     
     printLog() ;
     
     EEPROM_readAnything(0,myLog) ;
   
     printLog() ;
     
} 



void loop() {
}
void printLog() {
     Serial.println("====================================") ;
     Serial.print("SamplesTaken :") ;
     Serial.println( myLog.SamplesTaken) ;
     Serial.print("LightTotal :") ;
     Serial.println( myLog.LightTotal) ;
     Serial.print("TempTotal :") ;
     Serial.println( myLog.TempTotal) ;
     Serial.print("MinLight :") ;
     Serial.println( myLog.MinLight) ;
     Serial.print("MaxLight :") ;
     Serial.println( myLog.MaxLight) ;
     Serial.print("MinTemp :") ;
     Serial.println( myLog.MinTemp) ;
     Serial.print("MaxTemp :") ;
     Serial.println( myLog.MaxTemp) ;    
}
// *****************************************************************************
//                       Write Byte to EEPROM
// *****************************************************************************
void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) {
     Wire.beginTransmission(deviceaddress);
     Wire.send((int)(eeaddress >> 8));   // MSB
     Wire.send((int)(eeaddress & 0xFF)); // LSB
     Wire.send(data);
     Wire.endTransmission();

     delay(5);
}
// *****************************************************************************
//                       Read Byte from EEPROM
// *****************************************************************************
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) {
     byte rdata = 0xFF;

     Wire.beginTransmission(deviceaddress);
     Wire.send((int)(eeaddress >> 8));   // MSB
     Wire.send((int)(eeaddress & 0xFF)); // LSB
     Wire.endTransmission();

     Wire.requestFrom(deviceaddress,1);

     if (Wire.available()) rdata = Wire.receive();

     return rdata;
}

Normally, the IDE creates function prototypes for you.

You can't call a function unless the compiler knows what the signature is for a function. You don't normally need to define the prototype (for the Arduino) because the IDE does that for you.

There is a bug in the IDE, though, that prevents it from creating prototypes for functions with references (the & indicates a reference). The EEPROM_writeAnything and EEPROM_readAnything functions use references.

If having them on top bothers you, put them in another file, with a .h extension, and #include that file in the sketch.