首页 > 解决方案 > Arduino Pin 4 connected to keypad alsways HIGH resulting in not working keypad

问题描述

I am trying to integrate a keypad to my project and wanted to test it in a simple program first. The keypad is connected to the Arduino Uno (ATmega328P) like this:

C1 -> Pin 6

C2 -> Pin 8

C3 -> Pin 4

R1 -> Pin 7

R2 -> Pin 2

R3 -> Pin 3

R4 -> Pin 5

I downloaded a template program for this keypad and adjusted the configuration of my pins accordingly.

Here is the code:

#include <LCD5110_Graph.h> 
/* keyPadHiduino Example Code
   by: Jim Lindblom
   date: January 5, 2012
   license: MIT license. If you find this code useful, please
   feel free to use this code however you'd like, commercially 
   or otherwise. Just keep this license on there whatever you do.

   This code implements a 12-key USB keypad. You can type 0-9,
   * is the + sign and the # key is enter. I'm using SparkFun's
   12-button keypad, your pinouts may vary. Multi-touch is
   not supported.

   SparkFun Keypad Pinout:
   Rows and columns are connected as such:
   -------------
 R1  | 1 | 2 | 3 | - 7 (grün)
 R2  | 4 | 5 | 6 | - 2 (braun)
 R3  | 7 | 8 | 9 | - 3 (schwarz)
 R4  | * | 0 | # | - 5 (violett)
   -------------
       |C1 |C2 |C3
 6(blau) 8(gelb) 4(weiß)
*/
// Pins 1-7 of the keypad connected to the Arduino respectively: 
uint8_t keypadPins[7] = {2, 3, 4, 5, 6, 7, 8};
int keypadStatus;  // Used to monitor which buttons are pressed.
int timeout;  // timeout variable used in loop
LCD5110 LCD(9, 10, 11, 12, 13);
extern uint8_t SmallFont[]; //charactersize 6x8 pixels
extern uint8_t TinyFont[];  //charactersize 4x6 pixels
extern uint8_t MediumNumbers[];  //charactersize 12x16 pixels

void setup()
{
  LCD.InitLCD();
  LCD.setFont(TinyFont);
  
  for (uint8_t i=0; i<7; i++)
  {
    pinMode(keypadPins[i], INPUT);  // Set all keypad pins as inputs 
    digitalWrite(keypadPins[i], HIGH);  // pull all keypad pins high
  }
  
  keypadStatus = 0;
  Serial.begin(9600);
}

void loop()
{
  
  keypadStatus = getKeypadStatus();  // read which buttons are pressed
  if (keypadStatus != 0)  // If a button is pressed go into here
  {
    Serial.println("A button was pressed");
    sendKeyPress(keypadStatus);  // send the button over USB
    timeout = 2000;  // top of the repeat delay
    while ((getKeypadStatus() == keypadStatus) && (--timeout))  // Decrement timeout and check if key is being held down
      delayMicroseconds(1);
    while (getKeypadStatus() == keypadStatus)  // while the same button is held down
    {
      sendKeyPress(keypadStatus);  // continue to send the button over USB
      delay(50);  // 50ms repeat rate
    }
  }
}

/* sendKeyPress(int key): This function sends a single key over USB
   It requires an int, of which the 12 LSbs are used. Each bit in
   key represents a single button on the keypad.
   This function will only send a key press if a single button
   is being pressed */
void sendKeyPress(int key)
{
  switch(key)
  {
    case 1:  // 0x001
      LCD.clrScr();
      LCD.print("1",CENTER,14);
      LCD.update();
      Serial.print('1');  // Sends a keyboard '1'
      break;
    case 2:  // 0x002
      LCD.clrScr();
      LCD.print("2",CENTER,14);
      LCD.update();
      Serial.print('2');
      break;
    case 4:  // 0x004
      LCD.clrScr();
      LCD.print("3",CENTER,14);
      LCD.update();
      Serial.print('3');
      break;
    case 8:  // 0x008
      LCD.clrScr();
      LCD.print("4",CENTER,14);
      LCD.update();
      Serial.print('4');
      break;
    case 16:  // 0x010
      LCD.clrScr();
      LCD.print("5",CENTER,14);
      LCD.update();
      Serial.print('5');
      break;
    case 32:  // 0x020
      LCD.clrScr();
      LCD.print("6",CENTER,14);
      LCD.update();
      Serial.print('6');
      break;
    case 64:  // 0x040
      LCD.clrScr();
      LCD.print("7",CENTER,14);
      LCD.update();
      Serial.print('7');
      break;
    case 128:  // 0x080
      LCD.clrScr();
      LCD.print("8",CENTER,14);
      LCD.update();
      Serial.print('8');
      break;
    case 256:  // 0x100
      LCD.clrScr();
      LCD.print("9",CENTER,14);
      LCD.update();
      Serial.print('9');
      break;
    case 512:  // 0x200
      LCD.clrScr();
      LCD.print("Star",CENTER,14);
      LCD.update();
      Serial.print('*');
      break;
    case 1024:  // 0x400
      LCD.clrScr();
      LCD.print("0",CENTER,14);
      LCD.update();
      Serial.print('0');  // Sends a keyboard '0'
      break;
      case 2048:  // 0x800
      LCD.clrScr();
      LCD.print("Raute",CENTER,14);
      LCD.update();
      Serial.print('#');  // Sends the 'ENTER' key
      break; 
  }
}

/* getKeypadStatus(): This function returns an int that represents
the status of the 12-button keypad. Only the 12 LSb's of the return
value hold any significange. Each bit represents the status of a single
key on the button pad. '1' is bit 0, '2' is bit 1, '3' is bit 2, ..., 
'#' is bit 11.

This function doesn't work for multitouch.
*/
int getKeypadStatus()
{
  uint8_t rowPins[6] = {keypadPins[5], keypadPins[0], keypadPins[1], keypadPins[2]};  // R1 = KeypadPin[5], R2 = ...
  uint8_t columnPins[3] = {keypadPins[4], keypadPins[6], keypadPins[2]};  // C1 = KeypadPin[4], C2 = ...
  int keypadStatus = 0;  // this will be what's returned
  
  /* initialize all pins, inputs w/ pull-ups */  
   for (uint8_t i=0; i<7; i++)
  {
    pinMode(keypadPins[i], INPUT);
    digitalWrite(keypadPins[i], HIGH);
  }
  
  for (uint8_t row=0; row<4; row++)
  {  // initial for loop to check all 4 rows
    pinMode(rowPins[row], OUTPUT);  // set the row pin as an output
    digitalWrite(rowPins[row], LOW);  // pull the row pins low
    for (int col=0; col<3; col++)
    {  // embedded for loop to check all 3 columns of each row
      if (!digitalRead(columnPins[col]))
      {
        keypadStatus |= 1 << ((row+1)*3 + (col+1) - 4);  // set the status bit of the keypad return value
        Serial.print("keypadStatus: ");Serial.println(keypadStatus);
      }
    }
    pinMode(rowPins[row], INPUT);  // reset the row pin as an input
    digitalWrite(rowPins[row], HIGH);  // pull the row pin high
  }
  
  return keypadStatus;
}

To check if the pressed numbers gives back the correct value I print its value via serial communication to the arduino console and display it on my LCD.

My problem is that the moment I upload the code and the µcontroller starts running I get lot's of inputs from my keypad without touching anything, the value calculated in getKeypadStatus() is 2048" which translates to the "#" buttton. I tried to display the value keypadStatus whenever it was calculated and as a result I get tons of "2048" via serial communication.

furthermore I measured 5V at Pin 4 of the arduino. I switched some wires to check if the problem is on the keypad or arduino. When switching wires I still measured 5V on Pin 4 of arduino but and the value printed (keypadStatus) was still "2048".

The keypad itself can not be faulty as I measured the resistance for every button and it worked fine.

Does someone have advice?

标签: c++carduinomicrocontrollerkeypad

解决方案


Better use the Keypad library by Mark Stanley and Alexander Brevig. This library is responsible for setting up the pins and polling the different columns and rows. To install the Keypad library, go to Sketch > Include Library > Manage Libraries and search for "keypad". Click on the library and then click install. The code for a 3x4 keypad is as follows

#include <Keypad.h>

const byte ROWS = 4; 
const byte COLS = 3; 

char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte rowPins[ROWS] = {7, 2, 3, 5}; 
byte colPins[COLS] = {6, 8, 4}; 

Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char customKey = customKeypad.getKey();
  
  if (customKey){
    Serial.println(customKey);
  }
}

推荐阅读