Hello,
I am trying to feed digits through a keypad and intending to get a combination of digit.
For example: I pressed 123 then, integer num = 123.
For some reason, my code is not working.
I will very appreciate if you could help me solve this issue.
Thanks.
int key_loop(){
// if (count > 100) count = 0;
char key[100] = {keypad.waitForKey()};
key[100] = {keypad.getKey()};
TFTscreen.text(key,count,60);
if (key != NO_KEY){
Serial.println(key);
if (count > 1000) count = 0;
delay(150);
}
int key1 = atoi(key);
//Serial.println(key1);
while ((key1 >= 0) && (key1 <= 9)) {
int keyValue = key1 - 0;
num = (num * 10) + keyValue;
key[100] = {keypad.waitForKey()};
}
count=count + 12;
Serial.print("Got the number: ");
Serial.println(num);
//resetFunc();
return(count);
}
To solve this, I had to define waitforkey and getkey as array.
no you are receiving characters one by one and you need to build an array of char which then you can pass to your TFTscreen for display and analysis. (there are other way to do that on the fly)
a char is something like 'H', just one symbol taking one byte of memory. if you do char letter = 'H'; then your variable name letter is the address of a byte in memory which will be filled with the ASCII value of the symbol 'H'
a string is composed of multiple chars and is stored in memory as consecutive bytes. usually one allocate an array for that such as char message[100]; . This reserves 100 bytes in memory for your message (from message[0] to message[99]) and message is actually the pointer to that memory space, so a char *, a pointer (the *) to somewhere there are a bunch of char stored.
Thanks for explanation.
Yes it is clear to me but what doesn't make sense is TFTscreen.text(key,count,60);
Why can't I print a character? If I pressed 1 which is '1' in character format, I should be able to see this on the screen, but I don't.
If I define as array, TFT works great.
screen.text([color=blue]text[/color], xPos, yPos);
[color=blue]text[/color] : [color=red]char array[/color], the text you want to write on the screen
so you need to pass an array (null terminated sequence of characters) - that is from my explanation above a pointer to a set of character, not just one character as this is not what the function expects. if you want to print only 1 character, you still need to put it into a buffer of 2 chars, the first one being your character you want to show and the second one being the '\0' null character so that you do have a well formed string array.
So again - you need to read the input on the keypad as they come in and build up the string.
text : char array, the text you want to write on the screen
so you need to pass an array (null terminated sequence of characters) - that is from my explanation above a pointer to a set of character, not just one character as this is not what the function expects. if you want to print only 1 character, you still need to put it into a buffer of 2 chars, the first one being your character you want to show and the second one being the '\0' null character so that you do have a well formed string array.
So again - you need to read the input on the keypad as they come in and build up the string.
Create an array with 2 elements, populating the 0th element.
key[2] = {keypad.getKey()};
Then, write to the 3rd position in a 2 element array, thereby stomping on memory you don't own. The curly braces here are useless. The value that you are writing may well be NO_KEY, by the way.
No wonder things are not going well.
const char *key1 = &key[0];
This is useless. Anywhere you (try to) use key1, you can use key[0], instead.
if (key != NO_KEY){
Since key is the address of an array, it will never equal NO_KEY, so this test is worthless, even if it were correct.
Then, write to the 3rd position in a 2 element array, thereby stomping on memory you don't own. The curly braces here are useless. The value that you are writing may well be NO_KEY, by the way.
Array indices go from 0 to size -1' So if you declare an array key[2], you can access the elements using the indices 0 and 1. If you access element 2 (key[2]) you are overwriting (bad) or reading (not so bad but still bad) something that does not belong to the array.
sterretje:
Array indices go from 0 to size -1' So if you declare an array key[2], you can access the elements using the indices 0 and 1. If you access element 2 (key[2]) you are overwriting (bad) or reading (not so bad but still bad) something that does not belong to the array.
Sure, I am using key[0].
On TFT, I do see all the digits but in serial monitor "Got the number: 0"
zeus2kx:
I am not sure I understood.
Can you give an example?
Thanks.
Assuming you have a simple standard keypad, try this code. I did not try it so hopefully it works, even if there is a bug, you'll probably get the idea. I just copied the header part from the examples just wrote the loop part to show some of the things discussed above.
don't forget to put your serial console at 115200
#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] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
char message[10]; // ten memory slots, from 0 to 9
int nbCharacters = 0; // will count how many we get
unsigned long value = 0;
void setup() {
Serial.begin(115200);
}
void loop() {
// we read something from the keypad. this returns the null character ('\0') if nothing is available
char key = keypad.getKey();
if (key) { // if the key is not null, we've got something to handle
// build up a string of character
message[nbCharacters++] = key; // store the key at position nbCharacters, then increase nbCharacters (this is what ++ does)
message[nbCharacters] = '\0'; // put end of string in the next position to have a well formed string.
// if this is a digit we typed, then build up our value
if ((key >= '0') && (key <= '9')) {
value = 10 * value + key - '0'; // build up decimal representation of the number
}
// let's display where we are so far:
Serial.print("key entered\t= '"); Serial.print(key); Serial.println("'");
Serial.print("Value\t= "); Serial.println(value);
Serial.print("Message\t= \""); Serial.print(message); Serial.println("\"");
// make sure we don't overflow the buffer. after 9 chars + the trailing '\0' we add, we reset
if (nbCharacters >= 9) {
nbCharacters = 0; // will restart next time
value = 0;
Serial.println("message buffer full, reset everything");
}
}
}
void loop()
{
// an array to hold two characters
char key[2];
// initialize to zero
memset(key, 0, sizeof(key));
// read key
key[0] = keypad.getKey();
// you now have an array with one key that you can convert to integer
int x = atoi(key);
}
Do you really want to read 100 characters from the keypad? You do conversion to int so the max will be 5 plus possibly a sign
Define a maximum number of digits that you want to read. If possible, use '#' or '*' as the key; this make life easier.
/*
read characters from keypad till '#' is pressed
returns:
NULL if input not complete (no '#') else pointer to nul terminated input
*/
char * readKeypad()
{
// array to store keypad input; 6 characters plus terminating nul character
static char kpBuffer[7];
// index into above array to indicate where keypress must be stored
static byte index = 0;
if(index == sizeof(kpBuffer))
{
Serial.println("Buffer overflow; data discarded");
index = 0;
return NULL;
}
// read keypad
kpBuffer[index] = keypad.getKey();
// if '#', it's end of input
if(kpBuffer[index] == '#')
{
// create nul terminated string
kpBuffer[index] = '\0';
// reset the index so next time we read we fill kpBuffer from beginning
index = 0;
// and return the user input
return kpBuffer;
}
// if a key was pressed, increment the index
if(kpBuffer[index]!= NO_KEY)
{
index++;
}
// indicate input not yet complete
return NULL;
}
void loop()
{
char *kpString = readKeypad();
if(kpString != NULL)
{
Serial.println(atoi(kpString));
}
}
loop() will continuously call readKeypad(). readKeypad() will return NULL as long as the input is not complete; once the input is complete ('#' pressed), it will return the text that the user entered.
You can also create a readKeypadWithEcho() that will echo a keypress to the TFT
J-M-L:
Assuming you have a simple standard keypad, try this code. I did not try it so hopefully it works, even if there is a bug, you'll probably get the idea. I just copied the header part from the examples just wrote the loop part to show some of the things discussed above.
Super!!! Thanks a bunch.
key entered = '1'
Value = 1
Message = "1"
key entered = '2'
Value = 12
Message = "12"
key entered = '3'
Value = 123
Message = "123"
key entered = '#'
Value = 123
Message = "123#"
Two things:
How do I stop adding digits to message?
How do I set # to behave as "enter"? Should I define as a case?
Stop pressing keys. More realistically, you want some event to cause the contents of message to be converted to a value, stored somewhere, and for message to get a \0 in position 0.
How do I set # to behave as "enter"? Should I define as a case?
Since there are no switch statements, a case seems pointless. An else if statement, on the other hand, seems reasonable.