Beginner needs help w/ Keypad and LCD

Hello,

I've had my Uno for approx 2wks and am spending soo much time learning as much as I can. Youtube, Google, Blogs, Examples, PDF (terrible instructions from the kit), etc.

**Please not, I have no coding experience and and a total noob to the Arduino world. **

I have a piece I'm working on and I'm stuck in a strange loop or bug or code error. In fact, it's most def a code error (I have no idea what I'm doing). I've interpreted pieces of code from other projects (simulated on circuits.io).

Heres my code so far:

/* @file HelloKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates the simplest use of the matrix Keypad library.
|| #
*/
#include <Keypad.h>
#include <LiquidCrystal.h>

//initialize the library with the numbers of the interface pins
//LCD         lcd(RS, E,D4,D5,d6,d7)
LiquidCrystal lcd(A0,A1,A2,A3,A4,A5);

// 4x4 Matrix key pad
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

// define the key map
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

//connect to the row pinouts of the keypad
byte rowPins[ROWS] = {9, 8, 7, 6};

//connect to the column pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; 

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,2);
  
  lcd.setCursor(0,0);
  lcd.print("C1 Pro Test");

  lcd.setCursor(0,1);
  //lcd.print("Press Any Key");

}

void loop(){
  char key = keypad.getKey();
  
  lcd.setCursor(0,1);
 
  /*
  while(key == NO_KEY) {
    key = keypad.getKey();
   
  }
  */
  

  if (key){
    Serial.println(key);
    //lcd.println("                ");
    //delay(10);
    lcd.println("Capture         ");
    
  }
 
}

I can get the LCD to turn on and display my intro text

"C1 Pro Test"
and, when I press a key on the keypad, I see the corresponding keypad value on the serial monitor, although it seems inconsistent, and the word "Capture" does appear, but I can't get it to disappear without clearing the whole screen.

I've tried (you'll see the //comments above), to add "Press Any Key", in the intro text, but when I do, the "Capture" word won't register anymore. I don't understand.

I don't understand all of it actually, I've been copying and pasting code from other projects.

I tried using a while command to hold the loop to wait for a key press then clear the bottom line and display then an if to look for the key press, but that didn't work either.

Down the line, I'd like the keypad to behave like a logic keyboard and send keystrokes to my Mac.

Press A = send the CMD+K keystroke
Press 1 through 9 = keyboard # 1 to 9

I tried this:

void loop(){
  char key = keypad.getKey();
  
  lcd.setCursor(0,1);
  

  if (key == "A"){
    Serial.println(key);
    lcd.println("Capture         ");
  }
 	

}

But I get an error, "C++ forbids comparison between pointer and integer".

Need help.

Am I on the right track.

M.

 if (key == "A"){

single quote, not double

See reply #1

That did it!

But why?
I'm trying to understand.

Also, to make it display something else do I simply add more "if" commands?

M.

'A' is a character
"A" is a string.

Ah i see. So much to learn still.

heres what I have so far:

/* @file HelloKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates the simplest use of the matrix Keypad library.
|| #
*/
#include <Keypad.h>
#include <LiquidCrystal.h>

//initialize the library with the numbers of the interface pins
//LCD         lcd(RS, E,D4,D5,d6,d7)
LiquidCrystal lcd(A0,A1,A2,A3,A4,A5);

// 4x4 Matrix key pad
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

// define the key map
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

//connect to the row pinouts of the keypad
byte rowPins[ROWS] = {9, 8, 7, 6};

//connect to the column pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; 

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,2);
  
  lcd.setCursor(0,0);
  lcd.print("C1 Pro Test");

  lcd.setCursor(0,1);
  lcd.print("Press Any Key");

}

void loop(){
  char key = keypad.getKey();
  char waitForKey();
  
  lcd.setCursor(0,1); 
  
    
  if (key == 'A'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("Capture         ");
  }
 
  if (key == '1'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("1 Star          ");
  }
 
   if (key == '2'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("2 Star          ");
  }
 
   if (key == '3'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("3 Star          ");
  }
 
   if (key == '4'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("4 Star          ");
  }
 
   if (key == '5'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("5 Star          ");
  }
 
   if (key == '7'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("Green Tag       ");
  }
 
  if (key == '8'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("Yellow Tag      ");
  }
  if (key == '9'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("Red Tag         ");
  }
  if (key == '*'){
    char key = keypad.getKey();
    Serial.println(key);
    lcd.println("                ");
  }
 
  
  
}

It works, but I can't get the "lcd.print()" line to clear after a few seconds.

Once you've recognised an 'A' or a '1', you don't seem to wait for the next keypress.

AWOL:
Once you've recognised an 'A' or a '1', you don't seem to wait for the next keypress.

I don't understand.

Why would I wait for the next keypress?

Is there a way to:

Get the keypressed
print it to serial monitor
print if to LCD
wait 2 secs
go back to cursor (0,1)
clear that line

Here's the latest.

/* @file HelloKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates the simplest use of the matrix Keypad library.
|| #
*/
#include <Keypad.h>
#include <LiquidCrystal.h>

//initialize the library with the numbers of the interface pins
//LCD         lcd(RS, E,D4,D5,d6,d7)
LiquidCrystal lcd(A0,A1,A2,A3,A4,A5);

// 4x4 Matrix key pad
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

// define the key map
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

//connect to the row pinouts of the keypad
byte rowPins[ROWS] = {9, 8, 7, 6};

//connect to the column pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; 

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,2);
  
  lcd.setCursor(0,0);
  lcd.print("C1 Pro Test");

  lcd.setCursor(0,1);
  lcd.print("Press Any Key");

}

void loop(){
  char key = keypad.getKey();
  //char waitForKey();
  
  lcd.setCursor(0,1); 
  
    
  if (key == 'A'){
    char key = keypad.getKey();
    Serial.println("C1Pro Shortcut here");
    lcd.println("Capture         ");
  }
 
  if (key == '1'){
    char key = keypad.getKey();
    Serial.println("1");
    lcd.println("1 Star          ");
  }
 
   if (key == '2'){
    char key = keypad.getKey();
    Serial.println("2");
    lcd.println("2 Star          ");
  }
 
   if (key == '3'){
    char key = keypad.getKey();
    Serial.println("3");
    lcd.println("3 Star          ");
  }
 
   if (key == '4'){
    char key = keypad.getKey();
    Serial.println("4");
    lcd.println("4 Star          ");
  }
 
   if (key == '5'){
    char key = keypad.getKey();
    Serial.println("5");
    lcd.println("5 Star          ");
  }
 
   if (key == '6'){
    char key = keypad.getKey();
    Serial.println("6");
    lcd.println("Clr Color Tag   ");
  }
 
   if (key == '7'){
    char key = keypad.getKey();
    Serial.println("Green Tag");
    lcd.println("Green Tag       ");
  }
 
  if (key == '8'){
    char key = keypad.getKey();
    Serial.println("Yellow Tag");
    lcd.println("Yellow Tag      ");
  }
  if (key == '9'){
    char key = keypad.getKey();
    Serial.println("Red Tag");
    lcd.println("Red Tag         ");
  }
  if (key == '*'){
    char key = keypad.getKey();
    Serial.println("Clear line");
    lcd.println("                ");
  }
 
  
  
}

I don't understand.

Why would I wait for the next keypress?

Because it looks to me like that's what you want to do.

  char key = keypad.getKey();
...
if (key == 'A'){
    char key = keypad.getKey();

Oh I see. I didn't realize I didn't need "char key = ..." inside the if structure.

I want the keypad to act as a programmable keyboard.

I'd also like the second line to clear after 2 seconds.

I think I got it!

I couldn't get to erase the text on the LCD after I pressed a button, but that was because I forgot to reposition the cursor to (0,1).

Also I'm using a "switch" function instead of "if".

I wonder, can I add a KeyPressed Event handler with the keypad?

So I can have the LED stay on when I press and hold 'C' on the keypad.

Also, am I using the "keypad.setDebounceTime(10)" function in Setup correctly? Is it necessary with a keypad?

I'd love some feedback on how it all looks so far?

Next step, I want to have the keypad presses interact with my connected Mac. Can anyone help with that?

#include <Keypad.h>
#include <LiquidCrystal.h>

//initialize the library with the numbers of the interface pins
//LCD         lcd(RS, E,D4,D5,d6,d7)
LiquidCrystal lcd(A0,A1,A2,A3,A4,A5);

// 4x4 Matrix key pad
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

// define the key map
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

//connect to the row pinouts of the keypad
byte rowPins[ROWS] = {9, 8, 7, 6};

//connect to the column pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; 

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

#define ledpin 13

void setup(){
  
  Serial.begin(9600);

  keypad.setDebounceTime(10);
  
  pinMode(ledpin,OUTPUT);
  
  lcd.begin(16,2);
  
  lcd.home();
  
  lcd.print("C1 Pro Test");

  lcd.setCursor(0,1);
  
  lcd.print("Press Any Key");

}

void loop(){

  char waitForKey();
  
  lcd.setCursor(0,1); 
  
  char key = keypad.getKey();
      
  switch (key)
    {
      case '1':
        Serial.println("1");
        lcd.println("1 Star          ");
        delay(200);    
        lcd.setCursor(0,1);
        lcd.println("                ");
    break;
       
     case '2':
        Serial.println("2");
        lcd.println("2 Star          ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
    break;
     
     case '3':
        Serial.println("3");
        lcd.println("3 Star          ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
     break;
        
     case '4':
        Serial.println("4");
        lcd.println("4 Star          ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
     break;
        
     case '5':
        Serial.println("5");
        lcd.println("5 Star          ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
     break;
     
     case '6':
        Serial.println("6");
        lcd.println("Clear Color Tag ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
     break;
       
     case '7':
        Serial.println("7");
        lcd.println("Green Tag       ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
     break;
       
     case '8':
        Serial.println("8");
        lcd.println("Yellow Tag      ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
     break;
       
     case '9':
        Serial.println("9");
        lcd.println("Red Tag         ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
     break;

     case 'A':
        Serial.println("Capture Shortcut Here");
        lcd.println("Capture         ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
     break;

     case 'C':
        digitalWrite(ledpin, HIGH);   
        Serial.println("C");
        lcd.println("LED ON          ");
        delay(200);
        lcd.setCursor(0,1);
        lcd.println("                ");
     break;
  
     default:
        digitalWrite(ledpin, LOW);
        break;  
   
   }
  
}
  char waitForKey();

Not sure what it does but it is not doing what you think it is doing.

If you want to use waitForKey, it should be used similar to the shown below

char key = keypad.waitForKey();

And next you don't need to read the key with the keypad.getKey().

Now note that this is actually quite bad coding as it will block your loop till a key is pressed so you can not do anything else. If you e.g. also want to display a time every second, it will not be possible.

sterretje:

  char waitForKey();

Not sure what it does but it is not doing what you think it is doing.

I was looking into other codes related to the keypad, and I saw it written that way. I guess I misread or still don't understand how to code and what goes where.

If you want to use waitForKey, it should be used similar to the shown below

char key = keypad.waitForKey();

And next you don't need to read the key with the keypad.getKey().

Thank you for this. I'll try it now.

Now note that this is actually quite bad coding as it will block your loop till a key is pressed so you can not do anything else. If you e.g. also want to display a time every second, it will not be possible.

When you say bad code, what do you mean? If my intention is to have it return the key pressed to the LCD and to the serial monitor and nothing else. Is it still a bad code? if so, how would you improve it?

The next step is figuring out how to have the returned data interact with my Mac as a keystroke.

1 == 1
2 == 2
3 ==3
...

A = CMD+K (I assume I'll have to convert it to ASCII codes).

M

No, not in that case. But imagine that the Mac sends a message to the Arduino. You might never see it because you are waiting for a keypress.

By the way, the keypad returns ascii characters. So not sure what your last part is about.

sterretje:
By the way, the keypad returns ascii characters. So not sure what your last part is about.

The end goal of this project is to have the keypad send commands to my connected Mac.

I press 1 on the keypad and the Mac receives a keyboard command 1.

Press A on the keypad, Mac receives CMD+A string.

What is CMD? The '1' that was pressed first?

If you just want to send the pressed key to the Mac

void loop()
{
  char ch = keypad.getKey();

  // if a key is pressed
  if(ch != NO_KEY)
  {
    // send it over serial port
    Serial.write(ch);
  }
}

You can limit the acceptable characters

void loop()
{
  char ch = keypad.getKey();

  // if 0..4 is pressed OR 'A' or 'C'
  if((ch >= '0' && ch <=  '4') || ch == 'A' || ch == 'C')
  {
    // send it over serial port
    Serial.write(ch);
  }
}

I meant to say the Apple "command button".

See attachement.

Thank you @sterretje. You've been really helpful.

Screen Shot 2017-01-27 at 2.44.37 PM.png

This is a little outside my league, but I suspect that this can not be done with an Uno.

As far as I understand it, you want to simulate a keyboard. For that it's my understanding that you need an Arduino that can act as a HID (e.g. 32U4 based micro controller, e.g. the Leonardo or the Micro).

The alternative is to write an application for the Mac that reads the serial port and next translates the received input to keyboard presses that are send to the operating system. I have no idea how feasible this is.