Capturing multiple keystrokes on a 3x4 or 4x4 keypad (like a calculator)

Hi all

I am a newbie so I'm not sure this is the right place for my question and I would really appreciate some guidance or tips or pointers with the question I have so I can get by this stumbling block with confidence.
I was playing around with microchip PIC's and picbasic for the last 7 years or more but I notice there is a much nicer set of tutorials and links and so forth and I'm hoping the same is true for the forum :slight_smile:

I have just purchased an Arduino Uno as a hobby device and have covered the first tutroial explaining how to blink an LED.
My next mission is to connect a 3x4 or 4x4 matrix keypad for input.
I have gone through the tutorial in the Arduino playground and it's working great :slight_smile:
Here is my problem or question (the one I can't seem to find an example of):
I would like to grab several keys, that I press for example 1 392 and end with a #
then print that number on a screen or LCD and store that value in a variable for use later on in the program.
So I guess it's like a calculator where you type in the the number and that stays on screen until you choose what to do with it (the operation may be like X or + or - or /)

So in a nutshell I would like to know how you combine multiple numbers that are entered in via the keypad, into one number and then convert it to binary.

Is there some kind soul or souls who could shed some light here please.

Kind regards

Den

For keypad, use the library:
http://playground.arduino.cc/code/Keypad

You need to save the single number in a integer variable like int or long (how much long the number?)
For every number multiply the previous value by 10 and add this new value.
If key is # you display decimal number on Serial monitor.
Using bitRead() http://arduino.cc/en/Reference/BitRead
you can know if a single bit of variable is 0 or 1, so print "0" or "1" on display as many bits the variable is long.
sizeof() give you the number of bits of variable. For example for int give you 16, for long -> 32

Hi there

I Would like to know how to present all my variables in my array as one number
heres what I have at the moment :

A 4x4 keypad and LCD which collect a number by a user.
Each key is stored in an array called CODE (CODE stores 3 keypresses)
I would like each keypress 'added' to represent the number typed in (like a calculator or mobile phone displays and stores the number)

For example:
char CODE[3]

1+3+4 = 134

then possible store as hex and also decimal and also binary

I would also like to number checked to see whether it's value is less than 255 or not.

Any tips or examples would be highly appreciated

Kind regards

Den

What is your expertise level? This doesn't look like rocket science. Perhaps if you post your initial attempts.

A tutorial on C programming will help you get started with arrays, and using them.

Please do not cross-post. This wastes time and resources as people attempt to answer your question on multiple threads.

This is basically your other thread, reworded.

Threads merged.

  • Moderator

denman:
For example:
char CODE[3]
1+3+4 = 134
then possible store as hex and also decimal and also binary

So, why use an array of chars and every single keypressed as char or letter?
You can use a simple variable integer like "unsigned int" or "unsigned char" (byte)

The variable x start with value 0, variable n start as 0 (n=number of keypress)
1° keypress for example is 3, so x=x1 +keypress
2° keypress for example is 5, so x=x
10 +keypress (x now is 35)
3° keypress for example is 2, so x=x*100 +keypress (x now is 352)
1, 10 and 100 are power of 10 (1O at 0=1, 10 at 1=10, 10 at 2=100)
You need to know and store in a variable how many keypress.

Variable x is a simple number that you can print as decimal, hex or binary.

Hi All

First of all apologies for the cross post in the forums...and thanks for merging the posts Niick as well as the reply to the posts. Perhaps it was initially in the wrong place.

As mentioned I am an Arduino newbie and actually c is extremely new to me too.

I have spent the last week until 3 or 4 AM each night to try and find an example or how to just accomplish what NICK mentions is "This doesn't look like rocket science" .. actually take it from a beginner's perspective where you're so excited so you have build up the electronics find your way around the IDE and all the code and commands and examples and then sift through oodles of pages on google and the forums because every since stub of example is slightly different. And as you do so you find more exciting and interesting things. And how you try code and it doesn't work and you don't know why and you have nobody to ask. No mentors or instructor inside .. and the shining light that has driven you to get going starts fading and then to add insult to injury you feel terrible having asked a question on the one place that seems like the last port of call.
So that's my experience ...!

I wan't to do more and get to learn to swim and survive and continue on but sometimes tiny stumbling blocks like the one here prevents you from finishing the planned project.

I combed the web and the tutorials but have not found a simple tutorial showing how the keypresses get accumulated (unless I have missed something?)
Sure, there are tutorials explaining the functions and all the features and so forth and how easy and simple it is to capture a single key press and display it on the serial monitor or LCD. It seems when the math or code get a little deeper the comments in the code diminish as well.
And as I said most of the examples and tutorials show different code or variables declared as integers and characters and byte and long signed and unsigned. Is there a beginner newbie forum here ? I wish I could learn the whole entire C language and all the others out there in a night or two ... but sadly I am only human...does that compute ?

Thank you nid69ita for your reply. I will dive back into the code manual to see how I can make that into code that i could understand and that works.
Seems i may need t two variables ..one to hold keycount and the other for x and a if or do while loop ?

Any other help, tips and comments would be appreciated.

Kind regards

Denman

My first step in your shoes would be to use one of the keypad tutorials / examples and at least demonstrate to yourself that when you press a key, the appropriate number can be echoed to the serial port.

Once you have that, building up a sequence should be pretty easy.

And how you try code and it doesn't work and you don't know why and you have nobody to ask.

Yes, but you haven't shown any code. What people often do is make an attempt, it works partly (or not at all) and then they post that code and ask for guidance.

Yes, but you haven't shown any code. What people often do is make an attempt, it works partly (or not at all) and then they post that code and ask for guidance.

The reason that we ask you to do that is so we have some way to measure your distance from the target (complete working code). If your code is consistently structured, well commented, and well organized, but contains a logic error, you'll get one type of response.

If your code is poorly structured, not commented well (nothing but commenting of the obvious, comments that don't match the code, etc.), and/or poorly laid out (17 pages and only one function, for example), and full of logic errors, you'll get a somewhat different response.

So strictly speaking i could fling in the examples as code ?
I have tried each of the examples and the work perfectly for a SINGLE keypress to be displayed.
I will bash around with them in the dark and post my feeble attempt then.. at least that will serve as a starting block ... :slight_smile:

Den

I will bash around with them in the dark and post my feeble attempt then.. at least that will serve as a starting block ... :slight_smile:

Perhaps you'll surprise yourself. 8)

denman:
Seems i may need t two variables ..one to hold keycount and the other for x and a if or do while loop ?
Any other help, tips and comments would be appreciated.

Yes, for example a variable named n. variable x for the value.
n can be used as exponent for pow() function (first number the base base, second for the exponent)
calculus: x=x*pow(10,n-1) +keypress
The keypress must the value of keypressed, if you press the 3 must be 3, not '3'
All in a loop and attention how many keys you press. When you end the input? after 3 digits? But if you want insert only the number 54? only 2 digits.
It is very important to prepare an analisys (every steps) of every cases and how your program need to work.

And sorry for my english.

Counting the number of keys is superflous, unless you have a fixed number of digits to enter.

set x to 0 (make it an integer)
read a key into a byte (if there's one available)
convert the ASCI key to a numeric value (key = key & 0x0f)
multiply x by 10
add key to x
keep doing this until you get a terminating key (*, #, letter, whatever you want)
when you get that terminating character, you have the number

Hi all

To all of you who have replied so far .. THANK YOU :slight_smile:
I am finally seeing a little light at the end of what has been a rather dark tunnel.
I have at least got something functional now.
It needs a lot of polishing and probably even a re-design... but so far it's sort of working.

I am using the array called 'buffer[ ]' to store the keys entered.
This essentially holds the digits I want to combine as one number and eventually display or send.

Q1.
So going back to one of my original questions .. how do you add each character ?
Regarding the X adding 10 then 100 etc ..
Where in the code do I put the loop in for that ?

I have attached the code below:

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#include <Keypad.h>
char key;
char buffer[4];
int i; //loop key counter for counting number of keys pressed
int x; //used to multiply each digit entered by 1 then 10 then 100 etc

/*
keypad section note include library #include <keypad.h> after copying library in arduino\library
then define coulms in example code below
*/

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] = {8, 9, 10, 13}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A0, A2, A1, A3}; //connect to the column pinouts of the keypad

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

void setup(){
  Serial.begin(9600);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 4);
  // Print a message to the LCD.
  lcd.print("hello, world!");
   lcd.clear();
   delay(1000);
   
 
}
  
void loop(){
  
  
  i = 0;
  buffer[0] = '\0';
  while( i < sizeof(buffer) - 1)
  {
   
  key = keypad.getKey();
  if (key == '#')
     {
      //is this where the multiplier goes ? JUST an example so long ..i know it doesn't work yet .. I am researching the subject.
       x=(buffer[0]*1)+(buffer[1]*10)+(buffer[2]*100);
       
       lcd.setCursor(1, 1);
       lcd.print(x);
       delay(2000);
       lcd.setCursor(1, 1);
       lcd.print("Sent");
       delay(1000);
       lcd.clear();

    break;
     }
     
   else if ( key != NO_KEY)
    {
      lcd.print(key);
      buffer[i] = key;
      i++;
      buffer[i]= '\0';
      }
   
  }
  
  Serial.println(buffer);
}
  
   
   char getChar()
{
  char key = keypad.getKey();
  if (key != NO_KEY)
  {
     return key;
  }
  else { 
  return NO_KEY;
   }
   
   

  }

Code tags, please, not quote tags.

Read this before posting a programming question

Gee Nick thanks you have eyes like a h@wk :slight_smile:

If Late night computer eyes;
Else Butter fingers and error of parallax;
end
result human :frowning: // (I think ?)
STYNAX ERORR
You shouldn't go in the water until you know how to swim ........... and I find in paradox.

Fixed the post.

char getChar()
{
  char key = keypad.getKey();
  if (key != NO_KEY)
  {
    return key;
  }
  else { 
    return NO_KEY;
  }

}

This function doesn't do much, eh?

If you get NO_KEY, return NO_KEY, otherwise return what you got?


I wouldn't set "i" back to zero every time through loop.

More like this:

void loop()
  {
  key = keypad.getKey ();
  if (key == NO_KEY)
    return;
    
  // add to buffer
  buffer [i++] = key;
  
  // if we have all 3, process them
  if (i == 3)
    {
    processBuffer ();
    i = 0;  
    }
}  // end of loop

denman:

  if (key == '#')

{    //is this where the multiplier goes ? JUST an example so long ..i know it doesn't work yet .. I am researching the subject.
      x=(buffer[0]*1)+(buffer[1]*10)+(buffer[2]*100);
...

I haven't a keypad to test your code.

  1. So # key is the end of input ?!? When, you need to calculate value and diplay but also clear counter variable (n variable?).
  2. You need to check also when you pressed more then 3 keys. You can make all code only if you pressed less than 3 keys.
  3. I think library put in buffer[] (is a vector of chars) the keypressed as letteral. For example pressing 3 you get char '3'. Is not a number. It's ascii rappresentation of 3 so the value is 51 (see an ascii table '0'=>48)
    you need to subtract 48 ('3'=51 51-48=3 as value)
       x=((buffer[0]-48)*1)+((buffer[1]-48)*10)+((buffer[2]-48)*100);

Q1.
So going back to one of my original questions .. how do you add each character ?
Regarding the X adding 10 then 100 etc ..
Where in the code do I put the loop in for that ?

Gads! That's all wrong... let's look at one proposed example...

The variable x start with value 0, variable n start as 0 (n=number of keypress)
... good
1° keypress for example is 3, so x=x1 +keypress
....good
2° keypress for example is 5, so x=x
10 +keypress (x now is 35)
....good
3° keypress for example is 2, so x=x*100 +keypress (x now is 352)
...Yikes! x is now 3502
1, 10 and 100 are power of 10 (1O at 0=1, 10 at 1=10, 10 at 2=100)

Let's try something similar, but right, and it does' require doing something differeent on each pass.

The variable x start with value 0, variable n start as 0 (n=number of keypress)
... good
1° keypress for example is 3, so x=x1 +keypress
....good
2° keypress for example is 5, so x=x
10 +keypress (x now is 35)
....good
3° keypress for example is 2, so x=x*10 +keypress (x now is 352)
..good

So, assuming you are collecting characters from the keyboard, and are using '#' as an indicator that you are done entering numbers...

int inNum = 0;

// code to get key

     if (key >= '0'  && key<= '9' {
       inNum = inNum * 10 + (key && 0x0f);  // create a number from the character
       }
     elseif (key  == '#') {
         go_process_number();
     }

lar3ry:
[explanation snipped for brevity]

int inNum = 0;

// code to get key

if (key >= '0'  && key<= '9' {
      inNum = inNum * 10 + (key && 0x0f);  // create a number from the character
      }
    elseif (key  == '#') {
        go_process_number();
    }

Instead of mucking about converting the ASCII value of (say) '3' to a decimal value of 3, why not define the digit keys as decimal values instead of ASCII values? Like this:

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] = {8, 9, 10, 13}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A0, A2, A1, A3}; //connect to the column pinouts of the keypad

Then you don't need to muck about with key && 0x0f every time you want to use a number key in arithmetic. (/me is wondering what other parts I may have broken with this techinque...) Also change the if statement line from if (key >= '0'  && key<= '9' { to if (key >= 0  && key <= 9) { (note I added the forgotten close parentheses).