Selecting From a Menu Using a 4x4 Keypad

I'm trying to take input from a 4x4 keypad to select which function will be run from a "menu" of functions. The method I had in mind is to store the values into an array and compare the entered array to switch/case statements. Unfortunately, I haven't found a good way to implement this. This is part of the code for the only thing that's worked so far:

int key;
int order[4];
if(order[0]==1 && order[1]==13 && order[2]==13 && order[3]==13){
   function1();
 }

I wanted to try making "order[]" a String instead of an int so that I could use the toInt() function to convert it to a integer to be compared to in the switch/case statements. I could also use the string comparison functions. However, when I change "order[]" to a String I get the error "invalid conversion from int to 'cont char*'" at the following line:

order[x]=key;

Key is an integer from 0-15 representing which key was pressed. I don't understand why this doesn't work or if there is a way to make this work. If there's no way to make that work, is there a better way to implement selecting a function from a "menu" of functions using the input from a keypad? Thanks in advance.

I don't get a few things:

Your numbers are in what range? 0-999? When you type one key it must return something between 0 and 9, right? Can you post all you code, ore at least the "read key function"?

I think your problem is easy, but you must change a few things in the "read key function".

luisilva:
I don’t get a few things:

Your numbers are in what range? 0-999?
When you type one key it must return something between 0 and 9, right?
Can you post all you code, ore at least the “read key function”?

I think your problem is easy, but you must change a few things in the “read key function”.

The key function works well. It takes input in from 0-9 and I can pass it into the spaces of an array (of length 4 at the moment), but passing it into a string is a problem it seems. Here are the parts of the code I think are relevant:

String keys="123A456B789C*0#D";
int key;
boolean key_lockout=false;
String order[4];

void loop(){
    Serial.println("Begin:");
    for (int x=0; x<4; x++){ //Loop Assigns Values to 'order[]'
    key=getKeypad();
    if(key==-1){
      x=x-1; //prevents loop from iterating until a key is pressed
   }
    else{
        if(key!=14) //Print Keys Pressed
          Serial.print(keys[key]);
          delay(100);
          order[x]=key;
        if(key==14){  //Skips a line
          Serial.println();
        }
      }
    }
}
//Keypad Function for keypad on one pin
int getKeypad(){
  int ret=-1;
  boolean reset_lockout=false;
  if(analogRead(A0)==0)
    key_lockout=false;
  else if(!key_lockout){
    delay(100);
    ret=15.5-(log((analogRead(A0)-183.9)/58.24)/0.1623);//+0.5; //Interprets which key was pressed
    key_lockout=true;
    //Serial.println (ret);
    //Serial.print("AnalogRead");
    //Serial.println(analogRead(A0));
  }
  return ret;
}

The keypad function is a bit more complex than most because it only uses one analog pin as opposed to eight digital pins. The signal is passed over different resistances depending on which button was pressed.

You have a few bugs, I think.

String keys = "123A456B789C*0#D";
int key;
boolean key_lockout = false;
String order[4];

void loop() {
  Serial.println("Begin:");
  for (int x = 0; x < 4; x++) { //Loop Assigns Values to 'order[]'
    key = getKeypad();
    if (key == -1) {
      x = x - 1; //prevents loop from iterating until a key is pressed
    }
    else {
      if (key != 14) //Print Keys Pressed
        Serial.print(keys[key]);
      delay(100);
      order[x] = key;
      if (key == 14) { //Skips a line
        Serial.println();
      }
    }
  }
}
//Keypad Function for keypad on one pin
int getKeypad() {
  int ret = -1;
  boolean reset_lockout = false;
  if (analogRead(A0) == 0)
    key_lockout = false;
  else if (!key_lockout) {
    delay(100);
    ret = 15.5 - (log((analogRead(A0) - 183.9) / 58.24) / 0.1623); //+0.5; //Interprets which key was pressed
    key_lockout = true;
    //Serial.println (ret);
    //Serial.print("AnalogRead");
    //Serial.println(analogRead(A0));
  }
  return ret;
}

I think like this your code looks better. I only went to menu Tools->Auto format.
Now, tell me: What you want to do if the key is different of 14? Only print it to the serial or also do:

      delay(100);
      order[x] = key;

Because you are only printing the key to the serial!

Yes, you can use atoi(), but you need to change something. I don’t see it, so I don’t know what you are doing wrong.

I don’t know if you are using the A-D keys, but if you don’t, the best way to do what you are trying to do is, for example:

    for (int i=0, value=0; i<4; i++) {
        value = value*10 + order[x]-'0'; 
    }

After this, you will have a number from 0 to 9999 (if you don’t use the letters). If you need the letters or if you what, you can change the ‘A’ for the value 10, ‘B’ for 11, etc. I this case you must to the array of keys like:

int keys[] ={1, 2, 3, 10, 4, 5, 6, 11, 7, 8, 9, 12, -1,0, -2, 14}; //"123A456B789C*0#D";

luisilva:
I think like this your code looks better. I only went to menu Tools->Auto format.
Now, tell me: What you want to do if the key is different of 14? Only print it to the serial or also do:

      delay(100);

order = key;

Using the button represented by 14 (on my keypad it is the # button) works as an ‘enter’ button, skipping a line, and in another line of the code it “enters” your order. The code completely works if “order” is an int. If it is defined as a string then…

      order[x] = key;

…gets the error I mentioned before.

Yes, you can use atoi(), but you need to change something. I don’t see it, so I don’t know what you are doing wrong.

I have never seen this function before specifically. I just looked it up, and it seems to take a string (and possibly an array?) and “convert” it to an integer. I don’t really understand exactly how it works or what the exact inputs and outputs of it are. Arduino has a similar function called toInt() that I was trying to use.

I don’t know if you are using the A-D keys, but if you don’t, the best way to do what you are trying to do is, for example:

    for (int i=0, value=0; i<4; i++) {

value = value*10 + order-‘0’;
    }



After this, you will have a number from 0 to 9999 (if you don't use the letters). If you need the letters or if you what, you can change the 'A' for the value 10, 'B' for 11, etc. I this case you must to the array of keys like:


int keys ={1, 2, 3, 10, 4, 5, 6, 11, 7, 8, 9, 12, -1,0, -2, 14}; //“123A456B789C*0#D”;

That looks better than my idea of trying to use strings. I was hoping there was a more concise way. Thank you very much. As of now I intend to only use the numeric keys. I will try something like this out and see how it goes. Thanks again.

You miss the setup() function in your code.

If you want you can try de code like I was pointing:

//String keys="123A456B789C*0#D";//don't need this
int keys[] = {1, 2, 3, 10, 4, 5, 6, 11, 7, 8, 9, 12, -1, 0, -2, 14};
int key;
boolean key_lockout = false;
//String order[4];//don't need this

void loop() {
  Serial.println("Begin:");
  for (int x = 0, option=0; x < 4; x++) { //Loop Assigns Values to 'order[]'
    key = getKeypad();
    if (key == -1) {
      x = x - 1; //prevents loop from iterating until a key is pressed
    }
    else {
      if (key != 14 && key != 12) {//Print Keys Pressed
        Serial.print(keys[key]);   // print the value of the key pressed
        delay(100);
        //order[x] = key;   // don't use this
        option = option*10 + keys[key]; // NOTE: you only process the key if it is different  of '*' or '#'
      }
      if (key == 14) { //Skips a line
        Serial.println(option);   // prints the entery value entered.
      }
    }
  }
}
//Keypad Function for keypad on one pin
int getKeypad() {
  int ret = -1;
  boolean reset_lockout = false;
  if (analogRead(A0) == 0)
    key_lockout = false;
  else if (!key_lockout) {
    delay(100);
    ret = 15.5 - (log((analogRead(A0) - 183.9) / 58.24) / 0.1623); //+0.5; //Interprets which key was pressed
    key_lockout = true;
    //Serial.println (ret);
    //Serial.print("AnalogRead");
    //Serial.println(analogRead(A0));
  }
  return ret;
}

If you note, I made very few changes. Test if it work for what you want.

Good luck.