Problem with union and I2C eeprom [SOLVED]

Hi there,

I try to save float values into an I2C eeprom, without to use libraries.

I saw here in the forum (in spanish) this code, what save float and integer alues into the inner eeprom byt the use of union.

I modified the code a little bit because i want to save just only float values into an external I2C eeprom.

The modified code looks like this:

#include <Wire.h>

int eepromaddress = 0x50;
union Float_Byte {
float datoF;
byte  datoB[4];
} unionFB;

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


void loop(){
  unionFB.datoF = -12.13 ;
  Serial.print("\nFloat 1: ") ;
  Serial.println(unionFB.datoF);
  Serial.print("\nbyte1: ");  Serial.print(unionFB.datoB[0], DEC) ; // 123
  Serial.print("\nbyte2: ");  Serial.print(unionFB.datoB[1], DEC) ; // 20
  Serial.print("\nbyte3: ");  Serial.print(unionFB.datoB[2], DEC) ; // 66
  Serial.print("\nbyte4: ");  Serial.print(unionFB.datoB[3], DEC) ; // 193
 
  // save the number (divided in bytes) into the I2C eeprom
  eeprom_write_byte(200, unionFB.datoB[0]);
  eeprom_write_byte(201, unionFB.datoB[1]);
  eeprom_write_byte(202, unionFB.datoB[2]);
  eeprom_write_byte(203, unionFB.datoB[3]);
   
 
  // reconstruct the float number from the I2C eeprom
  unionFB.datoF = 0.0 ;
  unionFB.datoB[0] =  eeprom_read_byte(200);
  unionFB.datoB[1] =  eeprom_read_byte(201);
  unionFB.datoB[2] =  eeprom_read_byte(202);
  unionFB.datoB[3] =  eeprom_read_byte(203);

  Serial.print("\n\nFloat 2: ");
  Serial.println(unionFB.datoF);
     

  delay(5555);
}

// function to write bytes to external EEPROM
void eeprom_write_byte(unsigned int eeaddress, byte data){
  int rdata = data;
  Wire.beginTransmission(eepromaddress);
  Wire.write((int)(eeaddress >> 8)); 
  Wire.write((int)(eeaddress & 0xFF));
  Wire.write(rdata);
  Wire.endTransmission();
  delay(10);
}

// function to read bytes from external EEPROM
byte eeprom_read_byte(unsigned int eeaddress){
  byte rdata = 0xFF;
  Wire.beginTransmission(eepromaddress);
  Wire.write((int)(eeaddress >> 8)); 
  Wire.write((int)(eeaddress & 0xFF));
  Wire.endTransmission(); 
  Wire.requestFrom(eepromaddress, 1);
  if (Wire.available()){
    rdata = Wire.read();
  }
  return rdata;
}

The code compiles without problems, but the result is not good, because i could not have the number back from the eeprom (in my case, an 24LC512, with 0x50 in address). This is the serial output:

Float 1: -12.13

byte1: 123
byte2: 20
byte3: 66
byte4: 193

Float 2: nan

I use arduino nano and arduino ide 1.5.8 under windows 10.

Could you see where is the problem?
Thanks in advance!

Your problem is that you are trying to do two things at once. You do not know which of the two things is causing the problem.

Try this and post the output:

#include <Wire.h>

int eepromaddress = 0x50;
union Float_Byte {
float datoF;
byte  datoB[4];
} unionFB;

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


void loop(){
  unionFB.datoF = -12.13 ;
  Serial.print("\nFloat 1: ") ;
  Serial.println(unionFB.datoF);
  Serial.print("\nbyte1: ");  Serial.print(unionFB.datoB[0], DEC) ; // 123
  Serial.print("\nbyte2: ");  Serial.print(unionFB.datoB[1], DEC) ; // 20
  Serial.print("\nbyte3: ");  Serial.print(unionFB.datoB[2], DEC) ; // 66
  Serial.print("\nbyte4: ");  Serial.print(unionFB.datoB[3], DEC) ; // 193
 
  // save the number (divided in bytes) into the I2C eeprom
  eeprom_write_byte(200, unionFB.datoB[0]);
  eeprom_write_byte(201, unionFB.datoB[1]);
  eeprom_write_byte(202, unionFB.datoB[2]);
  eeprom_write_byte(203, unionFB.datoB[3]);
  
 
  // reconstruct the float number from the I2C eeprom
  unionFB.datoF = 0.0 ;
  unionFB.datoB[0] =  eeprom_read_byte(200);
  unionFB.datoB[1] =  eeprom_read_byte(201);
  unionFB.datoB[2] =  eeprom_read_byte(202);
  unionFB.datoB[3] =  eeprom_read_byte(203);

  Serial.print("\nbyte1 2: ");  Serial.print(unionFB.datoB[0], DEC) ;
  Serial.print("\nbyte2 2: ");  Serial.print(unionFB.datoB[1], DEC) ; 
  Serial.print("\nbyte3 2: ");  Serial.print(unionFB.datoB[2], DEC) ;
  Serial.print("\nbyte4 2: ");  Serial.print(unionFB.datoB[3], DEC) ;
  Serial.print("\n\nFloat 2: ");
  Serial.println(unionFB.datoF);
    

  delay(5555);
}

// function to write bytes to external EEPROM
void eeprom_write_byte(unsigned int eeaddress, byte data){
  int rdata = data;
  Wire.beginTransmission(eepromaddress);
  Wire.write((int)(eeaddress >> 8));
  Wire.write((int)(eeaddress & 0xFF));
  Wire.write(rdata);
  Wire.endTransmission();
  delay(10);
}

// function to read bytes from external EEPROM
byte eeprom_read_byte(unsigned int eeaddress){
  byte rdata = 0xFF;
  Wire.beginTransmission(eepromaddress);
  Wire.write((int)(eeaddress >> 8));
  Wire.write((int)(eeaddress & 0xFF));
  Wire.endTransmission();
  Wire.requestFrom(eepromaddress, 1);
  if (Wire.available()){
    rdata = Wire.read();
  }
  return rdata;
}

This will tell you if the problem is because of the union or because of the eeprom. I suspect the eemprom is not working and the 4 bytes are being read as 255, 255, 255, 255.

Thanks @PaulRB,

I tried your code and this is the serial output:

Float 1: -12.13

byte1: 123
byte2: 20
byte3: 66
byte4: 193
byte1 2: 255
byte2 2: 255
byte3 2: 255
byte4 2: 255

Float 2: nan

However, the I2C eeprom is working, because in fact, i have it connected for some months ago working storing and reading DS18B20 serial numbers…

I tried again your code with other epprom i have connected in serie with this one, and the result is exactly the same... it returns 255,255,255,255

I am so, so, so, so stupid!

The problem was not the eeprom, but my code… i forget to add this line of code in the setup() section:

Wire.begin();

Now it works great!!

I am so sorry for waste your time and patience!!

In any case, i leave here the working code in case others looks for how to save floats on external eeproms!

#include <Wire.h>

int eepromaddress = 0x50;
union Float_Byte {
float datoF;
byte  datoB[4];
} unionFB;
byte A = 5;

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


void loop(){
  unionFB.datoF = -12.13 ;
  Serial.print("\nFloat 1: ") ;
  Serial.println(unionFB.datoF);
  Serial.print("\nbyte1: ");  Serial.print(unionFB.datoB[0], DEC) ; // 123
  Serial.print("\nbyte2: ");  Serial.print(unionFB.datoB[1], DEC) ; // 20
  Serial.print("\nbyte3: ");  Serial.print(unionFB.datoB[2], DEC) ; // 66
  Serial.print("\nbyte4: ");  Serial.print(unionFB.datoB[3], DEC) ; // 193
  Serial.print("Control number: ");
  Serial.println(A);
 
  // save the number (divided in bytes) into the I2C eeprom
  eeprom_write_byte(20, unionFB.datoB[0]);
  eeprom_write_byte(21, unionFB.datoB[1]);
  eeprom_write_byte(22, unionFB.datoB[2]);
  eeprom_write_byte(23, unionFB.datoB[3]);
  eeprom_write_byte(24, A);
 
  // reconstruct the float number from the I2C eeprom
  unionFB.datoF = 0.0 ;
  unionFB.datoB[0] =  eeprom_read_byte(20);
  unionFB.datoB[1] =  eeprom_read_byte(21);
  unionFB.datoB[2] =  eeprom_read_byte(22);
  unionFB.datoB[3] =  eeprom_read_byte(23);

  Serial.print("\nbyte1 2: ");  Serial.print(unionFB.datoB[0], DEC) ;
  Serial.print("\nbyte2 2: ");  Serial.print(unionFB.datoB[1], DEC) ;
  Serial.print("\nbyte3 2: ");  Serial.print(unionFB.datoB[2], DEC) ;
  Serial.print("\nbyte4 2: ");  Serial.print(unionFB.datoB[3], DEC) ;
  Serial.print("\n\nFloat 2: ");
  Serial.println(unionFB.datoF);
  Serial.print("Control number: ");
  Serial.println(eeprom_read_byte(24));
  delay(5555);
}

// function to write bytes to external EEPROM
void eeprom_write_byte(unsigned int eeaddress, byte data){
  int rdata = data;
  Wire.beginTransmission(eepromaddress);
  Wire.write((int)(eeaddress >> 8));
  Wire.write((int)(eeaddress & 0xFF));
  Wire.write(rdata);
  Wire.endTransmission();
  delay(10);
}

// function to read bytes from external EEPROM
byte eeprom_read_byte(unsigned int eeaddress){
  byte rdata = 0xFF;
  Wire.beginTransmission(eepromaddress);
  Wire.write((int)(eeaddress >> 8));
  Wire.write((int)(eeaddress & 0xFF));
  Wire.endTransmission();
  Wire.requestFrom(eepromaddress, 1);
  if (Wire.available()){
    rdata = Wire.read();
  }
  return rdata;
}

Cheers,