Issue when recording struct in EEPROM

Hi,

I have some difficulties when recording information in EEPROM struct.
This is the structure I have declared and other declarations that will be used in program.

struct My_EEPROM_Object                 
{
  char password1[5];            
  char password2[5];             
  boolean additional_authorization;     
  char currency[8];
};
char New_password[5];	// array to store new password
char New_verification_password[5]; // array to store new verification password
boolean new_autorization_status;
char new_currency[8]; // array to store currency

struct MyObject{char money_box_opening_password[5]; char authorization_password[5]; boolean confirmation_password;char saved_currency[8];}

This is a part of the code where I’m using keypad to change the passwords:

void Admin_Screen()
{ 
    lcd.clear();
    lcd.blink();
   lcd.setCursor(0,0);
    lcd.print("Enter new password");
    while(1)
  {
    char key = keypad.getKey();
  
    if (key>='0' && key<='9')
    {
      lcd.print(key);
      New_password[new_password_char_count]+=key; // use array to store entered symbols
      new_password_char_count++;
    }
    if (new_password_char_count == 4)
    break;
  }
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("Enter verification password");
           while (1)
          {
              char key = keypad.getKey();
              if (key>='0' && key<='9')
        {
          lcd.print(key);
          New_verification_password[new_verification_password_char_count]+=key;
          new_verification_password_char_count++;
        }
      
    if (new_verification_password_char_count == 4)  
         break;
        }
          lcd.noBlink();
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("Autorization required?");
          lcd.setCursor(0,2);
          lcd.print("A - YES);
          lcd.setCursor(0,3);
          lcd.print("B - NO");
    while(1)
    {
      char key = keypad.getKey();
      if (key == 'A')
          {
            new_autorization_status = true;
            break;
          }
          if (key == 'B')
          {
            new_autorization_status = false;
            break;
          }
    }
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("Currency");
          lcd.setCursor(0,2);
          lcd.print("A - Euro");
          lcd.setCursor(0,3);
          lcd.print("B - Pound");
      while(1)
      {
        char key = keypad.getKey();
        if (key == 'A')
          {
             strcpy(new_currency,"Euro"); 
            break;
          }
          if (key == 'B')
          {
            strcpy(new_currency,"Pound");
             break;
          }    
      }
      float f = money;
      int eeAddress = 0;
      EEPROM.put(eeAddress,f);

      My_EEPROM_Object Memory_Entries =
      {
           New_password[5],
           New_verification_password[5],
           new_autorization_status,
           new_currency[8],
      };
      eeAddress += sizeof(float);
      EEPROM.put(eeAddress,Memory_Entries);
      MyObject customVar;
      lcd.clear();
      lcd.setCursor(0,0);
      EEPROM.get(eeAddress, customVar);
      lcd.print(customVar.money_box_opening_password);
      lcd.setCursor(0,1);
      lcd.print(customVar. authorization_password);
      lcd.setCursor(0,2);
      lcd.print(customVar. confirmation_password);
      lcd.setCursor(0,3);
      lcd.print(customVar.saved_currency);

The problem I have is with two saved passwords(money_box_opening_password and authorization_password). When I’m trying to read saved values from EEPROM , I’m just getting weird symbols on LCD display (not the values that were entered i.e 1234).
Confirmation_password and Saved_currency contain correct values.
Where I’m making a mistake? I think that the issue is with the arrays and how they are saved in memory.

My_EEPROM_Object Memory_Entries =
      {
           New_password[5],
           New_verification_password[5],
           new_autorization_status,
           new_currency[8],
      };

Another thing is that when I recorded values into My_EEPROM_Object Memory_Entries as below, everything was recorded correctly. The correct values were read from EEPROM and displayed on LCD.
My_EEPROM_Object Memory_Entries =
{
"1234",
"7777",
1,
"Euro",
};

I would really appreciate any help in this case as I’m stuck with this problem and I don’t really know how to fix it.

Thank you in advance

Post your whole code if you don't mind.

And, did you wire the lcd correctly? What type of driver?

      New_password[new_password_char_count] += key; // use array to store entered symbols

Why do you want to add the value of the key to the array value? I would just store it.

Where is the trailing zero stored? (or the number of valid chars...)

The code is quite lenghtly that's why I only copied part of the part of the code I have issue with. Lcd is wired correctly(LiquidCrystal.h).
Whandall - answering your question - I can't store STRING in EEPROM structure - that's why why I'm using array to store 4 digit password + 1 position for trailing zero character (char password1[5]).

+= does not append a character to a char array, it adds a value to one element.

Again, why do you want to add the values instead of storing them?

Your code contains no storing of a trailing zero (except the strcpy case).
Ok, in case of the fixed length passwords you get away with the initialization zero.

+= does not append a character to a char array, it adds a value to one element.

Just to clarify - the loop below will run four times in order to gather four new password digits.
Let's say I have entered digits 1234 using keypad - so New_password array will be containing {'1','2','3','4'}.
I have checked that using Serial port monitor and the values stored in array are correct(no weird symbols).

while(1)
  {
    char key = keypad.getKey();
  
    if (key>='0' && key<='9')
    {
      lcd.print(key);
      New_password[new_password_char_count]+=key; // use array to store entered symbols
      new_password_char_count++;
    }
    if (new_password_char_count == 4)
    break;
  }

It looks that there is some issue when recording this New_password array into EEPROM struct as the symbols copied from one char array to another are not correct.

My_EEPROM_Object Memory_Entries =
      {
           New_password[5],
           New_verification_password[5],
           new_autorization_status,
           new_currency[8],
      };

If you have any other ideas how to store passwords in EEPROM struct please share.
I have been thinking that using arrays should be ok but unfortunately it does not seem to work for some reason.

You still do not answer or understand my question.

Look closely at the follow statement:

     New_password[new_password_char_count] += key;

Why dont you use (as most people would) something like the following:

     New_password[new_password_char_count] = key;

You are aware of the difference between += and = ?

Are you really shure that the old char stored there is zero?
Only in that case it would make no difference in outcome, only in performance and code (bigger & slower).

If not, why are you wondering that you get strange content in the array fields?
Why do you blame the EEPROM for storing the 'modified' content?

New_password[new_password_char_count] = key;

Sorry my bad :blush: I did not notice this. Fixed now but the issue with EEPROM still not solved and I'm still getting incorrect readings.

Make a small compilable sketch that shows the behaviour.

Post it with the generated unexpected output and explain what makes it unexpected.

For testing you could use serial as input, if any is needed.

      My_EEPROM_Object Memory_Entries =
      {
           New_password[5],
           New_verification_password[5],
           new_autorization_status,
           new_currency[8],
      };

This is another reason your stuff can not work.

You initialize that object with single characters, that are all behind the arrays used to pick the items.

So you take wrong data (a single character) from the wrong place (behind the arrays) three times.
If you switch warnings to 'all', you would probably see some for this statement.

I was thinking that if I have the structure declared like below

struct My_EEPROM_Object                 
{
  char password1[5];            
  char password2[5];             
  boolean additional_authorization;     
  char currency[8];
};

I will be able to copy New_password[5] into password1[5] directly.

You initialize that object with single characters, that are all behind the arrays used to pick the items.

What should I do to fix this as I really don't have any ideas.

Whandall - thank you for your time to help me with this problem

gazi_24:
What should I do to fix this as I really don't have any ideas.

      My_EEPROM_Object Memory_Entries =
      {
           New_password,
           New_verification_password,
           new_autorization_status,
           new_currency,
      };

I modified the code as per your suggestion but an error message appears during compilation.

"array must be initialized with a brace-enclosed initializer"

This is one way that would work

struct My_EEPROM_Object {
    char password1[5];
    char password2[5];
    boolean additional_authorization;
    char currency[8];
    void setAll(const char* pw1, const char* pw2, bool state, const char* curr) {
      saveCopy(password1, pw1, sizeof(password1));
      saveCopy(password2, pw2, sizeof(password2));
      additional_authorization = state;
      saveCopy(currency, curr, sizeof(currency));
    }
    My_EEPROM_Object(const char* pw1, const char* pw2, bool state, const char* curr) {
      setAll(pw1, pw2, state, curr);
    }
    My_EEPROM_Object() {
      *password1 = 0;
      *password2 = 0;
      additional_authorization = false;
      *currency = 0;
    }
    void dump() {
      printNamedString(F("PWD1"), password1);
      printNamedString(F("PWD2"), password2);
      Serial.print(F("Autho "));
      Serial.println(additional_authorization ? F("True") : F("False"));
      printNamedString(F("Curr"), currency);
    }
  private:
    void saveCopy(char* target, const char* source, byte fieldSize) {
      if (fieldSize--) {
        strncpy(target, source, fieldSize);
        target[fieldSize] = 0;
      }
    }
    void printNamedString(const __FlashStringHelper* lab, const char * what) {
      Serial.print(lab);
      Serial.print(F(" '"));
      Serial.print(what);
      Serial.println(F("'"));
    }
};
char New_password[5] = "AA01";
char New_verification_password[5] = "BB02";
boolean new_autorization_status = true;
char new_currency[8] = "Pound";

void setup() {
  Serial.begin(250000);
  My_EEPROM_Object values(New_password, New_verification_password, new_autorization_status, new_currency);
  values.dump();
//** variant with deferred setting
//  My_EEPROM_Object values;
//  values.dump();
//  values.setAll(New_password, New_verification_password, new_autorization_status, new_currency);
//  values.dump();
}

void loop() {}
PWD1 'AA01'
PWD2 'BB02'
Autho True
Curr 'Pound'

@ gazi_24

Your problem has appeared due to an ineffective way that you have followed to update the members of My_EEPROM_Object with the values entered from the Keypad. The working steps are:

strcpy(Memory_Entries.password1, New_password);
strcpy(Memory_Entries.password2, New_verification_password);
Memory_Entries.additional_authorization = new_authorization_status;          
strcpy(Memory_Entries.currency, new_currency);

And Not the Following:

My_EEPROM_Object Memory_Entries = {
  New_password[5],
  New_verification_password[5],
  new_authorization_status,
  new_currency[8],
};

The complete codes that have been tested under MEGA Platform.

#include <EEPROM.h>
#include <Keypad.h>
#include<LiquidCrystal.h>
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
float money = 123.75;

int new_verification_password_char_count;
int new_password_char_count;

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
//-----------------------------------------------------------------------------

struct My_EEPROM_Object
{
  char password1[5];
  char password2[5];
  boolean additional_authorization;
  char currency[8];
};

char New_password[5];  // array to store new password
char New_verification_password[5]; // array to store new verification password
boolean new_authorization_status;
char new_currency[8]; // array to store currency

struct MyObject
{
  char money_box_opening_password[5];
  char authorization_password[5];
  boolean confirmation_password;
  char saved_currency[8];
};
//------------------------------------------------------------
My_EEPROM_Object Memory_Entries;
/*=
{
  New_password[5],
  New_verification_password[5],
  new_authorization_status,
  new_currency[8],
};
/*
  My_EEPROM_Object Memory_Entries =
  {
  "1234",
  "7777",
  1,
  "Euro",
  };
  //-------------------------------------------------------
*/

//initialize an instance of class NewKeypad
Keypad keypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

void setup()
{
  Serial.begin(9600);
  lcd.begin(20, 4);
  lcd.setCursor(0, 0);
  lcd.print("AUST");

  Admin_Screen();
}

void loop()
{

}



void Admin_Screen()
{
  lcd.clear();
  lcd.blink();
  lcd.setCursor(0, 0);
  lcd.print("Enter new password");
  lcd.setCursor(0, 1);
  
  while (1)
  {
    char key = keypad.getKey();

    if (key >= '0' && key <= '9')
    {
      lcd.print(key);
      New_password[new_password_char_count] += key; // use array to store entered symbols
      new_password_char_count++;
    }
    if (new_password_char_count == 4)
      break;
  }
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Enter veri. password");
  
  while (1)
  {
    char key = keypad.getKey();
    if (key >= '0' && key <= '9')
    {
      lcd.print(key);
      New_verification_password[new_verification_password_char_count] += key;
      new_verification_password_char_count++;
    }

    if (new_verification_password_char_count == 4)
      break;
  }
  
  lcd.noBlink();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Authorization required?");
  lcd.setCursor(0, 2);
  lcd.print("A - YES");
  lcd.setCursor(0,3);
  lcd.print("B - NO");
  
  while(1)
  {
    char key = keypad.getKey();
    if (key == 'A')
    {
      new_authorization_status = true;
      break;
    }
    if (key == 'B')
    {
      new_authorization_status = false;
      break;
    }
  }
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Currency");
  lcd.setCursor(0,2);
  lcd.print("A - Euro");
  lcd.setCursor(0,3);
  lcd.print("B - Pound");
  
  while(1)
  {
    char key = keypad.getKey();
    if (key == 'A')
    {
      strcpy(new_currency,"Euro");
      break;
    }
    if (key == 'B')
    {
      strcpy(new_currency,"Pound");
      break;
    }
  }
            float f = money;
            int eeAddress = 0;
            EEPROM.put(eeAddress,f);  //123.75 ---->0x0000
          //  Serial.println(New_password);//1234
           // while(1);
            strcpy(Memory_Entries.password1, New_password);
            //Serial.print(Memory_Entries.password1);//1234
             strcpy(Memory_Entries.password2, New_verification_password);
          //  Serial.print(Memory_Entries.password2);//6789
             Memory_Entries.additional_authorization = new_authorization_status;           //Serial.print(Memory_Entries.password1);//1234
          //  Serial.print(Memory_Entries.additional_authorization);//1
             strcpy(Memory_Entries.currency, new_currency);
            //Serial.print(Memory_Entries.currency;//Euro
            
         //   while(1);
            eeAddress += sizeof(float);
            EEPROM.put(eeAddress,Memory_Entries);
            
            MyObject customVar;
            lcd.clear();
            lcd.setCursor(0,0);
            EEPROM.get(eeAddress, customVar);
            lcd.print(customVar.money_box_opening_password);//1234
            lcd.setCursor(0,1);
            lcd.print(customVar. authorization_password);//6789
            lcd.setCursor(0,2);
            lcd.print(customVar. confirmation_password);//true
            lcd.setCursor(0,3);
            lcd.print(customVar.saved_currency);//Euro

}

It works :smiley:

Whandall, GolamMostafa - you are the best. Thank you so much for your help.