combining two parts of a float EEPROM

I’m trying to print temperature data of the form 22.45 i.e. 2 decimal places.

I need to store it to EEPROM and retrieve it and print it from serial (using it as a memory storage to send at certain intervals).
I can store it to EEPROM fine, and send it fine as just integers, but to try and do it as a float which is what i need, i can’t seem to do

I’ve used the EEPROManything.h in a seperate tab to store anything over (i assume) a few bytes, but bringing it back together and printing it as a float i have no ideas?

my code at the moment if it helps anyone:

#include <EEPROM.h>
#include "EEPROManything.h"

  struct config_t {
    float temp;
  } store;

int addr =100;
int tempPin = 1;
int n1;
int n2;
float output;

void setup(){
    Serial.begin(9600);   
}
void loop(){
   store.temp = ((analogRead(tempPin) * 0.004882814)-0.5)*100; //conversion to temp
    
    // Write the configuration struct to EEPROM
    EEPROM_writeAnything(addr, store.temp);
    // Read and print the contents of EEPROM
    n1 = EEPROM.read(addr);  
    n2 = EEPROM.read(addr+1);  //assuming a float outputs over two bytes
    Serial.print(n1); Serial.print("\t");
    Serial.print(n2);Serial.print("\t");
   //Bring together somehow:


    addr= addr + 2;
    if(addr == 4096){
      addr = 0;
    }
     delay(1000);
}

I know this is a pretty standard problem, but i’ve searched the forums, and not found a solution i can alter to suit my needs.

Thanks

I’ve used the EEPROManything.h in a seperate tab to store anything over (i assume) a few bytes, but bringing it back together and printing it as a float i have no ideas?

Well the EEPROManything.h I got from this site contained both a way to write the structure variables and a way to read back the structure variables. See if this makes sense.

Sketch:

#include <EEPROM.h>
#include "eetest.h"

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


void setup()
{
    Serial.begin(9600);
/*
    configuration.alarm = 22.45;  // comment out after inital eeprom written
    configuration.mode = 1;          // same

    // Write the configuration struct to EEPROM
   EEPROM_writeAnything(0, configuration);  // comment out after first written
   
// above three code lines could be a function in main sketch to save something away.
*/
}

void loop()
{
    // Read and print the contents of EEPROM
    EEPROM_readAnything(0, configuration);    
    Serial.print("alarm  = ");Serial.println(configuration.alarm,2);
    Serial.print("mode   = ");Serial.println(configuration.mode);

   // A "do nothing loop" where your real working code would be
    while(1)
     ;
}

eetest.h in seperate tabbed sheet:

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

I've used the EEPROManything.h in a seperate tab to store anything over (i assume) a few bytes, but bringing it back together and printing it as a float i have no ideas?

Why not use the corresponding EEPROM_readAnything method?

If that is not what you want to do, for some reason, you should at least be aware that you wrote 4 bytes to EEPROM. You'll never reassemble the float by reading just two bytes.

The bytes that you wrote do not contain the integer portion of the float and the decimal portion, if that's what you are expecting to see in them.

Be sure to space the variables written with eeprom-anything out a bit, like mentioned above a float takes four addresses in eeprom, so you need to make sure there is room.

Write a float to 0 and it consumes 0,1,2,3. If you change one or more of those addresses via another method (like writing another variable to address 3 for instance) your number will come back with issues.

Just a suggestion to make your life easier-- why not store as an int in hundredths of a degree? I.e. 22.45 degrees is an int 2245. Then, when it comes time to use those numbers, format them with a decimal point, or convert to float and divide by 100.

Thanks for the replies!

Initially i used EEPROM_readAnything.. this might be totally foolish of me, but it was outputting 4 when i printed it to serial, so i assumed it was storing the float as 4 addresses in the EEPROM, and just telling me that?... as it kept just outputting 4, not the float split in four or anything else. Is this what is supposed to happen? or am i doing something wrong/missing something to print it normally

Thats a good idea bilbo, if i can't get EEPROM_readAnything to work, i'll have a shot at that!

Thanks again

Initially i used EEPROM_readAnything… this might be totally foolish of me, but it was outputting 4 when i printed it to serial, so i assumed it was storing the float as 4 addresses in the EEPROM, and just telling me that?

You are again asking us to debug code that we can’t see. No, not today.

My mistake, i thought i was just miss-understanding the use of EEPROM_readAnything so i wouldn’t need code as i couldnt really find any tutorials, only ones on how to set up the header files.
The way (i thought) EEPROM_readAnything was supposed to work ive put below, but it outputs 4 which from what i’ve read it seemed readAnything was a check that outputted how many bytes were written and that you weren’t able to use to print said bytes

#include <EEPROM.h>
#include "EEPROManything.h"

struct config_t{
float temp;
} store;

int addr = 1;
int tempPin = 1;
float n;

void setup(){
    Serial.begin(9600);   
}
void loop(){
   store.temp = ((analogRead(tempPin) * 0.004882814)-0.5)*100;; 
    // Write the configuration struct to EEPROM
    EEPROM_writeAnything(addr, store.temp);
    // Read and print the contents of EEPROM
    n = EEPROM_readAnything(addr, store.temp);    
    Serial.println(n);
    addr++;
    if(addr == 4096){
      addr = 0;
    }
     delay(1000);
}

Thanks

The EEPROM_readAnything function takes two arguments, the address to read from and where to store the value read, and returns the number of bytes read.

So, you are printing the number of bytes read, not the bytes read.

So, 4 is correct, for having read a float. The value that was read is in store.temp, which you do not bother printing.

EEPROM has a limit on how many times you can write to it. Writing on every pass through loop will wear it out relatively quickly.

Some corrections and comments in Blue:

#include <EEPROM.h>
#include “EEPROManything.h”

struct config_t{
float temp;
} store;

int addr = 0; // First address to read or write in EEPROM is address zero not 1
int tempPin = 1;
float n;

void setup(){
Serial.begin(9600);
}
void loop(){
store.temp = ((analogRead(tempPin) * 0.004882814)-0.5)*100;;
// Write the configuration struct to EEPROM
EEPROM_writeAnything(addr, store.temp);
// Read and print the contents of EEPROM
n = EEPROM_readAnything(addr, store.temp);
Serial.println(n);
//addr++; //error, floats written to EEPROM memory take up four consecutive bytes
//of addresses, so use:
addr = addr + sizeof(store.temp);

if(addr == 4096) // note that this is end of EEPROM for mega chips avr1280/2560, 328 chips
//use 1024
{
addr = 0;
}
delay(1000);
}

Try those changes.

Lefty

   addr = addr + sizeof(store.temp);

Even better, in my opinion, is:

addr += EEPROM_readAnything(addr, store.temp);

EEPROM_readAnything already determined how many bytes of data it read, so why not use that value, instead of recalculating?

addr += EEPROM_readAnything(addr, store.temp);  EEPROM_readAnything already determined how many bytes of data it read, so why not use that value, instead of recalculating?

Because that hurts my head even trying to figure out what/how that works.

Make mine addr = addr + sizeof(store.temp); , I will know what and how that works when I read it back in a year or so. :D

Lefty

After 20 minutes with C, the += thing felt so much more natural than x = x + 1; that I hate going back and trying to do anything in FORTRANm which doesn't have all the compound operators that C has.

If you don't like addr += EEPROM_readAnything(addr, store.temp); , that's fine. But, EEPROM_readAnything already computed the number of bytes involved, and returned that, which OP stored in n. So, addr = addr +n; would remove the need to recompute the size.

PaulS: After 20 minutes with C, the += thing felt so much more natural than x = x + 1; that I hate going back and trying to do anything in FORTRANm which doesn't have all the compound operators that C has.

If you don't like addr += EEPROM_readAnything(addr, store.temp); , that's fine. But, EEPROM_readAnything already computed the number of bytes involved, and returned that, which OP stored in n. So, addr = addr +n; would remove the need to recompute the size.

No I appreciate the insight you share so often around here. My C/C++ experience would be less without so many of your comments.

I did go look at the what and how of the returned value of EEPROM_readAnything. It's just I know if I was reading the code a year from now I would go, Damn now I have to go read EEPROM_readAnything to see what it returns. The one I wrote tells me up front.

Maybe a compromise? How about addr += sizeof(store.temp); :D

Maybe a compromise? How about addr += sizeof(store.temp);

I guess I missed what you were concerned about forgetting after a while. I agree that it is not obvious that EEPROM_readAnything will return the number of bytes read. I had to look at the code to see that. So, I'll go along with addr += sizeof(store.temp);.