Arduino 1602 4*4键盘 的电子密码锁-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 31092|回复: 39

Arduino 1602 4*4键盘 的电子密码锁

[复制链接]
发表于 2016-12-7 15:34 | 显示全部楼层 |阅读模式
好久没发帖了,来电小干货~~
昨天心血来潮帮一位同学做了一个关于密码锁的课设
要求如下:
1、在输入密码正确的状态下可以修改密码
2、连续输入三次错误密码锁定键盘,锁定状态下检测到有按键按下重新计时

这里涉及到4*4键盘和1602的使用,做的过程发现还是需要动动脑的
先上照片
开机输入密码~~
IMG_0581.JPG

输入中密码用‘*’号显示
IMG_0582.JPG
输入错误
IMG_0583.JPG
连续三次错误锁定键盘等待30秒
IMG_0584.JPG
锁定期间有按键输入重新计时

IMG_0585.JPG

实现过程:

其实还是蛮简单的
使用到的硬件有LCD1602、4*4键盘、和promini(UNO、nano也可)
本次使用到的库有Keypad.h和LiquidCrystal.h
没有用IIC转接板,如果用IIC转接的用对应的1602的IIC库就可以啦,也是蛮简单的

先附上1602引脚图
1602.jpg
1602接线(偷懒复制注释里的,3号脚接电阻调节对比度,我这里偷懒直接接地了,所以有些模糊)
   LCD RS pin to digital pin 12
   LCD Enable pin to digital pin 11
   LCD D4 pin to digital pin 5
   LCD D5 pin to digital pin 4
   LCD D6 pin to digital pin 3
   LCD D7 pin to digital pin 2
   LCD R/W pin to ground
   LCD VSS pin to ground
   LCD VCC pin to 5V


键盘四横四纵,我接了三横四纵
具体接线看程序中

代如下:
[mw_shl_code=cpp,true]/*
  The circuit:
   LCD RS pin to digital pin 12
   LCD Enable pin to digital pin 11
   LCD D4 pin to digital pin 5
   LCD D5 pin to digital pin 4
   LCD D6 pin to digital pin 3
   LCD D7 pin to digital pin 2
   LCD R/W pin to ground
   LCD VSS pin to ground
   LCD VCC pin to 5V
   10K resistor:
   ends to +5V and ground
   wiper to LCD VO pin (pin 3)

  lcd.begin(16, 2);
  lcd.print("hello, world!");
  lcd.setCursor(0, 1);
*/
#include <LiquidCrystal.h>//1602库
#include <Keypad.h>//键盘库
#include <EEPROM.h>//EEPROM库用来保存修改过的密码,掉电后不遗失

const byte ROWS = 3; //3行
const byte COLS = 4; //4列
//键盘位置
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3', '4'},
  {'5', '6', '7', '8'},
  {'9', '0', '*', '#'}
};
byte rowPins[ROWS] = {15, 14, 10}; //定义接键盘横排引脚
byte colPins[COLS] = {9, 8, 7, 6}; //竖排引脚定义

//新的键盘对象
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

// 1602引脚,接法参照最上方注释
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);//lcd连接引脚

String oldPassword = "";//保存老密码
String newPassword = "";//保存输入的修改密码
int addNum = 0;//错误计数
String inPut = "";//保存输入字符串
String n = "";//字符串转整型用的变量
int beep = 13;//蜂鸣器和板载led
unsigned long now;//现在时间用于计时
unsigned long before;//参考时间用于计时
unsigned long delayTime = 30000;//锁定时间
void setup() {
  pinMode(beep, OUTPUT);//蜂鸣器引脚
  Serial.begin(9600);//初始化串口
  // 定义LCD两行16列
  lcd.begin(16, 2);


//开机从EEPROM中读取密码,四位密码保存在EEPROM0-3地址当中
  for (int i = 0; i < 4; i++)
  {
    oldPassword += EEPROM.read(i);
  }
//串口打印测试信息
  Serial.print("Old Password is : ");
  Serial.println(oldPassword);
  delay(2000);
  lcd.setCursor(0, 0);//1602输出位置,格式列、行
  lcd.print("Please input :");//1602输出
}
int i = 6;//'*'号开始位置
void loop() {
  char customKey = customKeypad.getKey();//获取按键
  if (customKey)//有按键按下
  {
    inPut += customKey;//保存输入
    lcd.setCursor(i, 1);//在指定位置输出*号
    lcd.print('*');
//串口打印测试信息
    Serial.println("inPut is : ");
    Serial.println(inPut);
    Serial.println("onece");
    i++;//后移1602输出*号位置
    if (i > 9)//超过输出位置回归
    {
      i = 6;
    }
  }
  //比较密码

  if (inPut == oldPassword) //密码正确
  {
    addNum = 0;//错误次数清零
    Serial.println("Bingo!");//串口打印测试信息
    lcd.clear();//清屏
    lcd.setCursor(4, 0);//输出位置
    lcd.print("Bingo!");//输出bingo
    delay(2000);//延时2秒
    lcd.clear();//清屏
    delay(500);
    lcd.setCursor(0, 0); //1列1行
    lcd.print("Change Password?");//lcd输出是否修改密码
    Serial.println("change password?");//串口打印测试信息
    lcd.setCursor(0, 1);
    lcd.print("1.YES       2.NO");//lcd输出1yes2no
    int a = 1;
    while (a)//等待按键按下
    {
      customKey = customKeypad.getKey();
      Serial.println("while");
      if (customKey == '1') //选择1则修改密码
      {
        a = 0;//跳出while循环
        Serial.println("select 1");//串口打印测试信息
        inPut = "";//输入字符串清空
        lcd.clear();//LCD清屏
        lcd.setCursor(0, 0);//位置
        lcd.print("Input the new:");//输出
        for (int b = 0; b < 4;)//输入新密码
        {
          customKey = customKeypad.getKey();
          if (customKey)
          {
            lcd.setCursor(b + 4, 1);
            lcd.print(customKey);
            newPassword += customKey;
            n = customKey;
            int num = n.toInt();//将输入的字符转换为整型用toInt()函数
            n = "";
//EEPROM保存新密码
            EEPROM.write(b, num );
            Serial.print("EEPROM ");
            Serial.print(b);
            Serial.print(" is : ");
            Serial.println(EEPROM.read(b));
            Serial.print("new password is ");
            Serial.println(newPassword);
            b++;
            if (b == 4 )//满足4位
            { newPassword = "";
              lcd.clear();
              lcd.setCursor(0, 0);//格式列、行
              lcd.print("Save the new !");//lcd输出保存新密码
              delay(2000);//延时两秒
              oldPassword = "";//清空重置
//读取新密码并设置为当前密码
              for (int i = 0; i < 4; i++)  {
                oldPassword += EEPROM.read(i);
              }
              lcd.clear();
              lcd.setCursor(0, 0);//格式列、行
              lcd.print("Please input :");
            }
          }
        }
      }
      else if (customKey == '2') //选择2什么都不干返回主页
      {
        a = 0;
        inPut = "";//清空输入
        lcd.clear();
        lcd.setCursor(0, 0);//格式列、行
        lcd.print("Please input :");
        Serial.println("back to home");
      }
    }
  }
  else if (inPut.length() == 4 && inPut != oldPassword)//密码错误
  {
    Serial.println("ERROR");//串口打印测试信息
//LCD组合操作清屏,位置,输出信息
    lcd.clear();
    lcd.setCursor(5, 0);
    lcd.print("ERROR!");
    inPut = "";//清空输入
    addNum++;//错误计数+1
//串口打印测试信息
    Serial.print("addNum is : ");
    Serial.println(addNum);
    delay(1500);
    lcd.clear();
    lcd.setCursor(0, 0);//格式列、行
    lcd.print("Please input :");
  }
  if (addNum > 2)//当错到第三次
  {
//LCD组合操作
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Wait for 30s");
//蜂鸣器报警一秒
    digitalWrite(beep, HIGH);
    delay(1000);
//计时
    before = millis();//参考时间
    now = millis();//当前时间
//串口输出测试信息
    Serial.print("before is : ");
    Serial.println(before);
    Serial.print("now is : ");
    Serial.println(now);
//锁定键盘等待30秒锁定
    while (now - before < delayTime)//当前时间减参考时间小于设定锁定时间
    {
      lcd.setCursor(0, 0);
      lcd.print("Wait for   s");
      lcd.setCursor(9, 0);
      lcd.print((30000 - (now - before)) / 1000);//LCD输出剩余秒数
      now = millis();
      Serial.print("n-b= ");
      Serial.println(now - before);
      char key = customKeypad.getKey();

      if (key)//如果有按键按下重置时间
      {
        before = millis();
        now = millis();
//串口输出测试信息
        Serial.print("key~~~before is  ");
        Serial.println(now - before);
      }
    }
    addNum = 0;//锁定时间到,错误次数清零
    lcd.clear();
    lcd.setCursor(0, 0);//格式列、行
    lcd.print("Please input :");
  }
}
[/mw_shl_code]

最后增加一点:
由于程序开头是直接读取EEPROM中保存的数据,所以在烧录上面的程序前请先对EEPROM进行写入默认密码操作,代码如下(先烧这个程序,再烧上面的代码)
[mw_shl_code=cpp,true]#include <EEPROM.h>

void setup() {
  for(int i = 0;i<4;i++)
  {
    EEPROM.write(i,1);//将EEPROM中0-3地址写入1,初始默认密码四个一
    }
   }

void loop() {}[/mw_shl_code]

操作视频:


使用到的Keypad库,LiquidCrystal库IDE自带
Keypad.zip (9.58 KB, 下载次数: 405)





发表于 2016-12-7 16:24 | 显示全部楼层
给楼主点赞
发表于 2016-12-7 16:50 | 显示全部楼层
顶一下                    
发表于 2016-12-7 22:09 | 显示全部楼层
可以教一下proteus仿真怎么接吗?楼主
 楼主| 发表于 2016-12-8 09:05 | 显示全部楼层
weimei1234 发表于 2016-12-7 22:09
可以教一下proteus仿真怎么接吗?楼主

从来没用过仿真,都是做实物实验的
发表于 2016-12-13 11:11 | 显示全部楼层
楼主做的不错!程序有错误,编译不了,是怎么回事? 图片.png
 楼主| 发表于 2016-12-13 14:01 | 显示全部楼层
songxia8013 发表于 2016-12-13 11:11
楼主做的不错!程序有错误,编译不了,是怎么回事?

程序应该是没有问题的,我刚才又编译了一下,看你用的貌似是arduino.org里下载的1.7.2,我用的是arduino.cc里下的IDE,我现在的版本是1.6.9,也有新的版本出来,要不换下IDE试试
发表于 2016-12-13 16:05 | 显示全部楼层
mostblack 发表于 2016-12-13 14:01
程序应该是没有问题的,我刚才又编译了一下,看你用的貌似是arduino.org里下载的1.7.2,我用的是arduino. ...

多谢朋友!我也分不清是谁的软件,就是网上随便下了一个。我再下载试试。
发表于 2016-12-14 15:28 | 显示全部楼层
我将这个程序的键盘模式修改了,改成四行三列的键盘模式,但是在程序中无法连续输入密码,就是输入一次算一次,变成了四次输入错误的情况,请问在程序中应该如何修改键盘不能连续输入密码的问题?
 楼主| 发表于 2016-12-14 23:11 | 显示全部楼层
songxia8013 发表于 2016-12-13 16:05
多谢朋友!我也分不清是谁的软件,就是网上随便下了一个。我再下载试试。 ...

不客气的
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 13:37 , Processed in 0.096901 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表