So I run into a problem when I am trying to disarm the system. When I upload the code to the arduino it asks me to enter a pin and then it activates the system right away. But then when I try to deactivate the system it takes the pin and just clears the screen and execute the mainScreen function that i have set.
The code is provided below:
#include "Keypad.h"
#include "LiquidCrystal.h"
#include "Password.h"
LiquidCrystal lcd(0,1,10,11,12,13);
char newPasswordString; //hold the new password
char newPassword[4]; //charater string of newPasswordString
//initialize password to 1234
//you can use password.set(newPassword) to overwrite it
Password password = Password("1234");
byte maxPasswordLength = 4;
byte currentPasswordLength = 4;
// keypad type definition
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9,8,7,6}; //Rows 0 to 3
byte colPins[COLS]= {5,4,3,2}; //Columns 0 to 3
int count=0;
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup()
{
lcd.begin(16, 2);
mainScreen();
}
void loop(){
char key = keypad.getKey();
if (key != NO_KEY){
delay(60);
switch (key){
case 'A': activate(); break;
case 'B': break;
case 'C': break;
case 'D': deactivate(); break;
case '#': break;
case '*': break;
default: processNumberKey(key);
}
}
}
void processNumberKey(char key) {
lcd.print(key);
currentPasswordLength++;
password.append(key);
if(password.evaluate()){
activate();
}
}
void activate() {
if (password.evaluate()){
lcd.clear();
lcd.print("Activated.");
delay(1000);
mainScreen();
} else {
lcd.clear();
lcd.print("Wrong Password!");
mainScreen();
}
}
void deactivate(){
if (password.evaluate()){
lcd.clear();
lcd.print("Deactivated.");
delay(1000);
} else {
lcd.clear();
lcd.print("Wrong Password!");
mainScreen();
}
}
void mainScreen(){
lcd.clear();
lcd.print("Enter Pin:");
keypad.getKey();
}
As noted in Arduino keypad 4x4 to LCD activate/deactivate you have to keep current state and you have to CLEAR the password and currenPasswordLength. See the WORKING example in the answer.
It won't help that you set byte currenPasswordLength = 4. If you press first key, it will be incremented to 5, next key increments it to the 6 and so on.
You'll get 4 again after the 256 key-presses!!!!!!! And as you don't clear previously checked password, you'll get "wrong password" result (and eventually stack overflow).
Related
I have developed two codes but while combining both of them is not giving me the desired result.
The following code correctly displays the text message input of keypad on the LCD and prints it perfectly as a text message.
#include <SoftwareSerial.h> // serial software library for interfacing gsm module
SoftwareSerial Serial1(2, 3); // RX, TX // connect gsm Tx at D2 and Rx at D3
#include<LiquidCrystal.h> // LCD library for interfacing LCD
LiquidCrystal lcd(14,15,16,17,18,19); // connect rs,en,d4,d5,d6,d7 respectevely
int i=0;
#include <Keypad.h> // keypad library for interfacing keypad
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
int x=0;
int y=0;
int n=0;
int minValue=0;
int maxValue=0;
char keyPress=0;
int keyPressTime=100;
String msg="";
char hexaKeys[ROWS][COLS] =
{
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {11, 10, 9, 8}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
String alpha="1!#_$%? ABC2 DEF3 GHI4 JKL5 MNO6 PQRS7 TUV8 WXYZ9 * 0# ";
void setup()
{
Serial1.begin(9600); // init serial1 for GSM
lcd.begin(16,2); // init LCD
delay(2000);
lcd.clear();
lcd.print("Initializing GSM");
delay(2000);
/*Serial1.print("\r");
delay(1000);*/
Serial1.print("AT+CMGF=1\r");
delay(1000);
Serial1.print("AT+CMGS=\"+91**********\"\r");
delay(1000);
lcd.clear();
lcd.print("Wallet Ready");
delay(2000);
}
void loop()
{
int n=0;
lcd.clear();
lcd.noCursor();
while(1)
{
lcd.cursor();
char key = customKeypad.getKey();
if(key=='1')
getkey(0, 7, key);
if(key=='2')
getkey(8, 12, key);
else if(key=='3')
getkey(13, 17, key);
else if(key=='4')
getkey(18, 22, key);
else if(key=='5')
getkey(23, 27, key);
else if(key=='6')
getkey(28, 32, key);
else if(key=='7')
getkey(33, 38, key);
else if(key=='8')
getkey(39,43, key);
else if(key=='9')
getkey(44, 49, key);
else if(key=='*')
getkey(50, 51, key);
else if(key=='0')
getkey(52, 54, key);
else if(key=='#')
getkey(55, 56, key);
else if(key == 'C')
{
x--;
lcd.setCursor(x,y);
lcd.print(" ");
n--;
msg[n]=' ';
lcd.setCursor(x,y);
}
else if(key == 'D')
{
lcd.clear();
lcd.noBlink();
lcd.print("Sending Data");
lcd.setCursor(0,1);
lcd.print("To Phone");
/*Serial1.print("\r");
delay(1000);*/
Serial1.print("AT+CMGF=1\r");
delay(1000);
Serial1.print("AT+CMGS=\"+91**********\"\r");
delay(1000);
Serial1.println(msg);
delay(1000);
Serial1.write(0x1A);
delay(1000);
lcd.clear();
lcd_status();
// clearmsg();
n=0;
i=0;
x=0;
y=0;
msg="";
}
}
}
void getkey(int minValue, int maxValue, char keyPress)
{
int ch=minValue;
int pressed=1;
char key=keyPress;
lcd.noBlink();
for(int i=0;i<keyPressTime;i++)
{
if(key==keyPress)
{
lcd.setCursor(x,y);
lcd.print(alpha[ch]);
ch++;
if(ch>maxValue)
ch=minValue;
i=0;
}
key=customKeypad.getKey();
delay(10);
}
if(pressed)
{
x++;
msg+=alpha[ch-1];
n++;
if(x>15)
{
x=0;
y=1;
}
}
pressed=0;
lcd.blink();
}
void lcd_status()
{
lcd.clear();
lcd.print("Transaction Sent");
lcd.setCursor(0,1);
lcd.print("Successfully");
delay(2000);
lcd.clear();
}
And this code gives me correct GPS location value stored in the string Message.
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
/*
This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
It requires the use of SoftwareSerial, and assumes that you have a
9600-baud serial GPS device hooked up on pins 12(rx) and 13(tx).
*/
static const int RXPin = 12, TXPin = 13;
static const uint32_t GPSBaud = 9600;
boolean sent = false;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
String message="";
void setup()
{
Serial.begin(9600);
ss.begin(GPSBaud);
}
void loop()
{
// This sketch displays information every time a new sentence is correctly encoded.
if (ss.available()>0 && sent == false){
if (gps.encode(ss.read())){
displayInfo();
if(message!=""){
Serial.print(message);
sent=true;
}
}
}
}
void displayInfo()
{
if (gps.location.isValid())
{
String lati=String(gps.location.lat(), 4);
String longi=String(gps.location.lng(), 4);
message="location: "+lati+","+longi+"\n";
}
}
But the issue comes when I am trying to combine the two codes such that I get the correct keypad input and GPS location on printing the text message through GSM module.
I'm working on a project on which I'm using a keypad to type a password, what I've done is that I'm reading keys typed by the user and collect it in an array to compare it with the password. The problem that I'm facing is that when I compare the typed word and and the correct password I'm getting always "wrong password".
Here is my 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','#'}
};
char passwrd[7];
char cst[7]="*1998#";
byte rowPins[ROWS] = {28, 27, 26, 25}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {24, 23, 22}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
void setup()
{
Serial.begin(9600);
}
void loop()
{
int i=0;
do
{
char key = keypad.getKey();
if (key != NO_KEY)
{
passwrd[i]=key;
i++;
Serial.println(key);
}
}while (i!=6);
Serial.println(passwrd);
Serial.println(cst);
if (passwrd==cst)
{
Serial.println("correct passwrd");
}
else
{
Serial.println("wrong passwrd");
}
}
Here is what I'm getting from the serial com:
*
1
9
9
8
#
*1998#
*1998#
wrong passwrd
Where is the problem?
Using == on a char* will compare the address that the pointer points to in memory, since a c-type string is a pointer. You need to use the strcmp() function.
strcmp() returns 0 if the c-strings are identical.
This should work:
if (strcmp(passwrd, cst) == 0)
{
Serial.println("correct passwrd");
}
else
{
Serial.println("wrong passwrd");
}
Demonstration
Put this on your Arduino to demonstrate this:
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
char* are_the_same(int val) {
if(val == 0)
return "No";
return "Yes";
}
void loop() {
// put your main code here, to run repeatedly:
char* one = "test";
char two[5];
// We are copying 'test' into string two. If we don't do this the compiler will optimise and make them point to the same piece of memory and ruin the demonstration.
int i;
for (i = 0; i < 5; i++)
two[i] = one[i];
Serial.print("one == two, are they the same? ");
Serial.println(are_the_same(one == two));
Serial.print("strcmp(one, two) == 0, are they the same? ");
Serial.println(are_the_same(strcmp(one, two) == 0));
Serial.println();
delay(1000);
}
This will give you:
one == two, are they the same? No
strcmp(one, two) == 0, are they the same? Yes
So as of right now when I arm the system and move my hand in front of the PIR sensor it says system triggered how do i get it to take a password from the user to deactivate the system. Also when the system is deactive it should say on the screen "Not Active"
#include <LiquidCrystal.h>
#include <Password.h>
#include <Keypad.h>
//Password
Password password = Password("1234");
LiquidCrystal lcd(0, 1, 10, 11, 12, 13);
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = { // Define the Keymap
{
'1','2','3','A' }
,
{
'4','5','6','B' }
,
{
'7','8','9','C' }
,
{
'*','0','#','D' }
};
byte rowPins[ROWS] = {9,8,7,6};
byte colPins[COLS] = {5,4,3,2};
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
int armed = 0;
const int pir1 = A4;
int sensorHit = 0;
int alarmStatus = 0;
int alarmActive = 0;
int zone = 0;
void setup() {
// put your setup code here, to run once:
lcd.begin(16,2);
pinMode(pir1, INPUT);
mainScreen();
keypad.addEventListener(keypadEvent);
}
void loop() {
// put your main code here, to run repeatedly:
keypad.getKey();
if(alarmActive == 1){
if(digitalRead(pir1) == HIGH){
zone = 0;
alarmTriggered();
}
}
}
void keypadEvent(KeypadEvent eKey){
switch (keypad.getState()){
case PRESSED:
lcd.print(eKey);
switch (eKey){
case '#': checkPassword(); break;
default:
password.append(eKey);
}
}
}
void alarmTriggered(){
password.reset();
alarmStatus = 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("SYSTEM TRIGGERED");
lcd.print(0,1);
if(zone == 0){
lcd.print(" FRONT DOOR OPEN ");
}
}
void checkPassword(){
if (password.evaluate()){ //if code is correct:
lcd.clear(); //clear LCD
lcd.print("VALID PASSWORD"); //print message
password.reset(); //resets password after correct entry
delay(1500); //wait...
lcd.clear(); //clear
if (alarmStatus==0 && alarmActive == 0){ //if system is off (ie: disarmed)
lcd.print("ARMED!"); //display message
alarmActive=1; //system armed
alarmStatus=1;
delay(2000); //wait
lcd.clear(); //clear
lcd.setCursor(0, 0); //return to top left of LCD
lcd.print("Code to disarm:"); //back to where we began
}
else{
lcd.print("DISARMED!"); //display message
alarmActive=0; //system unarmed
alarmStatus=0;
delay(2000); //wait
lcd.clear(); //clear
lcd.setCursor(0, 0); //return to top left of LCD
lcd.print("Code to arm:"); //back to where we began
}
}
else{ //if password is incorrect:
lcd.clear();
lcd.print("INVALID PASSWORD");
password.reset(); //resets password after INCORRECT entry
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Retry Code:");
}
}
void mainScreen(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Enter Pin:");
}
You need an input device for entering the password. A simple example can be 10 switches where each switch represent 1 so our password has to be between 0 to 10. You add the switches values together and compare with your set password. The rest should be easy for you.
I have a problem with an activation/deactivation system for Arduino. I can get the code to activate or deactivate once I upload a fresh copy of the code, but once I activate it after upload and try to deactivate the security system, it only takes in 2 numbers and then prompts me to Wrong password.
#include "Keypad.h"
#include "LiquidCrystal.h"
#include "Password.h"
LiquidCrystal lcd(0,1,10,11,12,13);
char newPasswordString; //hold the new password
char newPassword[4]; //character string of newPasswordString
//initialize password to 1234
//you can use password.set(newPassword) to overwrite it
Password password = Password("1234");
byte maxPasswordLength = 6;
byte currentPasswordLength = 0;
// keypad type definition
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9,8,7,6}; //Rows 0 to 4
byte colPins[COLS]= {5,4,3,2}; //Columns 0 to 4
int count=0;
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup()
{
lcd.begin(16, 2);
mainScreen();
}
void loop(){
char key = keypad.getKey();
if (key != NO_KEY){
delay(60);
switch (key){
case 'A': activate(); break;
case 'B': break;
case 'C': break;
case 'D': deactivate(); break;
case '#': break;
case '*': break;
default: processNumberKey(key);
}
}
}
void processNumberKey(char key) {
lcd.print(key);
currentPasswordLength++;
password.append(key);
if (currentPasswordLength == maxPasswordLength) {
activate();
}
}
void activate() {
if (password.evaluate()){
lcd.clear();
lcd.print("Activated.");
delay(1000);
mainScreen();
} else {
lcd.clear();
lcd.print("Wrong Password!");
}
}
void deactivate(){
if (password.evaluate()){
lcd.clear();
lcd.print("Deactivated.");
delay(1000);
mainScreen();
} else {
lcd.clear();
lcd.print("Wrong Password!");
delay(1000);
mainScreen();
}
}
void mainScreen(){
lcd.clear();
lcd.print("Enter Pin:");
keypad.getKey();
}
So for the first time it works (activation) and next time (deactivation) it doesn't?
The only occurrences of currentPasswordLenght are these:
Global variable declaration and initialization: byte currentPasswordLength = 0;
Incrementation in processNumberKey: currentPasswordLength++;
Compare and call activate in processNumberKey: if (currentPasswordLength == maxPasswordLength) {
The third one also explains why the deactivation (second round) fails after the second key press as maxPasswordLength is 6 and after the activation the currentPasswordLength is 4.
Example of working code:
#include <Key.h>
#include <Keypad.h>
#include <Password.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
const char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
const byte rowPins[ROWS] = {9,8,7,6};
const byte colPins[COLS] = {5,4,3,2};
Keypad keypad { makeKeymap(keys), rowPins, colPins, ROWS, COLS };
Password passwd { "1234" };
bool activated = false;
byte count = 0;
uint32_t timeout = 0;
void setup() {
Serial.begin(115200);
}
void loop() {
char key = keypad.getKey();
switch (key) {
case '0' ... '9':
Serial.print(key);
passwd << key;
timeout = millis() + 5000;
if (++count == 4) {
Serial.println();
if (passwd.evaluate()) {
activated = !activated;
Serial.println(activated ? F("Activated") : F("Deactivated"));
} else {
Serial.println(F("Wrong password"));
}
passwd.reset();
count = 0;
}
break;
case 'A' ... 'D':
break;
default:
delay(60);
break;
}
if ((count != 0) && (millis() > timeout)) {
Serial.println(F("\nTimeout"));
passwd.reset();
count = 0;
}
}
I have this code which I try to process is entering a password "78486" to shut down the sensor function !
The problem is, when I enter the code using the keypad .. It doesn't work ..
So please help me to make it work .. I think the problem is in the if condition !
#include <Keypad.h>
char* secretCode = "78486";
int position = 0;
int minSecsBetweenEmails = 60; // 1 min
int val = 0;
long lastSend = -minSecsBetweenEmails * 1000l;
const byte rows = 4;
const byte cols = 3;
char keys[rows][cols] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
byte rowPins[rows] = {8, 7, 6, 5};
byte colPins[cols] = {4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys),
rowPins, colPins,
rows, cols);
void setup()
{
pinMode (9, OUTPUT);
Serial.begin(9600);
}
void loop()
{
long now = millis();
char key = keypad.getKey();
if (key == '*') {
pinMode (9, INPUT); }
if(key == '2') {
pinMode (9, OUTPUT);
// if(key == secretCode[position])
// {
// position++;
// }
// if (position == 5){
// pinMode (9, OUTPUT);
// }
}
if(digitalRead(9) == HIGH)
{
if (now > (lastSend + minSecsBetweenEmails * 1000l))
{
Serial.println("MOVEMENT");
lastSend = now;
}
else
{
Serial.println("Too soon");
}
}
}
Personally I'd check the value at the end of the reading phase: this way it's harder to guess what is the wrong char (if it exits every time a char is wrong, you will have to do at most 50 tries; if it exits at the end you will need to do at most 100000).
Moreover you need a way to reset the position and start a new password: since you didn't use the # char I used it.
Lastly I definitely prefer the switch case in this case. So
// In the main definition part:
uint8_t position = 0;
char readingCode[5];
char secretCode[] = "78486";
// In the loop:
char key = keypad.getKey();
switch (key)
{
case '*': // shut down sensor
pinMode (9, INPUT);
break;
case '#':
position = 0;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (position < 5)
{
readingCode[position] = key;
position++;
}
if (position >= 5)
{ // check the code
bool correct = true;
uint8_t i;
for (i = 0; i < 5; i++)
if (readingCode[i] != secretCode[i])
correct = false;
if (correct)
pinMode (9, OUTPUT);
position = 0;
}
break;
}
Just one more thing: I don't know what does getKey return when no keys are pressed. Just verify it