Attempt to convert Keypad input to integer

I know this is probably a topic that has been beaten to death, but I just need someone to kindly provide an answer to a programming question. The project I am working on requires a person to input a number (up to 4 digits) by using a 4 x 4 keypad and have that value used in an other part of the sketch. I have fully read and worked with the examples for using a keypad and looked at the forum topics on converting a keypad entry to an integer, but I am having an issue in printing out the value of the integer variable in Serial Monitor. I know that when I press a button on the keypad, that it is registering the correct string value (by observing the Serial Monitor screen), but when trying to verify that the string value was converted correctly to an integer, I cannot seem to get this correct. I have looked through examples and forum entries both here and on line, but I cannot seem to find my error.
The code compiles without errors and I can see the string values of the buttons pushed.
Please see below for the code:

//LCD and Key Pad Test Sketch
//Library definitions
#include <Keypad.h>

//Keypad dimensions
const byte ROWS = 4; //4 rows
const byte COLS = 4; //4 columns


//Define buttons on keypad
char keys[ROWS][COLS] ={
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

//Pin IDs
byte rowPins[ROWS]={9,8,7,6}; //Row pins
byte colPins[COLS]={5,4,3,2}; //Col pins

//initialize keyboard function
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

String inputString="";
long inputInt;


void setup() {
  // Comms setup
  Serial.begin(9600);
  
  inputString.reserve(4); //max number of digits for a number is 4.  This can be changed.
}

void loop() {
  // Reading of key press
  char key = keypad.getKey();
  if(key){
    Serial.println(key);
    if(key >='0' && key <-'9'){  //Only act on numeric keys
      inputString += key;  //append new character to input string
    }
    else{
      if(key =='#'){
        if(inputString.length()>0){
          inputInt = inputString.toInt();  //Got integer number
          Serial.println("Integer Value of keypad input: ");
          Serial.println(inputInt);
          inputString=""; //clear input
        }
        else {
          if(key =='*'){
            inputString ="";
          }
        }
      }
    }
  }
}

Any assistance or suggestion for improvement would be greatly appreciated.

  • Please explain what this does ?
key <-'9'
  • Avoid using String.
    Just assemble the incoming integer as characters are received.
int myInteger;
. . .

myInteger = myInteger * 10 + (key - ‘0’);

2 Likes

That's not correct. should be "<=".

You should also do yourself a favor and ditch the Strings. You are reading a digit. just add it to your number and build it up in place.

inputInt = input*10 + key - '0';

1 Like

I was amazed (and a little shocked) that the compiler let that one slide by even with warnings set to ALL, but after a moment's reflection I realized that if char is signed (which it apparently is by default in the AVR core) it's perfectly legit.

Still, ugh!

look this over

//LCD and Key Pad Test Sketch
//Library definitions
# include <Keypad.h>

//Keypad dimensions
const byte ROWS = 4; //4 rows
const byte COLS = 4; //4 columns

//Define buttons on keypad
char keys[ROWS][COLS] ={
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
};

//Pin IDs
byte rowPins[ROWS]={9,8,7,6}; //Row pins
byte colPins[COLS]={5,4,3,2}; //Col pins

//initialize keyboard function
Keypad keypad = Keypad (makeKeymap(keys), rowPins, colPins, ROWS, COLS);

int val;

// -----------------------------------------------------------------------------
void loop () {
    char key = keypad.getKey ();
    if (key)  {
        if ('0' <= key && key <= '9')  {
            val = 10*val + key - '0';
            Serial.println (val);
        }
        else if (key =='#') {
            Serial.print   ("val = ");
            Serial.println (val);
            val = 0;
        }
    }
}

// -----------------------------------------------------------------------------
void setup () {
    // Comms setup
    Serial.begin (9600);
}

Thanks for all of the responses.
Yeah, I missed where the "<-", should have been "<=". That was a good catch.
As for the not using a string, could someone point me a good explanation on how "inputInt - input*10+key-'0'" syntax works . I saw this in one of the forum topics, but did not fully understand. If I understood the explanation correctly, each number character is assigned a number value and this line of code translates the number code to an integer, did I understand this correctly? Why is this better than the method I used? I am also going to go out on a limb and assume this will work for multiple digit numbers?

As always, I appreciate the assistance.

I will incorporate these suggestions and let you know how it works out.

Thanks,

all characters are represented by 8-bit values. ASCII digits are in sequence from 0-9. subtracting the value of '0', 48 or 0x30, results in the binary value 0-9. For example '4' - '0' is 4

As far as multiple, the first time through the loop val = 0 so 10 * 0 is still 0. The second and subsequent times through the loop effectively shift val 1 pos to the left. The reason + key - '0' works is the ascii code for digits is 30, 31, etc to 39 so 5 coming in the serial port is actually the ascii code 35 and subtracting the ascii value of '0' or 30 yields 5.

Thanks for the clearer explanation of this syntax. I get it now.

Again Thanks for the explanation and assistance.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.