Getting input from sparkfun Keypad

Hi guys.

I'm trying to figure out how i can use the keypad library to get the user to enter a value, i e press 2 then 3 then # on the keypad for 23 followed by an enter. I can read the keypad and get individual readings, but how can i convert the 2 and 3 to an int of value 23?

maybe i'm missing something but i cant work this out!!!

thanks for your help.

Dave

how can i convert the 2 and 3 to an int of value 23?

A simplistic way of doing it is shown below (untested). The idea is that you initialize an accumulator to zero and then when a digit key is received you multiply the accumulator by 10 and add in the value of the just-received key.

I call this simplistic because it has several shortcomings:

  • It doesn't allow "editing" the value, i.e. it doesn't support backspacing to correct an entered value but you could add that.
  • It ignores unsupported keys. You may want to add some user feedback indicating that an invalid key was pressed.
  • It returns zero if the Enter key is pressed with no preceding digit keys. You may want to ignore the enter key in that case. The variable 'valKeys' indicates the number of valid digit keys that have been seen.
  • It doesn't handle overflow. If you press the 9 key 99 times and then Enter, the value returned will not be correct. You could add user feedback indicating an error after a certain number of digits have been received. The unsigned long accumulator can handle up to 9 arbitrary digits, representing values up to 999,999,999.

The ideas in this code can be used to implement a similar function to support floating point value entry using, for example, the asterisk to represent the decimal point.

// Get an unsigned integer value from the keyboard terminated by an Enter key.
// All non-numeric keys (other than Enter) are ignored.
unsigned long
GetUnsignedVal()
{
#define ENTER_KEY '#'
  unsigned long val = 0;
  unsigned valKeys = 0;

  for (;;)
  {
    int key;

    key = kpd.get_key();
    if ((key >= '0') && (key <= '9'))
    {
      // add the key's value to the accumulator
      val = (val * 10) + (key - '0');
      valKeys++;
    }
    else if (key == ENTER_KEY)
      break;
  }
  return(val);
#undef ENTER_KEY
}

Thanks, i'll try this out!

One thing I've done w/ the keypads is to add each key entered to a char buffer, and then use atoi(), strtoul(), etc. to convert the buffer to an integer.

e.g.:

...

if( in_input == true && input_value == '#' ) {
   
   the_value = atoi(buffer);
   
   memset(buffer, 0, INPUT_BUF_LEN);
   
   buf_cur_pos = 0;

}
 else if( in_input == true ) {
   
   buffer[buf_cur_pos] = input_value;
   buf_cur_pos++;
}

!c

One thing I've done w/ the keypads is to add each key entered to a char buffer

The sample code that you showed has no protection for buffer overflow. If the user presses a digit key too many times, data following the buffer in memory will be overwritten causing difficult-to-diagnose problems.

The code fragment may be suitable to address this issue:

else if (in_input == true ) {
  if (buf_cur_pos < (INPUT_BUF_LEN - 1))
    buffer[buf_cur_pos++] = input_value;
}

The sample code that you showed has no protection for buffer overflow. If the user presses a digit key too many times, data following the buffer in memory will be overwritten causing difficult-to-diagnose problems.

... indeed - it also lacked variable and constant declaration, functions, etc. ;D I was trying to explain it as briefly as possible. It's often worth keeping in-mind that our readers may be fairly new to programming in general, and may not be aware of pitfalls and traps of common methods.

I'll make sure to keep that in-mind!

!c

Hi,

sorry for the delay in answering but thanks for your replies. I've been trying to get that first code example to work, and after some tweaking i managed to get it to compile but i still cant get it to actually output anything. can you have a look and see what i might be doing wrong?

thanks

#include <keypad.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(11, 13, 2, 7, 8, 9, 10);
keypad kpd = keypad(4, 3);
unsigned long i;

unsigned long GetUnsignedVal()
{
#define ENTER_KEY '#'
unsigned long val = 0;
char key[2];
int key_int = 0;
for (;:wink:
{
key[0] = kpd.get_key();
key[1] = '\0';
if ((key[0] >= '0') && (key[0] <= '9')) {

key_int = atoi(key);

val *= 10;
val += key_int;
lcd.clear();
lcd.print(val);

}

if (key[0] == ENTER_KEY) {
break;
}
return val;

}

}

void setup() {
kpd.init();

}

void loop() {
i = GetUnsignedVal();
lcd.clear();
lcd.print(i);

}

Hello Harry,

I wrote the keypad library and the tutorial that goes with it. However, not all the "gotcha's" are in the tutorial. You can find more notes and information in the keypad.cpp file.

Probably the worst thing I did was to make the library grab the digital lines every single time it reads a key. It made sense to me because when I wrote the library I wanted to be able to share the four data lines with the 4bit lcd library. In order to make that work I had to modify the lcd library, too.

So if you are sharing any hardware on the keypad data pins you need to grab control every time you re-enter your code segment.

-Mark