Arduino Using EEPROM

don't worry about that part if you don't understand it. Just use the put() method - that will write any data (and read using get)

okay im looking at the arduino ide example sket, focusing on this part of the code,,

float f = 123.456f; //Variable to store in EEPROM.
int eeAddress = 0; //Location we want the data to be put.

do i need a different "int eeAddress = 0 for each vaariable?"

int eeAddress = 0
int eeAddress = 1
int eeAddress = 2?

and if im using longs is it valid to use

eeAddress += sizeof(long); //Move address to the next byte after float 'f'.
instead of
eeAddress += sizeof(float); //Move address to the next byte after float 'f'.

you can see the EEPROM as a line of boxes - each box can hold 1 byte. The put() function will look at how many bytes are needed for your parameter (for example 4 bytes for your float on a UNO) and if you ask to save your float starting at box #0 then it will fill Boxes #0 #1 #2 and #3.

if you want to save a second element you want to make sure you don't store it in a box that has already a value, you need to start in box #4.

when you do eeAddress += sizeof(float); this is exactly what you do: you take into account how many boxes were needed to store your float and you set the eeAddress to the next available box

so depending on the data type you store, you need to add the right number of bytes to the address (so indeed use long if what you stored is a long)

this becomes tedious, that's why if you put everything in a structure, then you can just put() the structure in EEPROM and all will be taken care of for you

J-M-L:
you can see the EEPROM as a line of boxes - each box can hold 1 byte. The put() function will look at how many bytes are needed for your parameter (for example 4 bytes for your float on a UNO) and if you ask to save your float starting at box #0 then it will fill Boxes #0 #1 #2 and #3.

if you want to save a second element you want to make sure you don’t store it in a box that has already a value, you need to start in box #4.

when you do eeAddress += sizeof(float); this is exactly what you do: you take into account how many boxes were needed to store your float and you set the eeAddress to the next available box

thankyou for clearing that up, so far with the EEPROM.put() i have come up with this is this okay? im not sure because i know originally it was designed for use of floats in this example?

/***
    eeprom_put example.

    This shows how to use the EEPROM.put() method.
    Also, this sketch will pre-set the EEPROM data for the
    example sketch eeprom_get.

    Note, unlike the single byte version EEPROM.write(),
    the put method will use update semantics. As in a byte
    will only be written to the EEPROM if the data is actually
    different.

    Written by Christopher Andrews 2015
    Released under MIT licence.
***/

#include <EEPROM.h>

struct MyObject {
  float field1;
  byte field2;
  char name[10];
};

void setup() {

  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

unsigned long t1ontimeDAY = 10700;                       /////
unsigned long t1offtimeDAY = 10000;  
unsigned long t2ontimeDAY = 13400;                       /////
unsigned long t2offtimeDAY = 10000; 
unsigned long t3ontimeDAY = 0;                           /////
unsigned long t3offtimeDAY = 0;  
unsigned long t1ontimeNIGHT = 10000;                     /////
unsigned long t1offtimeNIGHT = 50000;  
unsigned long t2ontimeNIGHT = 12400;                     /////
unsigned long t2offtimeNIGHT = 50000; 
unsigned long t3ontimeNIGHT = 10;                         /////
unsigned long t3offtimeNIGHT = 10;  //Variable to store in EEPROM
  int eeAddress = 0;   //Location we want the data to be put.


  //One simple call, with the address first and the object second.
  EEPROM.put(eeAddress, t1ontimeDAY);
  EEPROM.put(eeAddress, t1offtimeDAY);
  EEPROM.put(eeAddress, t2ontimeDAY);
  EEPROM.put(eeAddress, t2offtimeDAY);
  EEPROM.put(eeAddress, t3ontimeDAY);
  EEPROM.put(eeAddress, t3offtimeDAY);
  EEPROM.put(eeAddress, t1ontimeNIGHT);
  EEPROM.put(eeAddress, t1offtimeNIGHT);
  EEPROM.put(eeAddress, t2ontimeNIGHT);
  EEPROM.put(eeAddress, t2offtimeNIGHT);
  EEPROM.put(eeAddress, t3ontimeNIGHT);
  EEPROM.put(eeAddress, t3offtimeNIGHT);

  Serial.println("Written float data type!");

  eeAddress += sizeof(long); //Move address to the next byte after float 'f'.

}

void loop() {
  /* Empty loop */
}

okay so i stored the long variables in the eeprom with the first eeprom.put() i posted right above. but now when i read them it dont display the correct value?

#include <EEPROM.h>

void setup() {

 unsigned long t1ontimeDAY = 10700;                       /////
unsigned long t1offtimeDAY = 10000;  
unsigned long t2ontimeDAY = 13400;                       /////
unsigned long t2offtimeDAY = 10000; 
unsigned long t3ontimeDAY = 0;                           /////
unsigned long t3offtimeDAY = 0;  
unsigned long t1ontimeNIGHT = 10000;                     /////
unsigned long t1offtimeNIGHT = 50000;  
unsigned long t2ontimeNIGHT = 12400;                     /////
unsigned long t2offtimeNIGHT = 50000; 
unsigned long t3ontimeNIGHT = 10;                         /////
unsigned long t3offtimeNIGHT = 10;  //Variable to store data read from EEPROM.
int eeAddress = 0; //EEPROM address to start reading from

  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print("Read float from EEPROM: ");

  //Get the float data from the EEPROM at position 'eeAddress'
  EEPROM.get(eeAddress, t1ontimeDAY);
  EEPROM.get(eeAddress, t1offtimeDAY);
  EEPROM.get(eeAddress, t2ontimeDAY);
  EEPROM.get(eeAddress, t2offtimeDAY);
  EEPROM.get(eeAddress, t3ontimeDAY);
  EEPROM.get(eeAddress, t3offtimeDAY);
  EEPROM.get(eeAddress, t1ontimeNIGHT);
  EEPROM.get(eeAddress, t1offtimeNIGHT);
  EEPROM.get(eeAddress, t2ontimeNIGHT);
  EEPROM.get(eeAddress, t2offtimeNIGHT);
  EEPROM.get(eeAddress, t3ontimeNIGHT);
  EEPROM.get(eeAddress, t3offtimeNIGHT);
  Serial.println(t1ontimeDAY);    //This may print 'ovf, nan' if the data inside the EEPROM is not a valid float.
}
  /***
    As get also returns a reference to 'f', you can use it inline.
    E.g: Serial.print( EEPROM.get( eeAddress, f ) );
  ***/

  /***
    Get can be used with custom structures too.
    I have separated this into an extra function.
  ***/



void loop() {
  /* Empty loop */
}

J-M-L:
you can see the EEPROM as a line of boxes - each box can hold 1 byte. The put() function will look at how many bytes are needed for your parameter (for example 4 bytes for your float on a UNO) and if you ask to save your float starting at box #0 then it will fill Boxes #0 #1 #2 and #3.

if you want to save a second element you want to make sure you don't store it in a box that has already a value, you need to start in box #4.

when you do eeAddress += sizeof(float); this is exactly what you do: you take into account how many boxes were needed to store your float and you set the eeAddress to the next available box

so depending on the data type you store, you need to add the right number of bytes to the address (so indeed use long if what you stored is a long)

this becomes tedious, that's why if you put everything in a structure, then you can just put() the structure in EEPROM and all will be taken care of for you

you make it sound so easy i have no idea what im doing

Here is a quick example showing how I deal with this

#include <EEPROM.h>
// __attribute__ ((packed)) is to force the compiler to use the minimum required memory to represent the type
// see https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html
struct __attribute__ ((packed)) _paramS {
  int16_t minimumT;
  int16_t maximumT;
} myParamters;

const uint32_t keyword = 0xDEADBEEF;
const uint16_t keywordAddress = 0x00;
const uint16_t paramAddress = keywordAddress + sizeof(keyword);

void printParam()
{
  Serial.println(F("\n************* PARAMS *************"));
  Serial.print(F("Temp min =\t")); Serial.println(myParamters.minimumT);
  Serial.print(F("Temp max =\t")); Serial.println(myParamters.maximumT);
}

void saveParam()
{
  EEPROM.put(keywordAddress, keyword);
  EEPROM.put(paramAddress, myParamters);
}

void getParam()
{
  uint32_t tmpKey;

  EEPROM.get(keywordAddress, tmpKey);
  if (tmpKey == keyword) {
    EEPROM.get(paramAddress, myParamters);    // EEPROM was already initialized OK to read
  } else {
    // First run on this arduino, memory was never initialized. so establish default values
    myParamters.minimumT = -22;
    myParamters.maximumT = 44;
    saveParam();
  }
}


void setup() {
  Serial.begin(115200);

  getParam();  // first run will establish the defaults in EEPROM
  printParam(); // see what the values are

  myParamters.minimumT = -55;  // change one of the parameters
  saveParam(); // save it
  printParam(); // show it has been saved
}

void loop() {}

all the values I want to save are in the myParamters structure. in the setup() you call the getParam() function which will either read what is already there in EEPROM if the memory was already initialized or will write there default values and initialize the structure

every time you change the structure (one of your parameter) you just call saveParam() to update the EEPROM.

→ run the program with your serial console opened at 115200 bauds. first time you run the program you’ll see that default values are written, then the minimumT param is updated to -55° and if you run the code a second time (close and re-open the serial console for example) you’ll see that the second time the minimumT param will already be at -55° instead of -22°

  EEPROM.put(eeAddress, t1ontimeDAY);
  EEPROM.put(eeAddress, t1offtimeDAY);
  EEPROM.put(eeAddress, t2ontimeDAY);

Do you understand the concept of putting different values at different addresses?

J-M-L:
Here is a quick example showing how I deal with this

#include <EEPROM.h>

// attribute ((packed)) is to force the compiler to use the minimum required memory to represent the type
// see Using the GNU Compiler Collection (GCC)
struct attribute ((packed)) _paramS {
 int16_t minimumT;
 int16_t maximumT;
} myParamters;

const uint32_t keyword = 0xDEADBEEF;
const uint16_t keywordAddress = 0x00;
const uint16_t paramAddress = keywordAddress + sizeof(keyword);

void printParam()
{
 Serial.println(F("\n************* PARAMS *************"));
 Serial.print(F(“Temp min =\t”)); Serial.println(myParamters.minimumT);
 Serial.print(F(“Temp max =\t”)); Serial.println(myParamters.maximumT);
}

void saveParam()
{
 EEPROM.put(keywordAddress, keyword);
 EEPROM.put(paramAddress, myParamters);
}

void getParam()
{
 uint32_t tmpKey;

EEPROM.get(keywordAddress, tmpKey);
 if (tmpKey == keyword) {
   EEPROM.get(paramAddress, myParamters);    // EEPROM was already initialized OK to read
 } else {
   // First run on this arduino, memory was never initialized. so establish default values
   myParamters.minimumT = -22;
   myParamters.maximumT = 44;
   saveParam();
 }
}

void setup() {
 Serial.begin(115200);

getParam();  // first run will establish the defaults in EEPROM
 printParam(); // see what the values are

myParamters.minimumT = -55;  // change one of the parameters
 saveParam(); // save it
 printParam(); // show it has been saved
}

void loop() {}




all the values I want to save are in the `myParamters` structure. in the setup() you call the `getParam()` function which will either read what is already there in EEPROM if the memory was already initialized or will write there default values and initialize the structure

every time you change the structure (one of your parameter) you just call `saveParam()` to update the EEPROM. 

--> run the program with your serial console opened at 115200 bauds. first time you run the program you'll see that default values are written, then the `minimumT` param is updated to -55° and if you run the code a second time (close and re-open the serial console for example) you'll see that the second time the `minimumT` param will already be at -55° instead of -22°

i ran your example code but both times it printed the same thing on the console. can you show me an example with an unsigned long please?

TolpuddleSartre:

  EEPROM.put(eeAddress, t1ontimeDAY);

EEPROM.put(eeAddress, t1offtimeDAY);
  EEPROM.put(eeAddress, t2ontimeDAY);



Do you understand the concept of putting different values at different addresses?

i do not. i know nothing about memory addresses or byte arrays structure arrays or any of that.

what i need is an example using 2 different unsigned longs that when changed i can call a function and update them. i could probably work from something like that. i could call the update function from a serial command.

notsolowki:
i ran your example code but both times it printed the same thing on the console.

Probably the code ran once without you noticing (ie the serial console was not opened when you first uploaded)

notsolowki:
can you show me an example with an unsigned long please?

Well just put unsigned long in the structure...

struct __attribute__ ((packed)) _paramS {
  unsigned long minimumT;
  unsigned long maximumT;
} myParamters;

of course you need to adjust the values as you can't store -22 or -55 in an unsigned...

change the keyword to something else so that default values are written again

J-M-L:
Probably the code ran once without you noticing (ie the serial console was not opened when you first uploaded)

Well just put unsigned long in the structure...

struct __attribute__ ((packed)) _paramS {

unsigned long minimumT;
  unsigned long maximumT;
} myParamters;


of course you need to adjust the values as you can't store -22 or -55 in an unsigned...


change the keyword to something else so that default values are written again

your right it is working. i'm starting to figure it out i'm going to spend some time trial and error. thanks again

hey im back, when i run this code none of the default values are correct?

#include <EEPROM.h>
// __attribute__ ((packed)) is to force the compiler to use the minimum required memory to represent the type
// see https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html
struct __attribute__ ((packed)) _paramS {
  unsigned long minimumT;
  unsigned long maximumT;
  unsigned long maximumA;
  unsigned long maximumB;
  unsigned long t1ontimeDAY;                       /////
  unsigned long t1offtimeDAY;  
  unsigned long t2ontimeDAY;                       /////
  unsigned long t2offtimeDAY; 
  unsigned long t3ontimeDAY;                           /////
  unsigned long t3offtimeDAY; 
   
  unsigned long t1ontimeNIGHT;                     /////
  unsigned long t1offtimeNIGHT;  
  unsigned long t2ontimeNIGHT;                     /////
  unsigned long t2offtimeNIGHT; 
  unsigned long t3ontimeNIGHT;                         /////
  unsigned long t3offtimeNIGHT;
} myParamters;

const uint32_t keyword = 0xDEADBEEF;
const uint16_t keywordAddress = 0x00;
const uint16_t paramAddress = keywordAddress + sizeof(keyword);

void printParam()
{
  Serial.println(F("\n************* PARAMS *************"));
  Serial.print(F("Temp minn =\t")); Serial.println(myParamters.t1ontimeDAY);
  Serial.print(F("Temp maxx =\t")); Serial.println(myParamters.t2ontimeDAY);
  Serial.print(F("Temp max =\t")); Serial.println(myParamters.maximumB);
}

void saveParam()
{
  EEPROM.put(keywordAddress, keyword);
  EEPROM.put(paramAddress, myParamters);
}

void getParam()
{
  uint32_t tmpKey;

  EEPROM.get(keywordAddress, tmpKey);
  if (tmpKey == keyword) {
    EEPROM.get(paramAddress, myParamters);    // EEPROM was already initialized OK to read
  } else {
    // First run on this arduino, memory was never initialized. so establish default values
    myParamters.t1ontimeDAY = 1002001;
    myParamters.t1offtimeDAY = 1002002;
     myParamters.t2ontimeDAY = 1002001;
    myParamters.t2offtimeDAY = 1002002;
        myParamters.t3ontimeDAY = 1002001;
    myParamters.t3offtimeDAY = 1002002;
        myParamters.t1ontimeNIGHT = 1002001;
    myParamters.t1offtimeNIGHT = 1002002;
        myParamters.t2ontimeNIGHT = 1002001;
    myParamters.t2offtimeNIGHT = 1002002;
        myParamters.t3ontimeNIGHT = 1002001;
    myParamters.t3offtimeNIGHT = 1002002;
    saveParam();
  }
}


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

  getParam();  // first run will establish the defaults in EEPROM
  printParam(); // see what the values are

  myParamters.minimumT = 1002001;  // change one of the parameters
  myParamters.maximumB = 1002011;  // change one of the parameters
  saveParam(); // save it
  printParam(); // show it has been saved
}

void loop() {}

or is it that this part don’t run unless there is a problem reading from eeprom?

  EEPROM.get(keywordAddress, tmpKey);
  if (tmpKey == keyword) {
    EEPROM.get(paramAddress, myParamters);    // EEPROM was already initialized OK to read
  } else {

I’m not sure what you mean… this works for me

#include <EEPROM.h>
// __attribute__ ((packed)) is to force the compiler to use the minimum required memory to represent the type
// see https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html
struct __attribute__ ((packed)) _paramS {
  unsigned long t1ontimeDAY;
  unsigned long t1offtimeDAY;
  unsigned long t2ontimeDAY;
  unsigned long t2offtimeDAY;
  unsigned long t3ontimeDAY;
  unsigned long t3offtimeDAY;
  unsigned long t1ontimeNIGHT;
  unsigned long t1offtimeNIGHT;
  unsigned long t2ontimeNIGHT;
  unsigned long t2offtimeNIGHT;
  unsigned long t3ontimeNIGHT;
  unsigned long t3offtimeNIGHT;
} myParamters;

const uint32_t keyword = 0xBADCAFFE;
const uint16_t keywordAddress = 0x00;
const uint16_t paramAddress = keywordAddress + sizeof(keyword);

void printParam()
{
  Serial.println(F("\n************* PARAMS *************"));
  Serial.println(myParamters.t1ontimeDAY);
  Serial.println(myParamters.t1offtimeDAY);
  Serial.println(myParamters.t2ontimeDAY);
  Serial.println(myParamters.t2offtimeDAY);
  Serial.println(myParamters.t3ontimeDAY);
  Serial.println(myParamters.t3offtimeDAY);
  Serial.println(myParamters.t1ontimeNIGHT);
  Serial.println(myParamters.t1offtimeNIGHT);
  Serial.println(myParamters.t2ontimeNIGHT);
  Serial.println(myParamters.t2offtimeNIGHT);
  Serial.println(myParamters.t3ontimeNIGHT);
  Serial.println(myParamters.t3offtimeNIGHT);
}

void saveParam()
{
  EEPROM.put(keywordAddress, keyword);
  EEPROM.put(paramAddress, myParamters);
}

void getParam()
{
  uint32_t tmpKey;

  EEPROM.get(keywordAddress, tmpKey);
  if (tmpKey == keyword) {
    EEPROM.get(paramAddress, myParamters);    // EEPROM was already initialized OK to read
  } else {
    // First run on this arduino, memory was never initialized. so establish default values
    myParamters.t1ontimeDAY = 1;
    myParamters.t1offtimeDAY = 2;
    myParamters.t2ontimeDAY = 3;
    myParamters.t2offtimeDAY = 4;
    myParamters.t3ontimeDAY = 5;
    myParamters.t3offtimeDAY = 6;
    myParamters.t1ontimeNIGHT = 7;
    myParamters.t1offtimeNIGHT = 8;
    myParamters.t2ontimeNIGHT = 9;
    myParamters.t2offtimeNIGHT = 10;
    myParamters.t3ontimeNIGHT = 11;
    myParamters.t3offtimeNIGHT = 12;
    saveParam();
  }
}


void setup() {
  Serial.begin(115200);

  getParam();  // first run will establish the defaults in EEPROM
  printParam(); // see what the values are

  myParamters.t1ontimeDAY = 10;
  myParamters.t1offtimeDAY = 20;
  myParamters.t2ontimeDAY = 30;
  saveParam(); // save it
  printParam(); // show it has been saved
}

void loop() {}

this is what I see in the console (set at 115200 - there is NO reason to go slow at 9600 bauds)

[sub][color=purple]
************* PARAMS *************
[color=green]1
2
3[/color]
4
5
6
7
8
9
10
11
12

************* PARAMS *************
[color=red]10
20
30[/color]
4
5
6
7
8
9
10
11
12
[/color][/sub]

the initial values are set properly and the 3 I changed are correctly changed…

If I run the code a second time, this is what the console shows

[sub][color=purple]
************* PARAMS *************
[color=blue]10
20
30[/color]
4
5
6
7
8
9
10
11
12

************* PARAMS *************
10
20
30
4
5
6
7
8
9
10
11
12
[/color][/sub]

we can see that the first read of the data in memory noticed that memory was already initialized and thus read the 10, 20 and 30 I had written there previously

Note that I changed the keyword so that your Arduino understands not using the previous values

when i run this code none of the default values are correct?

How do you know ?

Don't forget that the program runs when you upload it and on most Arduinos opening the serial monitor resets the board and it runs again, so by the time that you see the output the program has run twice.

UKHeliBob:
How do you know ?

Don't forget that the program runs when you upload it and on most Arduinos opening the serial monitor resets the board and it runs again, so by the time that you see the output the program has run twice.

i think i got it. im going to shake it down and see what happens. thanks for all the help guys,

J-M-L:
Here is a quick example showing how I deal with this

#include <EEPROM.h>

// attribute ((packed)) is to force the compiler to use the minimum required memory to represent the type
// see Using the GNU Compiler Collection (GCC)
struct attribute ((packed)) _paramS {
  int16_t minimumT;
  int16_t maximumT;
} myParamters;

const uint32_t keyword = 0xDEADBEEF;
const uint16_t keywordAddress = 0x00;
const uint16_t paramAddress = keywordAddress + sizeof(keyword);

void printParam()
{
  Serial.println(F("\n************* PARAMS *************"));
  Serial.print(F(“Temp min =\t”)); Serial.println(myParamters.minimumT);
  Serial.print(F(“Temp max =\t”)); Serial.println(myParamters.maximumT);
}

void saveParam()
{
  EEPROM.put(keywordAddress, keyword);
  EEPROM.put(paramAddress, myParamters);
}

void getParam()
{
  uint32_t tmpKey;

EEPROM.get(keywordAddress, tmpKey);
  if (tmpKey == keyword) {
    EEPROM.get(paramAddress, myParamters);    // EEPROM was already initialized OK to read
  } else {
    // First run on this arduino, memory was never initialized. so establish default values
    myParamters.minimumT = -22;
    myParamters.maximumT = 44;
    saveParam();
  }
}

void setup() {
  Serial.begin(115200);

getParam();  // first run will establish the defaults in EEPROM
  printParam(); // see what the values are

myParamters.minimumT = -55;  // change one of the parameters
  saveParam(); // save it
  printParam(); // show it has been saved
}

void loop() {}




all the values I want to save are in the `myParamters` structure. in the setup() you call the `getParam()` function which will either read what is already there in EEPROM if the memory was already initialized or will write there default values and initialize the structure

every time you change the structure (one of your parameter) you just call `saveParam()` to update the EEPROM. 

--> run the program with your serial console opened at 115200 bauds. first time you run the program you'll see that default values are written, then the `minimumT` param is updated to -55° and if you run the code a second time (close and re-open the serial console for example) you'll see that the second time the `minimumT` param will already be at -55° instead of -22°

that serial.print(f( wow went from 92 percent dynamic memory to 56% double winner thanks

you can see the EEPROM as a line of boxes - each box can hold 1 byte. The put() function will look at how many bytes are needed for your parameter (for example 4 bytes for your float on a UNO) and if you ask to save your float starting at box #0 then it will fill Boxes #0 #1 #2 and #3.

The following diagram is a visual representation of the above text description.

Figure-1: Conceptual view of the internal structure of EEPROM of ATmega328P MCU

Example-1: Let us save 21 decimal (0x15 in hex) into Box-1 with address 1 indecimal (0x0001 in hex).

EEPROM.write(1, 21);
==> EEPROM.write(0x0001, 0x15);

==> #define   adr    1
==> #define   data   21
==> EEPROM.write(adr, data);

Example-2 Let us save 13.75 (decimal number with fractional point) into EEPROM.
In Example-1, we had 1-byte data; so, we required only 1-box to store the data. Now, we have less than 2-byte data; how many boxes we need to store this fractional value? More than 1-box but not 2-box. Then, how many boxes?

It is obvious that the boxed are single entity of their own; they can not be divided. The IEEE-754 Committee has decided that every floating point number (decimal number with fractional part) will be transformed into 32-bit (4-byte) 'Bit Pattern' known as binary32 formatted data, and this transformation takes place based on a definite rule/template (Fig-2).

Figure-2: binray32 format for representing a floating point number.

When we declare like flaot x = 13.75;, the compiler automatically applies the template of Fig-2 and produces a 32-bit bit pattern (0x415C0000) and saves in a buffer (temporary storage area). Now, we know that there will be a need of 4 memory locations of the EEPROM to store the number 13.75.

float x = 13.75;  //415C0000 is automatically created by compiler
EEPROM.put(0x03FB, x); //the 4-byte corresponding to 13.75 will be stored into locations: 03FB-03FE.

BTW: You may have curiosity how have I so quickly obtained the binary32 formatted value for 17.35. I have executed the following codes which have printed the hex value on the Serial Monitor.

void setup() 
{
  Serial.begin(9600);
  float x = 13.75;
  unsigned long *ptr;
  ptr = (unsigned long*) &x;
  unsigned long m = *ptr;
  Serial.println(m, HEX);   //show: 415C0000
}

void loop() 
{
  
}

UKHeliBob:
How do you know ?

Don't forget that the program runs when you upload it and on most Arduinos opening the serial monitor resets the board and it runs again, so by the time that you see the output the program has run twice.

YEP - the trick is to have the serial monitor already opened when you upload (and if you want to test initial conditions, change the keyword to something else so that the code does not assume the memory is already initialized from other previous trials with the same keyword)