EEPROM read isn't working

I’m having problems using EEPROM read. Here’s the deal - I’m wanting to save 10 4-digit codes into EEPROM that are entered by a keypad. The keypad inputs apparently are received as ASCII characters (i.e., pressing a 0 on the keypad returns an ASCII 48.

I concatenate 4 keypad presses into a 4 digit string, and store this into the EEPROM using 4 bytes, 1 byte for each digit. So if I store into address 0, since the code is 4 digits using 4 bytes, the next code will be stored at an address 4 bytes away and so forth.

So I did a test case with code 9876 and stored it starting at EEPROM address 0, using address 0-3 for the 4 digits (bytes). I left the rest of the EEPROM untouched.

I’m having problems with my read routine which is copied below. I’m reading the first 40 bytes of the EEPROM (10 4-digit codes) stored in addresses 0-39. Here’s my code:

#include <EEPROM.h> //include EEPROM library

int intAsciiPin[10];          //integer representation of Ascii String PIN
int intPin[10];               //actual integer value of PIN array 
int i;
                
String asciiPin[10];          //ascii String PIN
String stringPin[10];         //string array of actual integer value of each digit of PIN
String PIN[10];               //final PIN of 4 string stringPin(index 0-3) concatanated together

void setup() {
    Serial.begin(9600);    //sets data baud rate for serial communication to 9600
                            //turns on serial output for debugging and printing to screen

    // Read bytes 0 to 39 of EEPROM
    for (int j=0; j<=9; j++) {
      Serial.print("j= ");
      Serial.println(j); 
      for (int k=0; k<=3; k++) {
        i = j*4+k;  
        Serial.print("i= ");
        Serial.println(i);
        asciiPin[i] = EEPROM.read(i);        //reads from EEPROM as ASCII string
        Serial.print("asciiPin[i]= ");
        Serial.println(asciiPin[i]);
        intAsciiPin[i] = asciiPin[i].toInt(); //converts ASCII string to integer value of ASCII
        Serial.print("intAsciiPin[i]= ");
        Serial.println(intAsciiPin[i]);
        intPin[i] = intAsciiPin[i] - 48;      //actual integer value, 0 = 48 in ASCII
        Serial.print("intPin[i]= ");
        Serial.println(intPin[i]);
        stringPin[i] = String(intPin[i]);     //convert integer to string
        Serial.print("stringPin[i]= ");
        Serial.println(stringPin[i]);
      }
    PIN[j] = stringPin[i-3] + stringPin[i-2] + stringPin[i-1] + stringPin[i]; //concatenate strings
    Serial.print("Address = ");
    Serial.println(j);
    Serial.print(" PIN = ");
    Serial.println(PIN[j]);
    } //end for

} //End Setup

void loop() {
  Serial.print("Here in the loop");
}

Below is my output. I’m really only interested in the variable PIN, the rest of the variables are printed out just for troubleshooting.

==================
j= 0
i= 0
asciiPin*= 57*
intAsciiPin*= 57*
intPin*= 9*
stringPin*= 9*
i= 1
asciiPin*= 56*
intAsciiPin*= 56*
intPin*= 8*
stringPin*= 8*
i= 2
asciiPin*= 55*
intAsciiPin*= 55*
intPin*= 7*
stringPin*= 7*
i= 3
asciiPin*= 54*
intAsciiPin*= 54*
intPin*= 6*
stringPin*= 6*
Address = 0
PIN = 9876
j= 1
i= 4
asciiPin*= 255*
intAsciiPin*= 255*
intPin*= 207*
stringPin*= 207*
i= 5
asciiPin*= 255*
intAsciiPin*= 255*
intPin*= 207*
stringPin*= 207*
i= 6
asciiPin*= 255*
intAsciiPin*= 255*
intPin*= 207*
stringPin*= 207*
i= 7
asciiPin*= 255*
intAsciiPin*= 255*
intPin*= 207*
stringPin*= 207*
Address = 1
PIN = 207207207207
j= 2
i= 8
asciiPin*= 255*
intAsciiPin*= 255*
intPin*= 207*
stringPin*= 207*
i= 9
asciiPin*= 255*
intAsciiPin*= 255*
intPin*= 207*
stringPin*= 207*
i= 10
asciiPin*= 255*
intAsciiPin*= 14136*
intPin*= 14088*
stringPin*= @⸮⸮⸮⸮*
i= 11
asciiPin*= 255*
intAsciiPin*= 271*
intPin*= 228*
================
(I’m not sure why everything remains in italics below, I couldn’t figure out how to remove the italics.)
j = the code number (0-9). I called it Address in my output which technically isn’t correct, it should be Code Number.
i = the EEPROM address
Notice that address 0-3 read correctly: PIN = 9876 which is what I’d previously stored.
Address 4-7 also read properly as they contained 255 as these addresses were untouched.
255-48=207 to convert from ASCII to decimal is fine. Yes I know up at 255 subtracting 48 doesn’t really give an ASCII to integer conversion but that’s fine, it works for integers 0-9 which is all I care about, so the fact that I get PIN = 207207207207 after concatenating 4 207 together is fine.
The 4 bytes from address 8-11 are where it gets weird. Look at address 10 (copied below):
i= 10
asciiPin*= 255*
intAsciiPin*= 14136*
intPin*= 14088*
stringPin*= @⸮⸮⸮⸮*
i= 11
asciiPin*= 255*
intAsciiPin*= 271*
intPin*= 228*
asciiPIN(10)=255 which is fine, but what’s going on when I convert to intAsciiPin?
Here’s my code for that line: intAsciiPin = asciiPin*.toInt();*
*Why does that suddenly give me 14088? *
And for address 11, asciiPin(11) again reads 255, which is fine, but again the function toINT() appears to mess up, because intAsciiPin(11) should be 207 but it gives 271 instead.
And then the code just stops, as in the output stops after printing intPin[11] and the arduino just stops responding.
What am I doing wrong? What’s my misunderstanding? I’m hoping someone can help!
Thanks,
Tom

You're writing on elements of your arrays outside their bounds. i.e. intAsciiPin has ten elements. You're writing to elements eleven and twelve just before your program crashes.

@wildbill Thanks! I feel foolish it was something so simple but I suppose that's why I don't code for a living! I sized the arrays to 10 for a previous iteration of the code and totally forgot about them when I extended the size, and kept overlooking that simple fact while debugging!

Don't use the literal number '10' everywhere. Define a constant at the start of the program and use that to size array, loop indexes, etc. That way, if you want to change it to '12' it is done in one place only and everything else adjusts.

@marco_c, thanks for the great suggestion! I'll start doing that with all my code, makes perfect sense!

You may study this system and the associated codes; some of the information could be helpful to solve your problem. In this system, the control program reads ASCII Codes of consecutive 4-digit entered from a keypad, stores the value in a character array and EEPROM along with null-byte. One may enter as many code blocks as he wishes, the limit is set in the program via the variable total. At the end of code entry, the codes are read from the EEPROM and are displayed on th bottom line of the LCD.

#include<EEPROM.h>
#include<Keypad.h>
#include<LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

const byte rows = 4, cols = 4;
char storage[5];
int adr = 0x0010;
int arrayTracker = 0, check = 0;
int counter = 0;
int total = 0;

char keys[rows][cols] = {
 
 {'1','2','3','a'},
 {'4','5','6','b'},
 {'7','8','9','c'},
 {'*','0','#','d'}
};

byte rPins[rows] = {9,8,7,6}, cPins[cols] = {5,4,3,2};

Keypad keypad = Keypad(makeKeymap(keys),rPins,cPins,rows,cols);

void setup()
{
 lcd.init();
 lcd.backlight();
 lcd.print("Enter Code:");
 lcd.setCursor(0,1);
}

void loop()
{
  lcd.setCursor(0, 0);
  lcd.print("Enter Code:");
  char input = keypad.getKey();
  if(input)
  {
    storage[arrayTracker] = input;
    lcd.setCursor(arrayTracker, 1);
    lcd.print(storage[arrayTracker]);
    arrayTracker++;   
    counter = arrayTracker; 
   }
   
   if(counter == 4)
   {
      storage[arrayTracker] = 0x00;//null-byte
      delay(2000);
      lcd.clear();
      EEPROM.put(adr, storage);
      adr = adr + 5;
      arrayTracker = 0x00;
      counter = 0x00;
      check = 0x00;
      total++;
      if (total == 4)
      {
        adr = 0x0010;
        lcd.setCursor(0, 0);
        lcd.print("EEPROM Reading!");
        lcd.setCursor(0, 1);
        for (int i = 0; i<4; i++)
        {
          EEPROM.get(adr, storage);
          lcd.print(storage);
          adr = adr +5;
        }
        while(1);
      }
    }
}