Keypad help needed

I am using this code to make a buzzer go off when a PIR sensor is tripped by movement and I would like the keypad to shut the buzzer off when a code is typed in, however it does not want to work. Can anybody help, it is much appreciated. :slight_smile:

#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};
byte colPins[COLS] = {8, 7, 6};

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

char PIN[4]= {'1','2','3','4'};
char attempt[4]={0,0,0,0};
int z=0;
int inputPin = 10;
int pirState = LOW;
int val = 0;
int pinSpeaker = 9;

void setup(){
pinMode(pinSpeaker,OUTPUT);
pinMode(inputPin, INPUT);
Serial.begin(9600);
}
void playTone(long duration, int freq) {
duration *= 1000;
int period = 1000000L / freq;
unsigned long start = millis();
while (millis() - start < duration) {
digitalWrite(pinSpeaker, HIGH);
delayMicroseconds(period / 2);
digitalWrite(pinSpeaker, LOW);
delayMicroseconds(period / 2);
}
}

void correctPIN()
{
digitalWrite(pinSpeaker, LOW);
Serial.println("Correct pin entered");
}

void incorrectPIN()
{
digitalWrite(pinSpeaker, HIGH);
Serial.println("Incorrect pin entered");
}

void checkPIN()
{
int correct=0;
int i;
for ( i = 0; i <4; i++ )
{
if (attempt_==PIN*)_
_
{_
_
correct++;_
_
}_
_
} if (correct==4)_
_
{_
_
correctPIN();_
_
}_
_
else*_
* {*
* incorrectPIN();*
* }*
* for (int zz=0; zz<4; zz++)*
* {*
* attempt[zz]=0;*
* }*
}
void readKeypad()
{
_ char key =keypad.getKey();
* if (key!=NO_KEY)
_
{*

* switch(key)*
* {*
_ case'':_
_
z=0;_
_
break;_
_
case '#':_
_
delay(100);_
_
checkPIN();_
_
break;_
_
default:_
_
attempt[z]=key;_
_
z++;_
_
}_
_
}_
_
}_
void loop()
_
{_
_
val = digitalRead(inputPin); _
_
if (val == HIGH) { _
_
playTone(300, 160);_
_
delay(150);_
_
readKeypad();_
_
}_
_
{_
_
playTone(0,0);_
_
delay(300); _
_
}_
_
}_
_
[/quote]*_

Hello,

One problem:

for ( i = 0; i <4; i++ )
{
  if (attempt==PIN)
  {
    correct++;
  }
}

This should be:

for ( i = 0; i <4; i++ )
{
  if ( attempt[i] == PIN[i] )
  {
    correct++;
  }
}

Thank you for your help, and that doesn't seem to work either. The keypad still doesn't stop the light from lighting. Also for some reason the serial won't tell me when I have typed in the correct pin or incorrect pin.

Here is an easier way to see the code.

#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};
byte colPins[COLS] = {8, 7, 6};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
char PIN[4]= {'1','2','3','4'};
char attempt[4]={0,0,0,0};
int z=0;
int inputPin = 10;
int pirState = LOW;
int val = 0;
int pinSpeaker = 9;

void setup(){
pinMode(pinSpeaker,OUTPUT);
pinMode(inputPin, INPUT);
Serial.begin(9600);
}

void loop()
{
val = digitalRead(inputPin);
if (val == HIGH) {
playTone(300, 160);
delay(150);
readKeypad();
}
{
playTone(0,0);
delay(300);
}
}

void readKeypad()
{
char key =keypad.getKey();
if (key!=NO_KEY)
{
switch(key)
{
case'*':
z=0;
break;
case '#':
delay(100);
checkPIN();
break;
default:
attempt[z]=key;
z++;
}
}
}

void playTone(long duration, int freq) {
duration *= 1000;
int period = 1000000L / freq;
unsigned long start = millis();
while (millis() - start < duration) {
digitalWrite(pinSpeaker, HIGH);
delayMicroseconds(period / 2);
digitalWrite(pinSpeaker, LOW);
delayMicroseconds(period / 2);
}
}

void correctPIN()
{
digitalWrite(pinSpeaker, LOW);
Serial.println("Correct pin entered");
}

void incorrectPIN()
{
digitalWrite(pinSpeaker, HIGH);
Serial.println("Incorrect pin entered");
}

void checkPIN()
{
int correct=0;
int i;

for ( i = 0; i <4; i++ )
{
if ( attempt == PIN )
* {*
* correct++;*
* }*
*} *
if (correct==4)
* {*
* correctPIN();*
* }*
* else*
* {*
* incorrectPIN();*
* }*
* for (int zz=0; zz<4; zz++)*
* {*
* attempt[zz]=0;*
* }*
}
[/quote]

Do you know that delays and while loops will make the arduino wait until... And while it's busy waiting, it cannot do anything else.

playTone(300, 160);

This will play a tone for 300 seconds. The playTone function that you use, is a blocking function (it's using a while loop until time elapsed). So during these 300 seconds, it cannot do anything else. That mean, the call to readKeypad() will be executed after the 300 seconds has elapsed.

And what's the point of all those calls to delay() ?

I'm not sure. I got that piece of code online. So what does the 160 mean?

160 is the frequency of the tone, but stick to subject :stuck_out_tongue: Your problem is most likely this playTone function and those delays.

Why not use the tone() function instead?

I decided just to cut out the playTone function since I was only wanting the buzzer to buzz constantly. Instead I used this code and it works sometimes, but for some reason, sometimes my Arduino won't read my keypad. Do you know why?

#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};
byte colPins[COLS] = {8, 7, 6};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
char PIN[4]= {'1','2','3','4'};
char attempt[4]={0,0,0,0};
int z=0;
int inputPin = 10;
int pirState = LOW;
int val = 0;
int pinSpeaker = 9;

void setup(){
pinMode(pinSpeaker,OUTPUT);
pinMode(inputPin, INPUT);
Serial.begin(9600);
}

void loop()
{
val = digitalRead(inputPin);
if (val == HIGH) {
digitalWrite(pinSpeaker, HIGH);
readKeypad();
}
}

void readKeypad()
{
char key =keypad.getKey();
if (key!=NO_KEY)
{
switch(key)
{
case'*':
z=0;
break;
case '#':
delay(100);
checkPIN();
break;
default:
attempt[z]=key;
z++;
}
}
}

void correctPIN()
{
digitalWrite(pinSpeaker, LOW);
delay(2000);
Serial.println("Correct pin entered");
}

void incorrectPIN()
{
digitalWrite(pinSpeaker, HIGH);
delay(2000);
Serial.println("Incorrect pin entered");
}

void checkPIN()
{
int correct=0;
int i;

for ( i = 0; i <4; i++ )
{
if ( attempt == PIN )
* {*
* correct++;*
* }*
*} *
if (correct==4)
* {*
* correctPIN();*
* }*
* else*
* {*
* incorrectPIN();*
* }*
* for (int zz=0; zz<4; zz++)*
* {*
* attempt[zz]=0;*
* }*
}
[/quote]

#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};
byte colPins[COLS] = {8, 7, 6};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
char PIN[4]= {'1','2','3','4'};
char attempt[4]={0,0,0,0};
int z=0;
int inputPin = 10;
int pirState = LOW;
int val = 0;
int pinSpeaker = 9;

void setup(){
pinMode(pinSpeaker,OUTPUT);
pinMode(inputPin, INPUT);
Serial.begin(9600);
}

void loop()
{
val = digitalRead(inputPin);
if (val == HIGH) {
digitalWrite(pinSpeaker, HIGH);
readKeypad();
}
}

void readKeypad()
{
char key =keypad.getKey();
if (key!=NO_KEY)
{
switch(key)
{
case'*':
z=0;
break;
case '#':
delay(100);
checkPIN();
break;
default:
attempt[z]=key;
z++;
}
}
}

void correctPIN()
{
digitalWrite(pinSpeaker, LOW);
delay(2000);
Serial.println("Correct pin entered");
}

void incorrectPIN()
{
digitalWrite(pinSpeaker, HIGH);
delay(2000);
Serial.println("Incorrect pin entered");
}

void checkPIN()
{
int correct=0;
int i;

for ( i = 0; i <4; i++ )
{
if ( attempt == PIN )
* {*
* correct++;*
* }*
*} *
if (correct==4)
* {*
* correctPIN();*
* }*
* else*
* {*
* incorrectPIN();*
* }*
* for (int zz=0; zz<4; zz++)*
* {*
* attempt[zz]=0;*
* }*
}
[/quote]

OK, I won't....

  if ( attempt == PIN )
  {
    correct++;
  }

This will never be equal.

Oops sorry...

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

Threads merged.

  • Moderator

Also: Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the "Code" button above the posting area (It looks like a scroll with < > inside it).

  if ( attempt == PIN )

This is why we ask you to use code tags!

You have to realize that you are trying to do two things at once here, handling the sensor and handling the keypad. That disqualifies from using the delay() function (something that should be avoided anyway..)
The solution to these kinds of problems is to design a separate statemachine for each task. I have attached these state diagrams.

These state machines can then be easily coded (i do not have a keypad hooked so im using serial but it should be easy to modify):

const int speaker = 9;
const int sensor = 10;
unsigned long alarmMark;

enum {idle, buzz, noBuzz} alarmState;
enum {codeOk, key, noKey} codeState;

const char secretCode[] = {1, 2, 3, 4};
byte codeIdx;

void setup(){
  pinMode(speaker, OUTPUT);
  pinMode(sensor, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println("Armed");
  alarmState = idle;
  codeState = codeOk;
}//setup()

void loop(){
  alarm();//run alarm sm
  code();//run code sm
}//loop()

void alarm(){
//  Serial.print("alarmState: ");
//  Serial.println(alarmState);
  switch(alarmState){
    case idle:
      if(!digitalRead(sensor)){
        alarmState = buzz;//change state on next call
        tone(speaker, 160);
        alarmMark = millis();//remember time
        codeState = noKey;//signal code request
        Serial.println("Alarm");
      }//digitalRead(sensor)
      break;
    case buzz:
      if(millis()-alarmMark >= 300){//been here for 300ms
        alarmState = noBuzz;//change state next call
        //Serial.println("mute");
        noTone(speaker);
      }//if(t=300)
      if(codeState == codeOk){//enetered code is valid
        alarmState = idle;//change state on next call
        Serial.println("code ok");
        noTone(speaker);
      }//if(codeOk)
      break;
    case noBuzz:
      if(millis()-alarmMark >= 150){//been here for 150ms
        alarmState = buzz;//change state on next call
        tone(speaker, 160);
        //Serial.println("sound");
      }//if(t=300)
      if(codeState == codeOk){
        alarmState = idle;
        Serial.println("code ok");
      }//if(codeOk)
      break;
  }//switch(alarmState)
}//alarm()

void code(){
  switch(codeState){
    case noKey:
      if(Serial.available()) codeState = key;//wait for key
      break;
    case key:
      if(Serial.read()-'0' == secretCode[codeIdx]) codeIdx++;//check code, advance if valid key
      else codeIdx = 0;//reset if invalid key
      codeState = noKey;//back to waiting state
      if(codeIdx == 4) codeState = codeOk;//signal valid code and stop checking
  }//switch(codeState)
}//code()

or you could use my state machine library to get a little cleaner code

#include <SM.h>

const int speaker = 9;
const int sensor = 10;

SM alarm(aIdle);
SM code(cCodeOk);

const char secretCode[] = {1, 2, 3, 4};
byte codeIdx;

void setup(){
  pinMode(speaker, OUTPUT);
  pinMode(sensor, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println("Armed");
}//setup()

void loop(){
  EXEC(alarm);//run alarm sm
  EXEC(code);//run code sm
}//loop()

State aIdle(){
  if(!digitalRead(sensor)){//sensor is active low
    alarm.Set(aBuzz);//change state on next call
    tone(speaker, 160);
    code.Set(cNoKey);//signal code request
    Serial.println("Alarm");
  }//digitalRead(sensor)
}//aIdle()

State aBuzz(){
  if(alarm.Timeout(300)){//been here for 300ms
    alarm.Set(aNoBuzz);//change state next call
    noTone(speaker);
  }//if(t=300)
}//aBuzz()

State aNoBuzz(){
  if(alarm.Timeout(150)){//been here for 150ms
    alarm.Set(aBuzz);//change state on next call
    tone(speaker, 160);
    //Serial.println("sound");
  }//if(t=300)
}//alarm()

State cCodeOk(){
//do aboluteley nothing
}//cCodeOk()

State cNoKey(){
      if(Serial.available()) code.Set(cKey);//wait for key
}//cNoKey()

State cKey(){
  if(Serial.read()-'0' == secretCode[codeIdx]) codeIdx++;//check code, advance if valid key
  else codeIdx = 0;//reset if invalid key
  code.Set(cNoKey);//back to waiting state
  if(codeIdx == 4){
    code.Set(cCodeOk);//stop checking
    alarm.Set(aIdle);
    Serial.println("code ok");
  }//if(codeok)
}//cKey()

sensor state diagram.png

code reader state diagram.png