I have written a simple sketch to play with eeprom on arduino. The sketch defines a character array string, then in the main loop it checks to see if the first value of that string exists in eeprom. If the value does not exist, it writes the new string to eeprom, otherwise it reads the existing string from eeprom.
The first thing I noticed while watching the serial monitor is that the line "No value saved in eeprom... Commencing save" is never printed which leads me to believe that the value is never written to eeprom, however the output from the serial monitor reads as follows:
Eeprom value exists... Dishing it out
~
Eeprom value exists... Dishing it out
~
Eeprom value exists... Dishing it out
~
Eeprom value exists... Dishing it out
~
Eeprom value exists... Dishing it out
~
Eeprom value exists... Dishing it out
~
I'm not sure why the confirmation line is never printed, or why only the first value of the string is printed. It's probably something simple that I have overlooked as I am relatively new to c/c++. Any advice is greatly appreciated:
#include <EEPROM.h>
char example_string[] = "~New eeprom string";
const int eeprom_size = 500; // values saved in eeprom should never exceed 500 bytes
char eeprom_buffer[eeprom_size];
char first_eeprom_value;
void setup() {
Serial.begin(9600); // serial communication initialize
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}
}
void loop() {
delay(3000);
first_eeprom_value = EEPROM.read(0);
if(first_eeprom_value != '~'){
Serial.println("No value saved in eeprom... Commencing save");
save_string_to_eeprom(example_string);
} else {
Serial.println("Eeprom value exists... Dishing it out");
read_string_from_eeprom(eeprom_buffer);
Serial.println(eeprom_buffer);
}
}
void save_string_to_eeprom(char* stringIn){
for(int i = 0; i < (strlen(stringIn) - 1); i++){
EEPROM.write(i, stringIn[i]);
}
}
void read_string_from_eeprom(char* theBuffer){
for(int i = 0; i < (strlen(theBuffer) - 1); i++){
theBuffer[i] = EEPROM.read(i);
}
}
An empty string would have a length of 1 for the null byte right? I replaced strlen(theBuffer) with eeprom_size like such:
void read_string_from_eeprom(char* theBuffer){
for(int i = 0; i < (eeprom_size - 1); i++){
theBuffer[i] = EEPROM.read(i);
}
}
However I still receive the same result? I am trying to (and this might be where I'm mistaken) work with variables example_string and eeprom_buffer by passing them to their respective functions. Am I way off here?
If I alter the code to modify the variables directly everything functions as expected, however I would like to understand what I did wrong when passing the variables to the functions:
#include <EEPROM.h>
char example_string[] = "~New eeprom string";
const int eeprom_size = 500; // values saved in eeprom should never exceed 500 bytes
char eeprom_buffer[eeprom_size];
char first_eeprom_value;
void setup() {
Serial.begin(9600); // serial communication initialize
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}
}
void loop() {
delay(3000);
first_eeprom_value = EEPROM.read(0);
if(first_eeprom_value != '~'){
Serial.println("No value saved in eeprom... Commencing save");
save_string_to_eeprom();
} else {
Serial.println("Eeprom value exists... Dishing it out");
read_string_from_eeprom();
Serial.println(eeprom_buffer);
}
}
void save_string_to_eeprom(){
for(int i = 0; i < (strlen(example_string) - 1); i++){
EEPROM.write(i, example_string[i]);
}
}
void read_string_from_eeprom(){
for(int i = 0; i < (eeprom_size - 1); i++){
eeprom_buffer[i] = EEPROM.read(i);
}
}
However I still receive the same result? I am trying to (and this might be where I'm mistaken) work with variables example_string and eeprom_buffer by passing them to their respective functions. Am I way off here?
When you write a NULL terminated string to EEPROM, the NULL is NOT written. It is a stop sign to tell the code to stop looping.
When you try to read from EEPROM, you have no way of knowing how much data to read. THAT is the first problem that you need to deal with.
for(int i = 0; i < (strlen(stringIn) - 1); i++){
You call the function with stringIn containing "~New eeprom string", which by my way of counting contains 18 characters. Then, you loop writing to EEPROM from 0 to 16 (stopping when i becomes 17). Since the last character (the 'g') is stored in position 17, I'm wondering why you want to store all but the last character of any arbitrary string.
An empty string would have a length of 1 for the null byte right?
Wrong.
If eeprom_buffer has never been used, because it is global, it is initialised to all zeroes.
Its first byte is therefore zero, so calling strlen on it will return zero.
AWOL:
If eeprom_buffer has never been used, because it is global, it is initialised to all zeroes.
Its first byte is therefore zero, so calling strlen on it will return zero.
Gotcha
PaulS:
When you try to read from EEPROM, you have no way of knowing how much data to read. THAT is the first problem that you need to deal with.
After some more googling I found the following post, which explains that whenever I pass eeprom_buffer, even though the size declaration is 500, all the function sees is the size of the pointer which is why my loop was only executing once. I have modified the function to use the const int eeprom_size, and now everything functions as expected.
The working code:
#include <EEPROM.h>
char example_string[] = "~New eeprom string";
const int eeprom_size = 500; // values saved in eeprom should never exceed 500 bytes
char eeprom_buffer[eeprom_size];
char first_eeprom_value;
void setup() {
// clear eeprom on new flash... just for debugging
for (int i = 0 ; i < EEPROM.length() ; i++) {
EEPROM.write(i, 0);
}
Serial.begin(9600); // serial communication initialize
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}
}
void loop() {
delay(3000);
first_eeprom_value = EEPROM.read(0);
if(first_eeprom_value != '~'){
Serial.println("No value saved in eeprom... Commencing save");
save_string_to_eeprom(example_string);
} else {
Serial.println("Eeprom value exists... Dishing it out");
read_string_from_eeprom(eeprom_buffer);
Serial.println(eeprom_buffer);
Serial.print("completed eeprom_buffer length: ");
Serial.print(strlen(eeprom_buffer));
Serial.println();
}
}
void save_string_to_eeprom(char *stringIn){
Serial.print("stringIn length: ");
Serial.print(strlen(stringIn));
Serial.println();
for(int i = 0; i < strlen(stringIn); i++){
EEPROM.write(i, stringIn[i]);
}
}
void read_string_from_eeprom(char *bufferIn){
Serial.print("bufferIn sizeof: ");
Serial.print(sizeof(bufferIn));
Serial.println();
for(int i = 0; i < eeprom_size; i++){
bufferIn[i] = EEPROM.read(i);
}
}