How to write float value in EEPROM

Hello all,
I am new to Arduino.
I am using Ph sensor and want to save my ph sensor reading in EEPROM. whenever i am reading value in EEPROM, its only printing integer value.
can somebody help me in this regards??
here is my code:

#include <EEPROM.h>

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);

float ph_water=7.0;
float ph_sample;
float phaddr=0;
float offset=0.40;
const int phpin = A0;





void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Welcome");
}

void loop() {
    int adcValue = analogRead(phpin);
  float phVoltage = (float)adcValue * 5.0 / 1024;
 ph_sample=(3.5*phVoltage)+offset;     
  Serial.print("phValue= "); 
  Serial.print(ph_sample);
  Serial.print("Po  = "); 
  Serial.println(phVoltage, 3);
  delay(1000);

  if (ph_water>=ph_sample){
    EEPROM.write(phaddr,  ph_sample);

    float value=EEPROM.read(phaddr);
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("phaddress=");
    lcd.print(phaddr);
    lcd.setCursor(0,2);
    lcd.print("phvalue=");
    lcd.print(value);
phaddress = phaddress + 1;
    if(phaddress== EEPROM.length()) {
    phaddress = 0;
  }

  }
  else {
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Ph is High");
    lcd.setCursor(0,2);
    lcd.print("Refill Solution");
  }
  


}

EEPROM.write() writes a single byte
EEPROM.read() reads a single byte

Try using EEPROM.put() and EEPROM.get() instead

1 Like

Thank you so much for response.
It worked out.

And yet, we should know why your codes did not work:

1. The syntax of EEPROM.write() command is:
EEPROM.write(address, byteData);

That means the allowable data range is: 0 to 255 (1-byte = 0x00 to 0xFF) -- only integer value and no fractional part.

2. When there is a floating point number (having integer and fractional part) like float x = 13.67, then four consecutive memory locations are needed to store the value of x. The said four memory locations will hole 32-bit (4x8) data which are genertaed according to binary332/IEEE-754 standard (Fig-1).

IEEE754Float
Figure-1:

3. Using write() method, we can store the value x of Step-2 by executing the following codes:

  float x = 13.67;
  byte *ptr;   
  ptr = (byte*)&x;  //ptr holds beginning address of 4-byte memory space containing value of x 
  for (int i = 0, address = 0; i < 4; i++, address++, ptr++)
  {
    EEPROM.write(address, *ptr);
  }

4. All the codes of Step-3 can be replaced by the following two lines of codes:

float x = 13.67;
EEPROM.put(address, x);

@UKHeliBob explained that already very clearly.

EEPROM.write() writes a single byte

what you explained is not why it did not work, it's what got really written in memory...

Flash memory has limited number of write cycles and it looks like you are killing it by writing to it in a loop. At least consider .update so that it won’t write the same value over and over.

It's quite simple

Thank you so much for explanation. It helps me to understand in depth.

And yet, the @ashish_senger has made the mistake which proves that it is a difficult task for him. Therefore, the theroy of the EEPROM.write(unsigned int arg1, byte arg2) method should be made clearer to him by way of examples.

What I meant was that the explanation was quite simple. Personally I think that you have made the explanation more complicated by bringing up the subject of how a float is represented in memory and how the value of the float is calculated from that representation. None of that matters in this case

But, it is related in order to know why the OP
should execute write() method four times if not using put() method.

Are you really suggesting that the the OP writes 4 bytes to EEPROM to save a float, to say nothing of the problem of reading it back

Thank you everyone for helping me out.
My program is working fine.

Please post your working code as it may help others with a similar problem in the future

Here is the final code for.

#include <EEPROM.h>

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);

float ph_water=7.0;
float ph_sample;
float phaddr=0;
float offset=0.00;   /*update this value during calibration phase*/
const int phpin = A0;





void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Welcome");
}

void loop() {
    int adcValue = analogRead(phpin);
  float phVoltage = (float)adcValue * 5.0 / 1024;
 ph_sample=(3.5*phVoltage)+offset;     
  Serial.print("phValue= "); 
  Serial.print(ph_sample);
  Serial.print("Po  = "); 
  Serial.println(phVoltage, 3);
  delay(1000);

  if (ph_water>=ph_sample){
    EEPROM.put(phaddr,  ph_sample);
    float value=EEPROM.get(phaddr);
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("phaddress=");
    lcd.print(phaddr);
    lcd.setCursor(0,2);
    lcd.print("phvalue=");
    lcd.print(value);

  }
  else {
    lcd.clear();
    lcd.setCursor(0,1);
    lcd.print("Ph is High");
    lcd.setCursor(0,2);
    lcd.print("Refill Solution");
  }
  


}

Remember you can only write 100,000 times at a given address in EEPROM

A float value - with the variability or analogRead() - is likely to change slightly often.

You have a 1 second delay between two reads, if the value keeps changing (even slightly) and is above the threshold at every read then you’ll destroy ERPROM address 0 in a bit more than a day (roughly in 27h and 47 min)

You might want to only keep 1 significant digit (or none - do you know the orecision of your device?) and adopt a strategy where you write to EEPROM only when you get significant changes or (with a bit of extra hardware) when the arduino looses power only

Thank you so much for your explanation. It is just a basic code. i am still working and trying to reduce the sample size (Applying for loop or using average method ). so i can merge 10-15 values in a single output.

There are chips that can store data without limits: https://www.adafruit.com/product/1895.

You could store the sample to EEPROM, and store the next sample 4 bytes further. At the end of the EEPROM, loop around and keep track of where the new data should be stored. Then you would have the 128 latest samples.
It needs good code and a mistake is easily made.

Using the average of a few samples is always good.