EEPROM structure best practice ?

Hi guys and girls, I have been using a structure to save my EEPROM data for a while now, but i have always wondered if i am doing it the correct way, both in terms of efficiency and general coding practice.

My concern is mainly saving arrays within a structure to the EEPROM, have i done it the correct way or can it be reduced in size as i feel it is quite convoluted?

ignore my little readEEPROM function, that just checks the EEPROM is intact.

#include <EEPROM.h>

byte EEPROM_key = 101; // change this key if you adjust the structure of the EEPROM ! i.e 102
// simple variables to store
bool test_1 = true;
char test_2 = 'T';
byte test_3 = 101;
int test_4 = 1234;
long test_5 = 1234567;
float test_6 = 21.43;
// arrays to store
bool test_array_1[5] = {true, false, true, false, true};
char test_array_2[5] = {'T', 'e', 's', 't', '1'};
byte test_array_3[5] = {101, 102, 103, 104, 105};
int test_array_4[5] = {1234, 1235, 1236, 1237, 1238};
long test_array_5[5] = {1234567, 1234568, 1234569, 1234570, 1234571};
float test_array_6[5] = {21.43, 21.44, 21.45, 21.46, 21.47};


struct EEPROMstructure {
  bool EEPROM_test_1;
  char EEPROM_test_2;
  byte EEPROM_test_3;
  int EEPROM_test_4;
  long EEPROM_test_5;
  float EEPROM_test_6;
  // arrays
  bool EEPROM_test_array_1[5];
  char EEPROM_test_array_2[5];
  byte EEPROM_test_array_3[5];
  int EEPROM_test_array_4[5];
  long EEPROM_test_array_5[5];
  float EEPROM_test_array_6[5];
};

void setup() {
  Serial.begin(115200);
  Serial.println("EEPROM structure example v1");
  readEEPROM();
  printvalues(); // show retrived EEPROM data
}

void loop() {

}

void readEEPROM(void) {
  if (EEPROM_key == EEPROM.read(0)) {
    retriveEEPROM();
  }
  else {
    Serial.println(F("EEPROM was blank or the structure changed, but is now corrected"));
    EEPROM.put(0, EEPROM_key);
    writeEEPROM();
  }
}

void writeEEPROM(void) {
  Serial.println(F("wrote variables to eeprom"));
  EEPROMstructure writeEEPROM = {
    test_1,
    test_2,
    test_3,
    test_4,
    test_5,
    test_6,
    test_array_1[0], // array 1
    test_array_1[1],
    test_array_1[2],
    test_array_1[3],
    test_array_1[4],
    test_array_2[0], // array 2
    test_array_2[1],
    test_array_2[2],
    test_array_2[3],
    test_array_2[4],
    test_array_3[0], // array 3
    test_array_3[1],
    test_array_3[2],
    test_array_3[3],
    test_array_3[4],
    test_array_4[0], // array 4
    test_array_4[1],
    test_array_4[2],
    test_array_4[3],
    test_array_4[4],
    test_array_5[0], // array 5
    test_array_5[1],
    test_array_5[2],
    test_array_5[3],
    test_array_5[4],
    test_array_6[0], // array 6
    test_array_6[1],
    test_array_6[2],
    test_array_6[3],
    test_array_6[4],
  };
  EEPROM.put(1, writeEEPROM);
  delay(250);
}

void retriveEEPROM(void) {
  Serial.println(F("retriving EEPROM variables"));
  EEPROMstructure retriveEEPROM;
  EEPROM.get(1, retriveEEPROM);
  delay(250);
  test_1 = retriveEEPROM.EEPROM_test_1;
  test_2 = retriveEEPROM.EEPROM_test_2;
  test_3 = retriveEEPROM.EEPROM_test_3;
  test_4 = retriveEEPROM.EEPROM_test_4;
  test_5 = retriveEEPROM.EEPROM_test_5;
  test_6 = retriveEEPROM.EEPROM_test_6;
  test_array_1[0] = retriveEEPROM.EEPROM_test_array_1[0]; // array 1
  test_array_1[1] = retriveEEPROM.EEPROM_test_array_1[1];
  test_array_1[2] = retriveEEPROM.EEPROM_test_array_1[2];
  test_array_1[3] = retriveEEPROM.EEPROM_test_array_1[3];
  test_array_1[4] = retriveEEPROM.EEPROM_test_array_1[4];
  test_array_2[0] = retriveEEPROM.EEPROM_test_array_2[0]; // array 2
  test_array_2[1] = retriveEEPROM.EEPROM_test_array_2[1];
  test_array_2[2] = retriveEEPROM.EEPROM_test_array_2[2];
  test_array_2[3] = retriveEEPROM.EEPROM_test_array_2[3];
  test_array_2[4] = retriveEEPROM.EEPROM_test_array_2[4];
  test_array_3[0] = retriveEEPROM.EEPROM_test_array_3[0]; // array 3
  test_array_3[1] = retriveEEPROM.EEPROM_test_array_3[1];
  test_array_3[2] = retriveEEPROM.EEPROM_test_array_3[2];
  test_array_3[3] = retriveEEPROM.EEPROM_test_array_3[3];
  test_array_3[4] = retriveEEPROM.EEPROM_test_array_3[4];
  test_array_4[0] = retriveEEPROM.EEPROM_test_array_4[0]; // array 4
  test_array_4[1] = retriveEEPROM.EEPROM_test_array_4[1];
  test_array_4[2] = retriveEEPROM.EEPROM_test_array_4[2];
  test_array_4[3] = retriveEEPROM.EEPROM_test_array_4[3];
  test_array_4[4] = retriveEEPROM.EEPROM_test_array_4[4];
  test_array_5[0] = retriveEEPROM.EEPROM_test_array_5[0]; // array 5
  test_array_5[1] = retriveEEPROM.EEPROM_test_array_5[1];
  test_array_5[2] = retriveEEPROM.EEPROM_test_array_5[2];
  test_array_5[3] = retriveEEPROM.EEPROM_test_array_5[3];
  test_array_5[4] = retriveEEPROM.EEPROM_test_array_5[4];
  test_array_6[0] = retriveEEPROM.EEPROM_test_array_6[0]; // array 6
  test_array_6[1] = retriveEEPROM.EEPROM_test_array_6[1];
  test_array_6[2] = retriveEEPROM.EEPROM_test_array_6[2];
  test_array_6[3] = retriveEEPROM.EEPROM_test_array_6[3];
  test_array_6[4] = retriveEEPROM.EEPROM_test_array_6[4];
}

void printvalues() {
  Serial.print(F("test_1 = ")); Serial.println(test_1);
  Serial.print(F("test_2 = ")); Serial.println(test_2);
  Serial.print(F("test_3 = ")); Serial.println(test_3);
  Serial.print(F("test_4 = ")); Serial.println(test_4);
  Serial.print(F("test_5 = ")); Serial.println(test_5);
  Serial.print(F("test_6 = ")); Serial.println(test_6);
  Serial.println("");
  for (byte i = 0; i < 5; i++) {
    Serial.print(F("test_array_1 [")); Serial.print(i); Serial.print(F("] = ")); 
    if (test_array_1[i]) {
      Serial.println(F("true"));
    }
    else {
      Serial.println(F("false"));
    }
    Serial.print(F("test_array_2 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_2[i]);
    Serial.print(F("test_array_3 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_3[i]);
    Serial.print(F("test_array_4 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_4[i]);
    Serial.print(F("test_array_5 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_5[i]);
    Serial.print(F("test_array_6 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_6[i]);
    Serial.println("");
  }
}

You could use memcpy to copy the arrays with one function call each.

Writing to EEPROM takes time. Anything that takes time can be interrupted. How well will your read code recover if writing is interrupted?

As you are using a full struct in memory for reading and writing, you can just attach this functionality
to the struct itself and use a global object for manipulation.
I would push the printing of the content also to the struct and initialize it with an initialization list.

If you need special manipulation functions you could add them easily.

#include <EEPROM.h>

const byte key = 101; // change this key if you adjust the structure of the EEPROM ! i.e 102

struct EEPROMstructure {
  bool test_1;
  char test_2;
  byte test_3;
  int test_4;
  long test_5;
  float test_6;
  bool test_array_1[5];
  char test_array_2[5];
  byte test_array_3[5];
  int test_array_4[5];
  long test_array_5[5];
  float test_array_6[5];
  void write() {
    EEPROM.put(1, *this);
    Serial.println(F("wrote variables to eeprom"));
  }
  void retrieve() {
    Serial.println(F("retrieving EEPROM variables"));
    EEPROM.get(1, *this);
  }
  void printValues();
} current = {
  true, 'T', 101, 1234, 1234567, 21.43,
  {true, false, true, false, true},
  {'T', 'e', 's', 't', '1'},
  {101, 102, 103, 104, 105},
  {1234, 1235, 1236, 1237, 1238},
  {1234567, 1234568, 1234569, 1234570, 1234571},
  {21.43, 21.44, 21.45, 21.46, 21.47},
};

void setup() {
  Serial.begin(250000);
  Serial.println("EEPROM structure example v1");
  if (key == EEPROM.read(0)) {
    current.retrieve();
  } else {
    Serial.println(F("EEPROM was blank or the structure changed, but is now corrected"));
    EEPROM.put(0, key);
    current.write();
  }
  current.printValues();
}

void loop() {}

void EEPROMstructure::printValues() {
  Serial.print(F("test_1 = ")); Serial.println(test_1);
  Serial.print(F("test_2 = ")); Serial.println(test_2);
  Serial.print(F("test_3 = ")); Serial.println(test_3);
  Serial.print(F("test_4 = ")); Serial.println(test_4);
  Serial.print(F("test_5 = ")); Serial.println(test_5);
  Serial.print(F("test_6 = ")); Serial.println(test_6);
  Serial.println("");
  for (byte i = 0; i < 5; i++) {
    Serial.print(F("test_array_1 [")); Serial.print(i); Serial.print(F("] = "));
    if (test_array_1[i]) {
      Serial.println(F("true"));
    }
    else {
      Serial.println(F("false"));
    }
    Serial.print(F("test_array_2 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_2[i]);
    Serial.print(F("test_array_3 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_3[i]);
    Serial.print(F("test_array_4 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_4[i]);
    Serial.print(F("test_array_5 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_5[i]);
    Serial.print(F("test_array_6 [")); Serial.print(i); Serial.print(F("] = ")); Serial.println(test_array_6[i]);
    Serial.println();
  }
}