Pages: [1]   Go Down
Author Topic: Arduino and Keypad  (Read 466 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I'm having some trouble with my 3x4 Matrix Keypad and an Arduino Demuilanove ATMega 328. I've uploaded this code, with the intention that it will check for a keypress, then after 4 keypresses it will check the user input array with the set password in the code, however it seems that in the serial monitor the keypad prints a random series of numbers even without a keypress.
I have learnt this is from using digital pins 0 and 1 which are used for serial communication, however is there any way to still use these pins as they are the only ones I have elft on the board due to other components?

Here is my code:

Code:
void pincode()
{
  GLCD.DrawBitmap(pin, 0,0, BLACK);

  char key= kpd.getKey();
    if(key == LOW){ } //if no key pressed, do nothing, else do the following
    else{
 {
    inputArray[i] = key; // store's key entry
    i++;
   
    if (i == 1) //if 1 press has been made
    {
      GLCD.DrawBitmap(pin1, 0,0, BLACK);
    }
   
    if (i == 2) //if 2 presses have been made
    {
      GLCD.DrawBitmap(pin2, 0,0, BLACK);
    }
   
    if (i == 3) //if 3 presses have been made
    {
      GLCD.DrawBitmap(pin3, 0,0, BLACK);
    }
   
    if (i == 4) //if 4 presses have been made
    {
      GLCD.DrawBitmap(pin4, 0,0, BLACK);
      {
        delay(5000);
       if (inputArray[0] == Main[0] &&
           inputArray[1] == Main[1] &&
inputArray[2] == Main[2] &&
   inputArray[3] == Main[3])
           {
     correctpin();
           }
       else
       {
         incorrectpin();
       }
     }
     {
       i=0; // reset integer to store user keypresses
     }
   }
 }
}
}
Logged

Wellington, New Zealand
Offline Offline
Sr. Member
****
Karma: 1
Posts: 404
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It would help if you posted all of your code.  We can't tell what libraries you're using or how you've done your setup.

If you're using pins 0 and 1 for digital I/O then you can't use the serial monitor, or have any Serial.print() calls in your code.
Logged


Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I have learnt this is from using digital pins 0 and 1 which are used for serial communication, however is there any way to still use these pins as they are the only ones I have elft on the board due to other components?
What other components? Are you using all the analog pins? If not, they can be used as digital pins.

If you are doing serial communications, even debugging, then you can NOT use pins 0 and 1 as input or output pins.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry I'll post all the code. I'm using the GLCD library and the Keypad library. I have rejigged it since the last post, I've unplugged pins 0 and 1 for diagnostics and currently have 4 wires in, for 3 rows and 1 column on the keypad.

Yes unfortunately I have used all the pins. I'm even sharing analog 5 as a digital on 19 and an A5. Luckily I've made this a condition so they don't conflict.

I hope you can help!

Code:
// -------------------------------------------------------------------------------------------------------INITIALISE---------------------------------------------------------
#include <glcd.h>
#include <Keypad.h>
#include <Servo.h>
#include "fonts/Arial14.h"         // proportional font
#include "fonts/SystemFont5x7.h"   // system font
#include "bitmaps/allBitmaps.h"

const byte myRows = 3;  // number of rows
const byte myCols = 1;  //number of columns

Servo myservo;

char keys[myRows][myCols] = {
{'1'},
{'4'},
{'7'}
}; //character array to map the button layout of the keypad

byte rowPins[myRows] = {13, 12, 3}; //array to map keypad to MCU pins
byte colPins[myCols] = {2}; //array to map keypad to MCU pins

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, myRows, myCols ); //keypad library map function

char inputArray[4]; //array to gather user keypad presses
char Main[4] = {'1','4','7','1'}; //array to hold keypad password

int i = 0;
int state = 1; //Creates the state
int pos = 0; // servo position

unsigned long startMillis;
unsigned int loops = 0;
unsigned int iter = 0;

// --------------------------------------------------------------------------------------------------------------SETUP---------------------------------------------------------

void setup(){
  GLCD.Init(NON_INVERTED);   // initialise the library, non inverted writes pixels onto a clear screen
  GLCD.ClearScreen(); 
  GLCD.SelectFont(System5x7); // switch to fixed width system font
  GLCD.ClearScreen();
 
  GLCD.DrawBitmap(splash1, 0,0, BLACK);
  delay(1000);
  GLCD.ClearScreen();
  GLCD.DrawBitmap(splash2, 0,0, BLACK);
  delay(500);
  GLCD.ClearScreen();
  GLCD.DrawBitmap(splash3, 0,0, BLACK);
  delay(500);
  GLCD.ClearScreen();
  GLCD.DrawBitmap(splash4, 0,0, BLACK);
  delay(500);
  GLCD.ClearScreen();
  GLCD.DrawBitmap(splash1, 0,0, BLACK);
  delay(500);
  GLCD.ClearScreen();
  GLCD.DrawBitmap(splash2, 0,0, BLACK);
  delay(500);
  GLCD.ClearScreen();
  GLCD.DrawBitmap(splash3, 0,0, BLACK);
  delay(1000);
  GLCD.ClearScreen();
  GLCD.DrawBitmap(splash4, 0,0, BLACK);
  delay(500);
  GLCD.ClearScreen();
  GLCD.DrawBitmap(splash5, 0,0, BLACK);
  delay(4000);
  GLCD.ClearScreen();               // clear the screen
}

// --------------------------------------------------------------------------------------------------------------LOOP---------------------------------------------------------

void loop()
{
  waiting();
}

// -------------------------------------------------------------------------------------------------CORRECT PIN ENTERED---------------------------------------------------------

void correctpin()
{
myservo.attach(19);
GLCD.DrawBitmap(welcome, 0,0, BLACK);
GLCD.CursorToXY(69,27);
GLCD.print("Tom");
delay(2000);
GLCD.ClearScreen();

for(pos = 0; pos < 90; pos += 1)  // goes from 0 degrees to 90 degrees
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
 
delay(5000);

  for(pos = 90; pos>=1; pos-=1)     // goes from 90 degrees to 0 degrees
  {                               
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
loop();
}

// --------------------------------------------------------------------------------------------INCORRECT PIN ENTERED---------------------------------------------------------

void incorrectpin()
{
GLCD.DrawBitmap(incorrect, 0,0, BLACK);
delay(4000);
GLCD.ClearScreen();
pincode();
}

// ------------------------------------------------------------------------------------------------READ FROM KEYPAD---------------------------------------------------------

void pincode()
{
  Serial.begin(9600);
  GLCD.DrawBitmap(pin, 0,0, BLACK);

  char key= kpd.getKey();
Serial.print(key);
 {
    inputArray[i] = key; // store's key entry
    i++;
   
    if (i == 1) //if 1 press has been made
    {
      GLCD.DrawBitmap(pin1, 0,0, BLACK);
    }
   
    if (i == 2) //if 2 presses have been made
    {
      GLCD.DrawBitmap(pin2, 0,0, BLACK);
    }
   
    if (i == 3) //if 3 presses have been made
    {
      GLCD.DrawBitmap(pin3, 0,0, BLACK);
    }
   
    if (i == 4) //if 4 presses have been made
    {
      GLCD.DrawBitmap(pin4, 0,0, BLACK);
      {
        delay(5000);
       if (inputArray[0] == Main[0] &&
           inputArray[1] == Main[1] &&
   inputArray[2] == Main[2] &&
   inputArray[3] == Main[3])
           {
     correctpin();
           }
       else
       {
         incorrectpin();
       }
     }
     {
       i=0; // reset integer to store user keypresses
     }
   }
 }
}

// ----------------------------------------------------------------------------WAITING FOR RFID---------------------------------------------------------

void waiting()
{
  int RFID = analogRead(A5);
  RFID = map(RFID, 0, 1023, 0, 5);
  GLCD.DrawBitmap(waiting1, 0,0, BLACK);
  delay(500);
  GLCD.DrawBitmap(waiting2, 0,0, BLACK);
  delay(500);
 
  if (RFID < 2)                      // CODE FOR RFID ANALOG VALUE. NEEDS TWEAKING
  {
    GLCD.ClearScreen();
    pincode();
  }
  else
  {
    GLCD.ClearScreen();
    loop();
  }
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The loop() function calls waiting(). The waiting() function may call loop(). Does that really seem like a good idea?

The correctpin() function calls loop(). Not a good idea, either.

Code:
  if (RFID < 2)                      // CODE FOR RFID ANALOG VALUE. NEEDS TWEAKING
No kidding. Does RFID mean something different from the usual meaning of the term?

Code:
  Serial.begin(9600);
This belongs in setup(), so it is called once, not in pincode() where it is called bazillions of times.

Code:
  char key= kpd.getKey();
Serial.print(key);
 {
Probably ought to check that a key was pressed, before printing it... What's the { for?

Looking at your code, I think that last statement is really the key to your problem. You never test that a key was pressed, so pincode() blasts through and returns many, many times before you get one key pressed.

Code:
    if (i == 1) //if 1 press has been made
    {
      GLCD.DrawBitmap(pin1, 0,0, BLACK);
    }
   
    if (i == 2) //if 2 presses have been made
    {
      GLCD.DrawBitmap(pin2, 0,0, BLACK);
    }
If i is 1, can it also be 2, 3, or 4? You need some elses in this function.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey Paul,

Thanks for your reply! It is very  helpful. As you can tell I'm fairly new to Arduino, but I shall try the things you mentioned and post a reply with my results! I left that comment there in the RFID so my colleague can tell which bits need tweaking. We mapped the value from 0 to 1023 to 0 to 5 so we get a better idea of true voltage. Our RFID seems a bit sketchy, and outputs 5v when alone and 1-2v when a tag is near, which explains the if statement.

Also for the serial begin, I'm using Analog 5 for the RFID data input, and the same pin as Digital 19 for the Servo motor output due to a lack of pins on the board. That is why I put the Serial call in that function, so it would not overwrite declaring it as a digital pin later in the code. Any idea if that is possible or will work?

Everything else seems obvious to me now. I apologise, had a lack of sleep trying to get this working. Will post my results later today! Thanks again Paul!

The loop() function calls waiting(). The waiting() function may call loop(). Does that really seem like a good idea?

The correctpin() function calls loop(). Not a good idea, either.

Code:
  if (RFID < 2)                      // CODE FOR RFID ANALOG VALUE. NEEDS TWEAKING
No kidding. Does RFID mean something different from the usual meaning of the term?

Code:
  Serial.begin(9600);
This belongs in setup(), so it is called once, not in pincode() where it is called bazillions of times.

Code:
  char key= kpd.getKey();
Serial.print(key);
 {
Probably ought to check that a key was pressed, before printing it... What's the { for?

Looking at your code, I think that last statement is really the key to your problem. You never test that a key was pressed, so pincode() blasts through and returns many, many times before you get one key pressed.

Code:
    if (i == 1) //if 1 press has been made
    {
      GLCD.DrawBitmap(pin1, 0,0, BLACK);
    }
   
    if (i == 2) //if 2 presses have been made
    {
      GLCD.DrawBitmap(pin2, 0,0, BLACK);
    }
If i is 1, can it also be 2, 3, or 4? You need some elses in this function.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Our RFID seems a bit sketchy, and outputs 5v when alone and 1-2v when a tag is near, which explains the if statement.
What RFID reader do you have? It is most likely trying to toggle the pin to send you data. You need to be reading that data far differently than you currently are.

Quote
I'm using Analog 5 for the RFID data input, and the same pin as Digital 19 for the Servo motor output due to a lack of pins on the board. That is why I put the Serial call in that function, so it would not overwrite declaring it as a digital pin later in the code.
Analog pin 5/digital pin 19 usage has nothing to do with the serial port initialization or pins. Put Serial.begin() where it belongs - in setup().
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great, thanks for the advice. I seem to have got the column working now. I have programmed numbers 1, 4 and 7. 1 and 4 are printing as expected however when I press 7 it prints "741" to the screen. I assume there might be a short circuit on the keypad. Will run a continuity test on a voltmeter and reply later.

The RFID we have uses a form of Manchester decoding to convert the signal to 1 state or another. As we got it off ebay, we got very limited information. I can't remember the chip name (Will try and dig up the datasheet if necessary) but after several nights of googling we couldn't find much out about decoding the signal. Because of that we are converting the volt reading into an analog signal in Arduino and using that as a value, abusing the fact that it reduces the voltage when a tag is near. We aren't too bothered about utilising the unique tag as this is a prototype model and we are hoping to spend more time later decoding the signal, however we do have a deadline approaching.

Thanks again for your help so far Paul

Quote
Our RFID seems a bit sketchy, and outputs 5v when alone and 1-2v when a tag is near, which explains the if statement.
What RFID reader do you have? It is most likely trying to toggle the pin to send you data. You need to be reading that data far differently than you currently are.

Quote
I'm using Analog 5 for the RFID data input, and the same pin as Digital 19 for the Servo motor output due to a lack of pins on the board. That is why I put the Serial call in that function, so it would not overwrite declaring it as a digital pin later in the code.
Analog pin 5/digital pin 19 usage has nothing to do with the serial port initialization or pins. Put Serial.begin() where it belongs - in setup().
Logged

Pages: [1]   Go Up
Jump to: