EEPROM Writing with Functions

I am new to C++ and Arduino coding and I am struggling to figure out why one version of my code works but the other doesn't

I am trying to do simple test of writing a defined array of custom structure to EEPROM then reading it back again. (This is part of game I am writing but I have split this out to debug)

In this code version of the code I apply the EEPROM.put and EEPROM.get all in the setup function and it works as expected.

#include <EEPROM.h>

#define DEBUG 1;

struct highscore {
  byte attempts;
  char name[4];
};

struct highscore highScores[5];

struct highscore dftHighScores[5] = {
  {10, "AAA"},
  {20, "BBB"},
  {30, "CCC"},
  {40, "DDD"},
  {50, "EEE"}
};

int initFlag = 0;
int eeAddressFlag = 0;

void setup() {

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

  EEPROM.get(eeAddressFlag, initFlag);
  
  #ifdef DEBUG
    Serial.print(" flag = ");
    Serial.println(initFlag);
  #endif
  
  if (initFlag != 5) {
    
    EEPROM.put(eeAddressFlag, 5);
    
    // Setup Default High Scores
    Serial.println("Setup Default HighScores");
    EEPROM.put(10, dftHighScores);
    
  }

  //Load High Scoores
  EEPROM.get(10, highScores);

  #ifdef DEBUG
    for(int i=0; i<5; i++) {
      HighScoreLog(highScores[i]);
      Serial.println("======================");
    }
  #endif
}

void HighScoreLog(struct highscore temp)
{
  Serial.println();
  Serial.print(" Name = ");
  Serial.println(temp.name);
  Serial.print(" Attempts = ");
  Serial.println(temp.attempts);
}

// }

void loop() {

  /* Empty loop */
}

But if I change the code so that the EEPROM.put is in its own function then my read seems to get bad data and I cannot figure out why

#include <EEPROM.h>

#define DEBUG 1;

struct highscore {
  byte attempts;
  char name[4];
};

struct highscore highScores[5];

struct highscore dftHighScores[5] = {
  {10, "AAA"},
  {20, "BBB"},
  {30, "CCC"},
  {40, "DDD"},
  {50, "EEE"}
};

int initFlag = 0;
int eeAddressFlag = 0;

void setup() {

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

  EEPROM.get(eeAddressFlag, initFlag);
  
  #ifdef DEBUG
    Serial.print(" flag = ");
    Serial.println(initFlag);
  #endif
  
  if (initFlag != 5) {
    
    EEPROM.put(eeAddressFlag, 5);
    
    // Setup Default High Scores
    Serial.println("Setup Default HighScores");
    writeHighScore(dftHighScores);
    
  }

  //Load High Scoores
  EEPROM.get(10, highScores);

  #ifdef DEBUG
    for(int i=0; i<5; i++) {
      HighScoreLog(highScores[i]);
      Serial.println("======================");
    }
  #endif
}

void writeHighScore(highscore writeScore[5])
{
  #ifdef DEBUG
      for(int i=0; i<5; i++) {
        HighScoreLog(writeScore[i]);
        Serial.println("+++++++++++++++++++++++");
      }
  #endif
  
  EEPROM.put(10, writeScore);
  delay(250);
}

void HighScoreLog(struct highscore temp)
{
  Serial.println();
  Serial.print(" Name = ");
  Serial.println(temp.name);
  Serial.print(" Attempts = ");
  Serial.println(temp.attempts);
}

void loop() {

  /* Empty loop */
}

Output is now as follows:
flag = -1

Setup Default HighScores

Name = AAA

Attempts = 10

+++++++++++++++++++++++

Name = BBB

Attempts = 20

+++++++++++++++++++++++

Name = CCC

Attempts = 30

+++++++++++++++++++++++

Name = DDD

Attempts = 40

+++++++++++++++++++++++

Name = EEE

Attempts = 50

+++++++++++++++++++++++

Name = ÿÿÿ

Attempts = 0

======================

Name = ÿÿÿÿ

Attempts = 255

======================

Name = ÿÿÿÿ

Attempts = 255

======================

Name = ÿÿÿÿ

Attempts = 255

======================

Name = ÿÿÿÿ

Attempts = 255

======================

Any help would be appreciated I am sure it is something simple I am missing.

did you tried it with real board?

no I have been using

to simulate everything but so far behavior has been the same on both sides

Just tested the same code on a actual board and I got the same behavior

09:33:13.480 -> flag = 5

09:33:13.480 -> Setup Default HighScores

09:33:13.516 ->

09:33:13.516 -> Name = AAA

09:33:13.516 -> Attempts = 10

09:33:13.516 -> +++++++++++++++++++++++

09:33:13.516 ->

09:33:13.516 -> Name = BBB

09:33:13.550 -> Attempts = 20

09:33:13.550 -> +++++++++++++++++++++++

09:33:13.583 ->

09:33:13.583 -> Name = CCC

09:33:13.616 -> Attempts = 30

09:33:13.616 -> +++++++++++++++++++++++

09:33:13.683 ->

09:33:13.683 -> Name = DDD

09:33:13.683 -> Attempts = 40

09:33:13.683 -> +++++++++++++++++++++++

09:33:13.716 ->

09:33:13.716 -> Name = EEE

09:33:13.716 -> Attempts = 50

09:33:13.748 -> +++++++++++++++++++++++

09:33:13.962 ->

09:33:13.962 -> Name = 

09:33:13.962 -> Attempts = 0

09:33:13.962 -> ======================

09:33:13.995 ->

09:33:13.995 -> Name = ����

09:33:14.029 -> Attempts = 1

09:33:14.029 -> ======================

09:33:14.062 ->

09:33:14.062 -> Name = ����

09:33:14.062 -> Attempts = 255

09:33:14.095 -> ======================

09:33:14.128 ->

09:33:14.128 -> Name = ����

09:33:14.128 -> Attempts = 255

09:33:14.162 -> ======================

09:33:14.162 ->

09:33:14.195 -> Name = ����

09:33:14.195 -> Attempts = 255

09:33:14.195 -> =====================

no, it works. try so:

#include <EEPROM.h>

struct highscore {
  byte attempts;
  char name[4];
};

highscore HS[5];
highscore dftHighScores[5] = {
  {10, "AAA"},
  {20, "BBB"},
  {30, "CCC"},
  {40, "DDD"},
  {50, "EEE"}
};

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

void writeHighScore()
{
  EEPROM.put(10, dftHighScores);
  EEPROM.get(10, HS);
  Serial.println();
  for (int i = 0; i < 5; i++) {
    Serial.print(" Name = ");
    Serial.println(HS[i].name);
    Serial.print(" Attempts = ");
    Serial.println(HS[i].attempts);
    Serial.println("+++++++++++++++++++++++");
  }
}

void loop() {}

Both programs work as expected for me, on an Arduino Uno.

Same for me.

What exactly are you doing?
What I did was built / uploaded the working version from post #1 and got the correct output.
Then I built / uploaded the not working version from post #1 and got the same correct output.
We must be doing something different. I'm using an Uno R3.

I understand that the simulator might be off.

So I am using Arduino IDE to connect to two different boards to run my test one is this one

( Maker UNO)

the other is this one

( ELEGOO UNO R3 Board ATmega328P with USB Cable(Arduino-Compatible) for Arduino)

both run my code the same as the simulator, and the later one is a UNO R3 board (although generic version)

When I run the modified code by kolaha it all works on all environments. It seems in my case as soon as I use the write method like this

void writeHighScore(highscore writeScore[5])
{
  EEPROM.put(10, writeScore);
  
}

it breaks but using it like this

void writeHighScore()
{
 EEPROM.put(10, dftHighScores);
 
}

seems to work but I really want to be able to pass in the write to the function as it will be used to update highscores not just set the defaults.

void writeHighScore(highscore writeScore[5])
{
  EEPROM.put(10, writeScore);
  Serial.print(sizeof(writeScore)); // =2
  Serial.print(sizeof(dftHighScores)); // =25
}

I see that on my end too but why is the big question I have

(not real code just example)

writeHighScore(dftHighScores);


void writeHighScore(highscore writeScore[5])
{
  EEPROM.put(10, writeScore);
  Serial.println(sizeof(writeScore)); // =2
  Serial.println(sizeof(dftHighScores)); // =25
  
}

Since I am passing dftHighScores to writeHighScore and assigning it to writeScore why are they not the exact same size?

if I do this

void writeHighScore(highscore writeScore[5])
{
  for (int i = 0; i < 5; i++) {
    Serial.print(" Name = ");
    Serial.println(writeScore[i].name);
    Serial.print(" Attempts = ");
    Serial.println(writeScore[i].attempts);
    Serial.println("+++++++++++++++++++++++");
  }
  
  EEPROM.put(10, writeScore);
  Serial.println(sizeof(writeScore)); // =2
  Serial.println(sizeof(dftHighScores)); // =25
  
}

I can see that writeScores has all the data that expect -- I am just confused as to why the sizeof would be different.

I feel like the answer to that is my problem.

Sorry if this is me being naive but I am new to this.

AFAIK the total size of a function argument has to be communicated separately, usually using one or more separate function argument(s). If you pass an pointer or array of N elements, pass N as well.

I think you are seeing the size of the pointer to the data and not the size of the data block itself.

Is it possible that this function then is just writing the point to the eeprom

void writeHighScore(highscore writeScore[5])
{
  for (int i = 0; i < 5; i++) {
    Serial.print(" Name = ");
    Serial.println(writeScore[i].name);
    Serial.print(" Attempts = ");
    Serial.println(writeScore[i].attempts);
    Serial.println("+++++++++++++++++++++++");
  }
  
  EEPROM.put(10, writeScore);
  Serial.println(sizeof(writeScore)); // =2
  Serial.println(sizeof(dftHighScores)); // =25
  
}

not the actual data and that is why I am getting the different behavior. If that is the case how would I resolve it .

would you be able to give me a code sample of how I should do this correctly then?

Why don't pass arrays as references or pointers?

void writeHighScore(highscore *writeScore) {//same as 'writeScore[]'
  Serial.println("+++++++++++++++++++++++");

  highscore HS[5];
  for (byte i = 0; i < 5; i++) {
    HS[i] = writeScore[i];
    HighScoreLog(HS[i]);
  }
 
  EEPROM.put(10, HS);
  Serial.println("+++++++++++++++++++++++");
}

OR

void writeHighScore(highscore writeScore[]) {
  Serial.println("+++++++++++++++++++++++");

  for (byte i = 0; i < 5; i++) {
    EEPROM.put(10 + i * sizeof(highscore), writeScore[i]);
    HighScoreLog(writeScore[i]);
  }

  Serial.println("+++++++++++++++++++++++");
}

One of many tutorials on the topic. There are several other approaches to communicating sizes.

how should EEPROM.put() look to use whole passed array?

void writeHighScore(highscore writeScore[5]){
  EEPROM.put(10, writeScore);
}

not work, it is clear.


void writeHighScore(highscore writeScore[5]){
  EEPROM.put(10, *writeScore);
}

work, but written is only first structure from 5


Thank you everyone I learn allot here and found my solution to work. Bonus is I understand what I did wrong and why the previous didn't work.

I am not sure why other were able to get the original code to work on there system but I couldn't that still has be baffled less concerning of all of it

Thanks @kolaha for the great code samples
and @jremington great link with some good information that helps me learn more.

Thanks again and I sure I will be back!