Multiple number entry with a keypad?

I have a adafruit 419 membrane keypad. I'm using the library found at Arduino Playground - Keypad Library

I am displaying single digits correctly in the serial monitor. What I want to do, is be able to take a string of number entries, terminated with the #, and save into a variable. So, push 1 2 3 4 # would save 1234 into a variable. The # tells the sketch that data entry is finished, and to listen for a new entry. Advice?

Current sketch:

/* @file HelloKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates the simplest use of the matrix Keypad library.
|| #
*/
#include <Keypad.h>

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

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

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char key = keypad.getKey();
  
  if (key){
    Serial.println(key);
  }
}

Advice?

Go for it. What is the problem?

Well, I assume I need a string array:

char entryStr[3];

then a loop that adds entry characters to the array as long as entry is not #.

then I need to concatenate the array members, and add .mp3 to the end, so I can load a file from my sd card. I'm getting ahead of myself, and I don't know how to code this without some direction.

Well, I assume I need a string array:

You need a larger array than that to hold "1234".

then a loop that adds entry characters to the array as long as entry is not #.

You already have that loop(). You need an index variable, to keep track of where you last wrote.

The process of getting intermittent data is the same, regardless of where the data comes from - the serial port, the keypad, an ethernet client. Robin2 and Nick Gammon have posted plenty on how to read from serial.

Here is my code so far. I'm getting boxes and an n when I print the array:

/* @file HelloKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates the simplest use of the matrix Keypad library.
|| #
*/
#include <Keypad.h>

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

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

char entryStr[3]; 
int i=0;

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char key = keypad.getKey();
 
 if (key){ 
  if (key != '#'){
     entryStr[i]= key;
     i++;
    
     }
   else {
   entryStr[i]= '/n';  
   i=0;
   Serial.println(entryStr);
   }  


 }
}

I enlarged the array to 8, and removed the '/n' insert. resolved that issue.now need to save the array into a variable, and clear the array.

now need to save the array into a variable, and clear the array.

strcpy() and entryStr[0] = '\0';

i as an index is a horrid name. Far too easy to accidentally write a loop that uses i, and trashes your one letter global name.

I don't have a keypad, but this might work:

/* @file HelloKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates the simplest use of the matrix Keypad library.
|| #
*/
#include <Keypad.h>

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

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

char entryStr[5];   // This can hold up to 4 digits
int i=0;

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char key;
  int index = 0;
  
  while ( (key = keypad.getKey()) != '\n') {   // Until they press Enter...
    entryStr[index++] = key;
  }
  entryStr[index] = '\0';     // Make it a string
  Serial.println(entryStr);
}

Remember that strings in C always terminate with the null character ('\0'). If you forget this, anything using the string will march through memory until it reads a zero somewhere. This also means that your input char array must be 1 element larger than you expect the input to be.

W8TEE

String fileName = entryStr;
memset(entryStr, 0, sizeof(entryStr));
fileName = fileName + ".mp3";
did the trick for me.

Code finished, here is the sketch that creates a filename from the entry, and allows you to cancel and start over with a * entry. # tells the sketch that the entry is ready to be processed. Thank you all (especially Mike McRoberts) for your help!

#include <Keypad.h>

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

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

char entryStr[8]; 
int i=0;

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char key = keypad.getKey();
 
 if (key){ 
   if (key == '*'){
   memset(entryStr, 0, sizeof(entryStr));  
   i=0;
   key=0;
   Serial.println(""); 
   Serial.println("Canceled"); 
   
   } else if (key != '#'){
     entryStr[i]= key;
     i++;
     Serial.print(key);
     }
   else {
   Serial.println(""); 
   i=0;
   key=0;
   
   String fileName = entryStr;
   memset(entryStr, 0, sizeof(entryStr));
   fileName = fileName + ".mp3";
   Serial.println(fileName);
   }  


 }
}

Pissing away resources wrapping a 13 character maximum string in a String is silly.

Pissing away resources wrapping a 13 character maximum string in a String is silly.

Plus the other inefficient ways to do things. Anytime you see exact duplicates of statements, such as:

   memset(entryStr, 0, sizeof(entryStr));  
   i=0;
   key=0;

you can almost bet the farm that other resources are being squandered.

Feel free to suggest optimizations. Those variables need to be reset to zero after use for the next entry, so I'm not sure why you think they're squandered resources.

so I'm not sure why you think they're squandered resources.

You don't understand the concept of NULL terminated, apparently. It takes one NULL to terminate an array of chars.

There was no reason to assign a new value to key.

tried that, and it didn't work. politeness seems to be a concept you are missing. we both have room for improvement.

tried that, and it didn't work.

Where are you properly NULL terminating the array?

I had

entryStr[0] = '\0';

where I now have

memset(entryStr, 0, sizeof(entryStr));

I was still getting left over data on subsequent entries.

I had

entryStr[0] = '\0';

where I now have

memset(entryStr, 0, sizeof(entryStr));

That should have been

entryStr[i] = '\0';

which makes it obvious that i is a crappy name.

Again, I don't have a keypad, but see if this works:

#include <Keypad.h>

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

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

void setup() {
  Serial.begin(9600);
}

void loop() {
  char entryStr[12];
  char key;
  int i = 0;

  while (1) {
    key = keypad.getKey();
    switch (key) {
      case '*':                     // Cancel
        Serial.println("");
        Serial.println("Canceled");
        break;
      case '#':                     // Done
        entryStr[i] = '\0';
        strcat(entstr, ".mp3");
        Serial.print(entstr);
        break;
      default:                      // Add a char
        entryStr[i++] = key;
        break;
    }
    if (key == '#' || key == '*') { // Start over??
      break;
    }
  }
}

Note the disappearance of memset() and filename and fewer statements on key and i.

There is no output in the Serial Monitor. I did correct the inconsistent spellings on entryStr, but that did not help.