EEPROM put and get Array in Structs problems

When I use EEPROM put and get in my sketch, the values I get aren’t correct.
Here’s example code:

#include <EEPROM.h>

typedef  struct   progData {
  uint8_t      selectProg;
  uint16_t     WCount;
  uint8_t      feedRate;
  uint16_t     keepTime;
  uint8_t      deep;
  uint8_t      varArr [2][3];

} progData;

progData pData;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Read data from EEPROM: ");

  resetEeprom();

  loadEeprom();

  Serial.println(pData.varArr [0][0]);
  Serial.println(pData.varArr [0][1]);
  Serial.println(pData.varArr [0][2]);
  Serial.println(pData.varArr [0][3]);
  Serial.println();
  Serial.println(pData.varArr [1][0]);
  Serial.println(pData.varArr [1][1]);
  Serial.println(pData.varArr [1][2]);
  Serial.println(pData.varArr [1][3]);
  Serial.println();
  Serial.println(pData.varArr [2][0]);
  Serial.println(pData.varArr [2][1]);
  Serial.println(pData.varArr [2][2]);
  Serial.println(pData.varArr [2][3]);
  Serial.println();
  Serial.println(pData.feedRate);
  Serial.println(pData.keepTime);
  Serial.println(pData.deep);
  Serial.println();
  Serial.println("Done");

}

void loop() {
  // put your main code here, to run repeatedly:

}



void loadEeprom() {
  uint32_t uniqueID;
  EEPROM.get( 0, uniqueID );
  if ( uniqueID != 0x18fae9c8 )
    resetEeprom();
  else
    EEPROM.get( 4, pData );
}

void resetEeprom() {

  for (int i = 0; i < 512; i++)
    EEPROM.write(i, 0);

  pData.WCount            = 0;

  pData.selectProg          = 1;

  pData.varArr [0][0]     = 10;
  pData.varArr [0][1]     = 1;
  pData.varArr [0][2]     = 1;
  pData.varArr [0][3]     = 1;

  pData.varArr [1][0]     = 15;
  pData.varArr [1][1]     = 1;
  pData.varArr [1][2]     = 1;
  pData.varArr [1][3]     = 1;

  pData.varArr [2][0]     = 20;
  pData.varArr [2][1]     = 1;
  pData.varArr [2][2]     = 1;
  pData.varArr [2][3]     = 1;

  pData.feedRate            = 150;
  pData.keepTime            = 500;
  pData.deep                = 10;

  EEPROM.put( 4, pData );

  EEPROM.put( 0, 0x18fae9c8 );
}

And here’s what I see on the serial monitor:

Read data from EEPROM: 
10
1
1
15

15
1
1
73

73
1
1
1

150
500
10

Done

So what I’m getting out of the EEPROM doesn’t match what I’m putting in there. I have searched this, and other forums, but not found a solution using put/get commands for eeprom Array in Structs.
Thanks! Thanks!

The first index has values of 0 and 1. The second index has values of 0,1 and 2.

I have not tested your sketch, but let us know what happens when you either enlarge the arrays to hold the indexes you need or limit the indexes to the array size you have.

Weird. If you had generated indexes in a loop you would have gotten several warnings that you were using undefined behavior (indexing off the end of an array). But using compile-time constants for indexing, NOT A SINGLE WARNING!

For example, adding this in setup():

  for (int r = 0; r < 3; r++)
    for (int c = 0; c < 4; c++)
      pData.varArr[r][c] = 0;

causes these warnings:

sketch_aug28a.ino:28:26: warning: iteration 3 invokes undefined behavior [-Waggressive-loop-optimizations]
       pData.varArr[r][c] = 0;
       ~~~~~~~~~~~~~~~~~~~^~~
sketch_aug28a.ino:27:23: note: within this loop
     for (int c = 0; c < 4; c++)
                     ~~^~~

sketch_aug28a.ino:28:26: warning: iteration 2 invokes undefined behavior [-Waggressive-loop-optimizations]
       pData.varArr[r][c] = 0;
                          ^
sketch_aug28a.ino:26:21: note: within this loop
   for (int r = 0; r < 3; r++)
                     ^

@miaopro
Is that (shown below) what you wish to get?

Read data from EEPROM: 
10
1
1

15
1
1

150
500
10

Done

#define ArrayCount(array) (sizeof array / sizeof array[0])

  for (unsigned int r = 0; r < ArrayCount(pData.varArr); r++)
    for (unsigned int c = 0; c < ArrayCount(pData.varArr[0]); c++)
      pData.varArr[r][c] = 0;

Not warnings! But it is not related to my problem.

  pData.varArr [0][0]     = 10;
  pData.varArr [0][1]     = 1;
  pData.varArr [0][2]     = 1;
  pData.varArr [0][3]     = 1;

  pData.varArr [1][0]     = 15;
  pData.varArr [1][1]     = 1;
  pData.varArr [1][2]     = 1;
  pData.varArr [1][3]     = 1;

  pData.varArr [2][0]     = 20;
  pData.varArr [2][1]     = 1;
  pData.varArr [2][2]     = 1;
  pData.varArr [2][3]     = 1;

  pData.feedRate            = 150;
  pData.keepTime            = 500;
  pData.deep                = 10;

I get aren’t correct.

Read data from EEPROM: 
10
1
1
15  correct 1

15
1
1
73 correct 1

73 correct 20
1
1
1

150
500
10

Done

I think it has something to do with the delay() function when saving to EEPROM.

No. It has to do with the declaration of varArr [2][3];

It should be declared as varArr [3][4];

Arrary indexes are zero based. Two elements are 0 and1 and three elements are 0,1,2. If you want to store and retrieve elements from these elements noted below, you will need to declare a larger matrix. varArr[3][4]

pData.varArr [0][3]     = 1;
pData.varArr [1][3]     = 1;

and

pData.varArr [2][0]     = 20;
pData.varArr [2][1]     = 1;
pData.varArr [2][2]     = 1;
pData.varArr [2][3]     = 1;

That's very wonderful. Thanks a lot!

You were told this in reply #2 and #3, but it evidently did not register with you. :wink:

There are a few more things:

  • You name the typedef twice with the same name. In C++ the word "typedef" is no longer needed. I made the name of the typedef and the name of the data better to distinguish from each other.
  • When the unique ID should tell if the data is valid, then that ID should be part of the data.
  • Using the "0x18fae9c8" twice in your sketch could cause a bug. Suppose the other one is "0x18fea9c8", then it is almost not noticable that it is wrong. I made a #define for it.
  • The names of the functions are confusing.
  • If you use always the same order of the elements of the struct in your sketch, then it is easier to check if there is a bug.

That resulted into this:

#include <EEPROM.h>

#define UNIQUE_ID 0x18fae9c8

struct PROGDATA {
  uint32_t  uniqueID;
  uint8_t   selectProg;
  uint16_t  WCount;
  uint8_t   feedRate;
  uint16_t  keepTime;
  uint8_t   deep;
  uint8_t   varArr[3][4];   // 4 bytes, and that 3 times
};

PROGDATA progData;

void setup() {
  Serial.begin(9600);
  Serial.println("Read data from EEPROM: ");

  clearEeprom();
  initializeData();
  EEPROM.put( 0, progData );
  EEPROM.get( 0, progData );
  showData();
  Serial.println("Done");
}

void loop() {}

void initializeData() {
  progData.uniqueID      = UNIQUE_ID;
  progData.selectProg    = 1;
  progData.WCount        = 0;
  progData.feedRate      = 150;
  progData.keepTime      = 500;
  progData.deep          = 10;

  progData.varArr [0][0] = 10;
  progData.varArr [0][1] = 1;
  progData.varArr [0][2] = 1;
  progData.varArr [0][3] = 1;

  progData.varArr [1][0] = 15;
  progData.varArr [1][1] = 1;
  progData.varArr [1][2] = 1;
  progData.varArr [1][3] = 1;

  progData.varArr [2][0] = 20;
  progData.varArr [2][1] = 1;
  progData.varArr [2][2] = 1;
  progData.varArr [2][3] = 1;
}

void showData() {
  Serial.println(progData.uniqueID, HEX);
  Serial.println(progData.selectProg);
  Serial.println(progData.WCount);
  Serial.println(progData.feedRate);
  Serial.println(progData.keepTime);
  Serial.println(progData.deep);
  Serial.println();
  
  Serial.println(progData.varArr [0][0]);
  Serial.println(progData.varArr [0][1]);
  Serial.println(progData.varArr [0][2]);
  Serial.println(progData.varArr [0][3]);
  Serial.println();
  Serial.println(progData.varArr [1][0]);
  Serial.println(progData.varArr [1][1]);
  Serial.println(progData.varArr [1][2]);
  Serial.println(progData.varArr [1][3]);
  Serial.println();
  Serial.println(progData.varArr [2][0]);
  Serial.println(progData.varArr [2][1]);
  Serial.println(progData.varArr [2][2]);
  Serial.println(progData.varArr [2][3]);
  Serial.println();
}

void clearEeprom() {
  for (int i = 0; i < 512; i++)
    EEPROM.write(i, 0);
}
2 Likes