Matrix keypad: Storing data on internal eeprom

Hi all,
How storing keypresses in the arduino internal eeprom memory. Data must be stored under a sequence of 4 digits time stamped (Hour:Mn:Sec).

Libraries used:
"keypad"
"DateTime"
"Eeprom" or "Database"
"Password" (eventualy)

How to combine or complete all of sketch and library to make it run?
As an exemple: If 1234 is pressed, it must be store time stamped on the internal eeprom just after pressing the validate button "C". The button "A" is used to cancel the actual sequence and start again, and the button "B" to correct the last digit entered.

Keypad matrix form:
{'1','2','3','A'}
{'4','5','6','B'}
{'7','8','9','C'}
{'#','0','*','D'}

Form of data extracted from eerpom:

Keys | Time

1234 | 14:32:45
6839 | 15:05:28
... | ...

Thanks...

Link to libraries used and sketch example:
"keypad": Arduino Playground - KeypadTutorial
"DateTime" : Arduino Playground - DateTime
"Eeprom": http://arduino.cc/en/Reference/EEPROM
or
"Database": Arduino Playground - DatabaseLibrary
"Password" (eventualy): Arduino Playground - Password Library

I haven't used the database library but that would seem the easiest way to store and retrieved your info in EEPROM

If only numeric key sequences need to be stored and the maximum number of digits is four then you can store the sequence as an integer value (this uses two bytes instead of the four required if you stored the keys pressed as characters)

struct MyRec {
time_t time;
int keys;
} myrec;

a function called atoi can convert a string of digits into an integer.

The DateTime library has been updated, the new library is called Time and can be found here: Arduino Playground - Time

First, thank you for you quick reply mem.
However, during this week, I tried to change the following code without any real success. I'm trying to save characters string in built in eeprom every time i press a key ("C" key for example)... At this moment i'm only abble to read key pressed on the serial monitor.

Example of what i'm looking for:

  1. 1234AB78 14:32:45
  2. 6567 15:05:28
  3. 8943D 15:47:02
  4. A205B7 16:12:56
    ...
    As you can see characters string are not necessarily the same size. Each string must be save on eeprom after each press on "C" key.
    I tried different function like "switch case" "event keys" "eeprom read and write" "database" "time" without succes...
#include <Keypad.h>
#include <EEPROM.h>
#include <Time.h>

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

// Make the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
byte ledPin = 13; 

boolean blink = false;

[color=#ff0000]//I think here comes eeprom address and value declaration
[/color]
void setup(){
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);           // sets the digital pin as output
  digitalWrite(ledPin, HIGH);         // sets the LED on
  keypad.addEventListener(keypadEvent);    //add an event listener for this keypad
}
  
void loop(){
  char key = keypad.getKey();
  
  if (key != NO_KEY) {
    Serial.println(key);
[color=#ff0000]// I think here comes the part of code to write in eeprom[/color]
  }
  if (blink){
    digitalWrite(ledPin,!digitalRead(ledPin));
    delay(100);
  }
}

//take care of some special events
void keypadEvent(KeypadEvent key){
  switch (keypad.getState()){
    case PRESSED:
      switch (key){
        case 'C': digitalWrite(ledPin,!digitalRead(ledPin)); break;
[color=#ff0000]// here part of code to save the sequence string on each pressed "C" keys[/color]
      }
    break;
}
[color=#ff0000]// Here part of code to read on serial monitor all sequences store in eeprom [/color]
}

[color=#ff0000]//Here the part of setting current time code with using "T...." taken from http://www.epochconverter.com/ [/color]

Please, give me somes guidances to put everything in order...

Your task is simplified if you don't need to store the letter keys because you can save the numeric values which will be smaller than the strings and they will have fixed length.

Do you lose any meaningful information if you don't store the 'letter' keys?

If only four digit sequences are valid, Do you lose any meaningful data if you don't store the full value of entries that consist of more digits? (You can store up to ten digits using 32 bit values – 4 bytes, but this halves the storage space available for perhaps no real benefit)

Storing data that you can't use can cost you storage space and program complexity.

I don't see the problem with the letter keys.
If you save each key as its position (ie: 11 for 1 = row 1 column 1, 14 = row 1 column 4, 44 = row 4 column 4), you can easily fit each key in a single byte.

the issue is not about how to encode the letters, its about simplifying the code and minimizing the number of characters stored.

The letters and digits can be stored as their ascii values but this involves holding more data and dealing with variable length.

If only 4 digit numeric values represent valid codes then these can be stored using two bytes per entry.

Yes you are right, it doesn't really need to store alphabetic characters (A,B,C,D) but only 4 digits sequence. However they are their importance because the 'A' key is used to cancel the current sequence and start again, and the 'B' key to correct the last digit entered... The 'C' key to validate the sequence by saving in eeprom.
I think it need to use keypadEvent listener and switch case to use action key for 'A' 'B' 'C' or by using a loop If key = 'A' then "Cancel" ... If key='B' then "Correct" ... if key='C' then "Validate". In all case the sequence digit and the timestamp is retained in eeprom when the 'C' key is presed.
How to sketch all these operations?

If you can write in words what you want to happen in the various condition that will occur in normal use then it will be easier to decide how to implement the code. Your descriptions should include cases where users make mistaken entries (too few or too many characters)

Once you are clear on what you want to happen, you can think about the code that you would need to make this work

:slight_smile: yes it is quite confusing and I'll try to be a little clearer on what the sketch is supposed to do... Overall, it must save all sequence of 4 key pressed, however mistakes of seizure can occur (that is the first contraint). For exemple if 1234 is pressed instead 1734 ... Or i cancel the sequence by pressing 'A' key to start again the seizure, or i correct the last previous keys by ascending back.

If key = 'A' }
Cancel // Cancel the last sequence of digits and start again
}
If key = 'B' {
Correct // Correct the last previous digit
}
If key = 'C' {
Validate
EEPROM.write () // Save in eeprom the sequence as an "integer value"
{

The problem is to include the differents cases where users make irregular mistaken entries? How combining all this functions?

I forget to mention that there is no comparison with any password that is stored in memory. All entries are free.

Also the digit sequence entered can be irregular and not necessarily equal to 4, it's depend of mistakes made by the user.

However, finally the sequence digit must be of 4 stored after the validate 'C' key is pressed...

I think saying what you want to happen in words would be a good place to start. I don't know if this is the functionality you want, but I hope if gets you started. change and add to this description as you want

The system is capable of holding an array of four digits.
The array is cleared when the system starts and after each entry (pressing the Valdiate key)
When the user enters a digits on a keypad it is appended to the array and the digits are shown on a display
When the user presses the Cancel (delete) button the array and display are cleared
When the Correct (Backspace) button is pressed, the must recently entered digit is erased and the display is updated
If more than 4 digits are pressed, (explain here what you want to happen)
When the Validate (enter) key is pressed, the digits are processed (saved to eeprom, validated,?)

I tried to resolve it in severals and differents ways but I am turning around ... i think i am lost with it...

The system is capable of holding an array of four digits.
The array is cleared when the system starts and after each entry (pressing the Valdiate key)
When the user enters a digits on a keypad it is appended to the array and the digits are shown on a display
When the user presses the Cancel (delete) button the array and display are cleared
When the Correct (Backspace) button is pressed, the must recently entered digit is erased and the display is updated
If more than 4 digits are pressed, (explain here what you want to happen) .... save only the first 4 digits after 'C' validate key is pressed
When the Validate (enter) key is pressed, the digits are processed (saved to eeprom, validated,?)

This is exactly what what the system must do.

That is where I am with this sketch:

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

int i = 0; // variable to keep track of number of keys pressed);
char sequence [4] = {0, 0, 0, 0};  // 4 digits
char key;

char Correct = 'A';      // Correct the last digit (Backspace)
char Cancel = 'B';       // Cancel (Clear) the current sequence
char Validate = 'C';     // Validate by "saving in eeprom"
char Read = 'D';         // Read all sequences of digits from eeprom

boolean correctCombo = false;    // Make a boolean to store whether the correct sequence is entered


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

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
byte ledPin = 13;

void setup(){
  Serial.begin(9600);
  Serial.println("KEYPAD: ENTER DIGITS");
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  digitalWrite(ledPin, HIGH);   // sets the LED on
  
   if (key == 'D') {
   Serial.println("address \t sequence \t i");
   for (i=0; i < 1024; i++) {
        sequence [i] = EEPROM.read(i);
        Serial.print(i);
        Serial.print("\t");
        Serial.println(sequence [i]);
        Serial.print("\t");
        sequence [i] = EEPROM.read(i);
        Serial.println(sequence [i]);
        Serial.println();
        delay(500);
   }
 }
}

void loop(){
  if (i == 4){
  check();
  }
  char key = keypad.getKey();
  if(key != NO_KEY)
    {
    sequence[i] = key;
    i++;
    sequence[i] = '\0';
    Serial.print(key);    
  }
   if (key == 'C')   // Validate by "saving in eeprom"
   {
   for (i = 0; i < 1024; i++)
   EEPROM.write(i, sequence[i]);
   }
   if (key == 'D')                     // Read all sequences of digits from eeprom
   {                                   
        for (i=0; i < 1024; i++)
        sequence [i] = EEPROM.read(i);
        Serial.println(i);
        Serial.println(sequence [i]);
        delay(500);
   if (key == 'A') { }                 // Correct the last digit (Backspace)
   if (key == 'B') { }                 // Cancel (Clear) the current sequence
}
}

void check()
{

    if (strcmp(sequence, sequence) == 0){  
        Serial.println( "\t" "Valid");
        correctCombo = true;
        i = 0;        
     }        
 }

Here the serial output when sequences are pressed:

KEYPAD: ENTER DIGITS
5533      Valid
3333      Valid
3333      Valid
3221      Valid
1122      Valid
2333      Valid
C2222222222222333333333333333338888888D1024
2
D1024
D
D1024
D
D1024
D
D1024
D
D1024
D
ABBBAAABBD1024
A
D1024
D
D1024
D
D1024
D

I can not move forward... i can't save sequences on eeprom... Where are all my mistakes??

suggest you break the task into smaller chunks. Try and get the logic described above implemented and tested before you add any code to read or write from eeprom.

One way to do this is to write a function that you call when the 'Correct' key is pressed that (for now) just displays the 4 characters to the serial port, later you will add code to save this eeprom.

When you can enter digits, add the cancel functionality. When the digit entry is working correctly you can move on to dealing with the eeprom.

Thank you for your advices, i am going to try to brush it, hoping to get there..