EEPROM put(), get() and read(), write()

Hello,
I can't seem to figure out how i get a boolean in a EEPROM memory location and reading it out. After erasing the EEPROM with the clear() example in the IDE this memory location still reads out a 1 or true. The 'clear()' example does it work on a array of int's (after clearing they read 0) but for some reason it doesn't work with a single boolean that just takes up one byte.
To my knowlege the EEPROM read() and write() function are limited to single bytes and don't accept any other type of variables.
The way i wrote this test sketch is to register a first startup of the program/sketch so that in case of a power faillure my device knows at startup it is not the first startup and should retrieve data (setting) from before the power failure.
Don't mind the second part that is a readout of a array of ints.

#include <EEPROM.h>

bool firststartupFlag;
int menuVariables[5];
int i;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  //fist checking if it is a first startup BUT BEFORE LOADING THE EEPROM MUST BE CLEARED WITH A OTHER SKETCH
  int eeAddress = 100; //EEPROM address to start reading from
  Serial.println("Read startup boolean:");
  EEPROM.get(eeAddress, firststartupFlag);
  Serial.println((String)firststartupFlag);

  Serial.println("now checking startupflag. if it was 0 ore false it will be changed in 1 or true");
  if (firststartupFlag == false){  //THIS MEANS IF THE FLAG IS ZERO AFTER THE EEPROM WAS CLEARED
  EEPROM.write(eeAddress, !firststartupFlag); //setting firststartupflag to 1 aka true
  Serial.println("firststartupFlag has changed from 0 to 1 (false to true");
  };

  Serial.println("Read startup boolean again:");
  EEPROM.get(eeAddress, firststartupFlag);
  Serial.println((String)firststartupFlag);//WITH CLEARING EEPROM THIS SHOULD BE 1
  
//this readout works fine
  eeAddress = 0; //EEPROM address to start reading from
  Serial.println("Read array of int's from EEPROM: ");
  EEPROM.get(eeAddress, menuVariables);
  for (i=0; i<5; i++) {
  Serial.println((String)menuVariables[i]);
  }
  Serial.println("Done!");
}
  
void loop() {
  /* Empty loop */

..i have tried it with read() and write() but it's more trouble because i need to make conversions (right?...or can i use bytes and booleans one on one?)

thx!

PS: can i change a setting in the IDE that; everytime i upload a sketch to my Arduino uno R3; the EEPROM gets erased to?

The output of your program (after adding a closing '}') running on Wokwi is:

Read startup boolean:
255
now checking startupflag. if it was 0 ore false it will be changed in 1 or true
Read startup boolean again:
255
Read array of int's from EEPROM: 
-1
-1
-1
-1
-1
Done!

EEPROM.get(address,variable) copies the data bytewise verbatim into the variable, and doesn't do any casting.

Cleared EEPROM is filled with 0xFF, so EEPROM.get(eeAddress, firststartupFlag); is copying the 0xFF directly into the storage for firststartupFlag, which does not == false, so it skips the test and moves along, and prints "255"

If you use a firststartupFlag = EEPROM.read(eeAddress); it will cast the result to a bool.

Take a look at the output of:

#include <EEPROM.h>

bool firststartupFlag;
int menuVariables[5];
int i;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  //fist checking if it is a first startup BUT BEFORE LOADING THE EEPROM MUST BE CLEARED WITH A OTHER SKETCH
  int eeAddress = 100; //EEPROM address to start reading from
  Serial.println("Read startup boolean:");
  //EEPROM.get(eeAddress, firststartupFlag);
  firststartupFlag = EEPROM.read(eeAddress);
  Serial.println(firststartupFlag);
  Serial.println(firststartupFlag ? "true" : "false");
  Serial.println(String(firststartupFlag));
  Serial.println((int)firststartupFlag);
  Serial.println(sizeof(firststartupFlag));

  Serial.println("now checking startupflag. if it was 0 ore false it will be changed in 1 or true");
  if (firststartupFlag != true) { //THIS MEANS IF THE FLAG IS ZERO AFTER THE EEPROM WAS CLEARED
    EEPROM.write(eeAddress, !firststartupFlag); //setting firststartupflag to 1 aka true
    Serial.println("firststartupFlag has changed from 0 to 1 (false to true");
  };

  Serial.println("Read startup boolean again:");
  EEPROM.get(eeAddress, firststartupFlag);
  Serial.println(firststartupFlag ? "true" : "false"); //WITH CLEARING EEPROM THIS SHOULD BE 1

  //this readout works fine
  eeAddress = 0; //EEPROM address to start reading from
  Serial.println("Read array of int's from EEPROM: ");
  EEPROM.get(eeAddress, menuVariables);
  for (i = 0; i < 5; i++) {
    Serial.println(menuVariables[i]);
  }
  Serial.println("Done!");
}

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

Since you're reading a whole byte from EEPROM, maybe checking it whether the byte is 0xff is a stronger test for clearedness than testing if it is 0.

1 Like

The IDE example of EEPROM.clear() sets all the addresses to 0:

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  // initialize the LED pin as an output.
  pinMode(13, OUTPUT);
  
  /***
    Iterate through each byte of the EEPROM storage.

    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduino Duemilanove: 512 B EEPROM storage.
    - Arduino Uno:         1 kB EEPROM storage.
    - Arduino Mega:        4 kB EEPROM storage.

    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/

  for (int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }

  // turn the LED on when we're done
  //digitalWrite(13, HIGH);
  Serial.println("EEPROM erase Done!");
}

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

...as proof, the readout of the array of int's after clearing the EEPROM returns with all the int's being zero.

And i'm getting annoyed by the IDE. I'm trying to copy the output of the serial monitor but that is apparently not possible (why in the name of G..).
Your sketch with the adjustments is still giving me a 1 or true after clearing the EEPROM.

This is the output

I'm not certain of the root cause but if you add a small delay to the start of the reading program it gets the correct 0 value from the clearing sketch.

void setup() {
  delay(1000);
  Serial.begin(9600);
13:58:22.422 -> EEPROM erase Done!

//Load new reading program

13:58:58.496 -> Read startup boolean:
13:58:58.496 -> 0
13:58:58.496 -> false
13:58:58.545 -> 0
13:58:58.545 -> 0
13:58:58.545 -> 1
13:58:58.545 -> now checking startupflag. if it was 0 ore false it will be changed in 1 or true
13:58:58.593 -> firststartupFlag has changed from 0 to 1 (false to true
13:58:58.641 -> Read startup boolean again:
13:58:58.690 -> true
13:58:58.690 -> Read array of int's from EEPROM: 
13:58:58.738 -> 0
13:58:58.738 -> 0
13:58:58.738 -> 0
13:58:58.738 -> 0
13:58:58.738 -> 0
13:58:58.738 -> Done!

EDIT:

I think the eeprom in the AT328 has a startup/initialization process.
If you add this line to the code, it can replace the delay.

void setup() {
//delay(1000);
 while (!eeprom_is_ready()); // Wait for EEPROM to be ready 
 Serial.begin(9600);

I'm gonna test it asap. I read that somebody had a similar problem but it got solved by adding a delay. The problem was the a serial monitor problem in combo with the usb connection not fully ready so i skipped it because is have:

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

The delay trick did it.
But this one:
while (!eeprom_is_ready()); // Wait for EEPROM to be ready
Is suppose this is not a existing function in the EEPROM lib?
I'v been testing the needed delay time and even 800ms doesn't cut it.

and now the next issue.
When i'm using my original posted sketch that uses get(), it reads 1 after clearing the EEPROM.


This blows my mind in a negative way (yes i have added the 1sec delay) and what's more dazling is the fact that i can't find anything about this problem anywhere. It seems that nobody is using the EEPROM of the Uno R3.
But in the meanwhile thanks y'all for the help and posts!

I'm reading from my phone so can't really check in details but you are messing up with boolean types and bytes.

get() is type dependant. read() and write() are just dealing with bytes

To be 100% sure of what's going on use real boolean operation when dealing with a bool

bool firststartupFlag;
...
  firststartupFlag = EEPROM.read(eeAddress);

should be

bool firststartupFlag;
...
  firststartupFlag = EEPROM.read(eeAddress) != 0;

and instead of relying on bool to int promotion,

    EEPROM.write(eeAddress, !firststartupFlag); //setting firststartupflag to 1 aka true

use a byte

    EEPROM.write(eeAddress, firststartupFlag ? (byte) 0, (byte) 1); 

➜ ensure type's compliance throughout.

try

#include <EEPROM.h>

void setup() {
  Serial.begin(9600);
  int eeAddress = 100; //EEPROM address to start reading from
  byte eepromRead;
  Serial.println("Read @100 with get():");
  EEPROM.get(eeAddress, eepromRead);
  Serial.println(eepromRead);

  Serial.println("now checking ");
  if (eepromRead == 0) {
    EEPROM.write(eeAddress, (byte) 1); //setting firststartupflag to 1 aka true
    Serial.println("@100 has changed from 0 to 1");
  } else {
    Serial.println("@100 was not 0");
  }

  Serial.println("Read @100 with read():");
  EEPROM.get(eeAddress, eepromRead);
  Serial.println(eepromRead);
}

void loop() {}
1 Like

see Is it necessary to always check EEPROM is ready before reading/writing? - #2 by system

eeprom_is_ready()
There is no mentioning on the arduino website of this function in the embedded EEPROM library.
Could anyone tell me where is can find the code (.h) of the embedded Arduino IDE libaries? ...sometimes it can come in handy (like it already did in some other not-embedded lib's).Thx!


doen't seem to work (i've added the 1s delay and the 'while (!Serial)')

It depends on the details and version of you IDE installation. It might be somewhere like "...\hardware\arduino\avr\libraries\EEPROM\src".

The AVR version is at C:\Users<your username>\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\EEPROM\src

Versions for other processors will be in the corresponding folders if other boards have been installed

1 Like

Could anyone tell me where is can find the code (.h) of the embedded Arduino IDE libaries?

Underlying the Arduino EEPROM.h library is the avr/eeprom.h. It is used in EEPROM.h

#include <avr/eeprom.h>

eeprom_is_ready is a function in avr/eeprom.h.

https://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

1 Like

thx for the tip!...but i'm getting tired of trying.
To be clear: I thought i found the solution (by first using the EEPROM clearing example sketch and then my sketch with the EEPROM read()&write() functions) but that's not the case :enraged_face:
I've tried evoking a pattern and for starters i've added the delay and the 'while (!Serial)' in the sketch to clear the EEPROM (to be shure).
Been trying everything i can think off (like waiting long and short duration between clearing and reading, clearing multiple times with the reset button, ...etc) but i can't draw a patern when it failles and when it doesn't. So the last solution is to try the an other (AVR) EEPROM library (if i can find one).
When i tried the eeprom_is_ready() (after post #6) it was not recognized by the IDE as a function. I'll try it again tomorrow.

thx!

I am a bit confused as to your issue. I thought you said things were working correctly in post #8 with a delay of one second at the start of setup().

Is the issue something to do with .get() rather than .read(). Is it related to .clear() and then writing and reading in the same sketch?

Please post the code you are trying to use and the output.

Sure, if you write zeros the the EEPROM, it will have zeros in it.
But if you use a new chip or the Chip Erase Operation:

The chip erase operation turns the content of every
memory location in both the program and EEPROM arrays into 0xFF.

Locations that have never been written to have the value of 255.
-- https://docs.arduino.cc/learn/built-in-libraries/eeprom/

Unwritten EEPROM will have 0xFF in it:

EEPROM memory consists of independent cells each representing a single bit. The cells are based on floating-gate transistor technology: An electrical charge trapped on the transistor gate determines the logic level of the cell. Slightly simplified, the way that the cell works can be described as follows: When erasing a cell, a charge is placed on the gate and the cell is read as logic one. Programming a cell is equivalent to discharging the gate, bringing the logic value to zero. It is only possible to program (discharge) a cell that has been erased (charged). Note that even if EEPROM memory is accessed in bytes, bits can be programmed individually. Since only the bits being programmed are discharged (zero), the remaining unprogrammed bits are still charged (one). Any unprogrammed bit can be programmed at a later stage. Therefore, programming a byte that is already programmed, without erasing in between, will result in a bit-wise AND between the old value and the new value.

I think there's a bit of confusion.
I'm not using 'clear()' to whipe the EEPROM. I'm using the IDE example called clear to erase the EEPROM. In this example it's only writing (write()) 0 to every memory location in the EEPROM.

I need to simulate a startup for the first time so i can set a flag that is has been started up for the first time so if i start up the second time and prevent of loading some default data again.
My project needs to be user friendly and load some default setting at first startup. After a power failure (when the power comes up again) i must prevent loading these default settings because it needs to load the saved (adjusted) settings in the EEPROM from before the power failure.
This is what i use to whipe:

#include <EEPROM.h>

void setup() {
  delay(1000);
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  // initialize the LED pin as an output.
  //pinMode(13, OUTPUT);
  
  /***
    Iterate through each byte of the EEPROM storage.

    Larger AVR processors have larger EEPROM sizes, E.g:
    - Arduino Duemilanove: 512 B EEPROM storage.
    - Arduino Uno:         1 kB EEPROM storage.
    - Arduino Mega:        4 kB EEPROM storage.

    Rather than hard-coding the length, you should use the pre-provided length function.
    This will make your code portable to all AVR processors.
  ***/

  for (int i = 0 ; i < EEPROM.length() ; i++) {
    EEPROM.write(i, 0);
  }

  // turn the LED on when we're done
  //digitalWrite(13, HIGH);
  Serial.println();
  Serial.println("EEPROM erase Done!");
}

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

I'v tried it by just writing 0 to one address but of course that also doesn't work.