基于Arduino UNO 的密码电子锁 带蓝牙HC05 LCD1602-IIC

原创内容----转载请说明。

材料(只是主要的):

材料
名称 个数
Arduino UNO 1
LCD1602A--IIC(要带IIC转接板) 1
矩形按键3*4 (也可以自制)

1

继电器模块 (也可以自制 Q8550+IN4148) 1
任意V电磁锁 1
5mm或3mm led 2
杜邦线 n

接口定义

名称

接口

单片机      硬件

备注
蓝牙

10<------RX

11------->TX

VCC---+5V

GND----GND

SoftwareSerial.h

原0(RX)口无法正常通讯

LCD1602AIIC

SDA---SDA

SCL---SCL

VCC---+5V

GND---GND

void
矩形按键3*4

2, 3, 4, 5 //行

6, 7, 8    //列

void

达成启动

(继电器)

9
警告led 12 密码输入错误
错误led 13 严重错误(可省略)
使用的库文件
Passwordlock.h 自定义
Keypad.h
Wire.h
LiquidCrystal_I2C.h
SoftwareSerial.h

使用的是多文件编写,主要使用的是C(不包括库文件{头文件}),现在只是写完,但为完善

例如:

下次添加(可选):
1.开门一直不关检测  2.NFC开门(刷卡)    3.WLAN(无线,互联网,远程)开门

4.可找回密码(需要USB连入电脑/手机)并且要管理员密码.....

想办法进行断电保存...

说明:
接键输入密码开门,可以改密码,并且可以删除输入(#键);
蓝牙输入密码开门,可以改密码。
互不冲突(不同密码)也可以同密码需改下。
蓝牙连接上可提示。
有任何问题会亮灯并在usb波特9800报错。

不多说了上代码:

Passwordlock.ino

#include"Passwordlock.h"

SoftwareSerial BT(10,11); //10-RX 11-TX

bool GetKey_Value();   //获取键盘值
void Failure_function();  //失效函数
void Strand_door(); //串口
char Serial_port();//串口接收到信息 并返回
void Serial_PortManagement();  //串口管理

const byte ROWS = 4; //行
const byte COLS = 3; //列

//按键接口定义
byte rowePins[ROWS] = {2, 3, 4, 5}; //行
byte colPins[COLS] = {6, 7, 8}; //列
//辅助脚位定义
byte reach = 9;       //达成启动-脚位
byte led_reachErrors = 12; //警告-脚位
byte led_errors = 13; //错误-脚位


short reac_time = 3000; //达成启动-时间

//定义矩形按键,键位值
char Keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
//用户密码-用于保存
char User_Password[Password_Max] = {'1', '2', '3', '4', '5'};
//用户串口密码-用于保存
char BT_Password[Password_Max] = {'1', '2', '3', '4', '5'};

//用户串口临时密码
char BT_UserPd[Password_Max];



//设置LCD1602设备地址,具体看模块手册
LiquidCrystal_I2C lcd(0x27, 16, 2);
//设置矩形键盘
Keypad keypad = Keypad(makeKeymap(Keys), rowePins, colPins, ROWS, COLS);


void setup()  //在main ()中调用
{
  pinMode(led_errors, OUTPUT);
  pinMode(led_reachErrors, OUTPUT);

  pinMode(reach, OUTPUT); //达成
  Serial.begin(9600);
  BT.begin(38400);
  lcd.init();                  // 初始化LCD
  lcd.backlight();             //设置LCD背景等亮

  digitalWrite(reach, HIGH); //关闭继电器
  digitalWrite(led_errors, LOW);
}

int ergodic = 10;  //遍历
char auxiliary; //辅助键使用(决定程序走向)
char Temporary_password[Password_Max];  //临时密码 用于比较

void loop()   //在main ()中for( ; ; ;)调用
{
  //analogRead(Bluetooth);
init_errors:   //goto
  /****************************/
  //只让执行一遍,否则重复打印
  if (ergodic == 10)
  {
    lcd.clear();  // 清屏
    lcd.setCursor(0, 0);               //设置显示指针
    lcd.print("QWQ-Welcome-QAQ");
    lcd.setCursor(0, 1);
    lcd.print("'#'Key InPassword");


    //初始化-临时密码
    if ((change_init_password(Temporary_password)))
    {
      Serial.println("[state]:init_password:ok");
    }
    else
    { //初始化失败
      Serial.println("[error]:init_password:on");
      lcd.clear();  // 清屏
      lcd.setCursor(0, 0);
      lcd.print("Press the '*' key");
      lcd.setCursor(0, 1);
      lcd.print("[error]:init...");
      Failure_function();
      ergodic = 10;
      goto init_errors;
    }

    BT.println("Enter the password in '3S'");
    BT.println("____________________________");
    BT.println("Please enter a selection:");
    BT.println(">'1'-Open the door");
    BT.println(">'2'-Change password");
    
  } //只让执行一遍,否则重复打印
  /****************************/
  ergodic = 0;


  //串口开门
  while (BT.available())
  {
    Strand_door();
    ergodic = 10;
    delay(2500);
  }

  auxiliary = keypad.getKey();
  if ((auxiliary != NO_KEY) && auxiliary == '#')
  { //开始

    Serial.println("Start InPassword");
    delay(20);

Cancel_pd:

    lcd.clear();  // 清屏
    lcd.setCursor(0, 0);
    lcd.print("#Key in password");   //输入密码
    lcd.setCursor(0, 1);
    lcd.print("*Key change password");  //改密码
    Serial.println("[state]:Input password");

    while (1)
    {
      auxiliary = keypad.getKey();

      if ((auxiliary != NO_KEY) && auxiliary == '*' || auxiliary == '#')
      {
        lcd.clear();  // 清屏
        lcd.setCursor(0, 0);

        /****************'*'*************************/
        if (auxiliary == '*')
        {
          lcd.print("In Original pd:");   //输入密码
          if (GetKey_Value())
            if ((Password_Comparison(Temporary_password, User_Password)))
            { //相等
              Serial.println("[state]:change password..");
              lcd.clear();  // 清屏
              lcd.setCursor(0, 0);
              lcd.print("New password:");  //新密码
              if (GetKey_Value())
              { //获取密钥值
                lcd.clear();  // 清屏
                lcd.setCursor(0, 0);
                lcd.print("Original password:YES");  //改密码
                delay(1900);
                lcd.clear();  // 清屏
                lcd.setCursor(0, 0);
                lcd.print("* Key Determine");  //确定改密码
                lcd.setCursor(0, 1);
                lcd.print("# Key Cancel");  //改密码

                Serial.println("Original password:YES");

                while (1)
                {
                  auxiliary = keypad.getKey();

                  if ((auxiliary != NO_KEY) && auxiliary == '*' || auxiliary == '#')
                  {
                    if (auxiliary == '*')
                    {
                      //密码更改   临时密码,用户密码
                      if (Password_Change(Temporary_password, User_Password))
                      { //密码更改 成功
                        lcd.clear();  // 清屏
                        lcd.setCursor(0, 0);
                        lcd.print("Pd Ce success!");
                        delay(1000);
                        Serial.println("|change password:success!|");
                        goto Cancel_pdok;
                      }//密码更改 失败
                      else
                      {
                        Serial.println("[error]:Acquisition failed");
                        lcd.clear();  // 清屏
                        lcd.setCursor(0, 0);
                        lcd.print("Press the '*' key");
                        lcd.setCursor(0, 1);
                        lcd.print("[error]:Acquisition failed");
                        Failure_function();

                      }//else
                    }//if*
                    else
                      goto Cancel_pd;

                  }//if if(* #)
                }//while...while


              }//IF获取密钥值
              else
              { //获取密钥值失败
                Serial.println("[error]:Acquisition failed");
                lcd.clear();  // 清屏
                lcd.setCursor(0, 0);
                lcd.print("Press the '*' key");
                lcd.setCursor(0, 1);
                lcd.print("[error]:Acquisition failed");
                continue;
              }//获取密钥值失败

            }//if相等
            else
            {
              lcd.clear();  // 清屏
              lcd.setCursor(0, 0);
              lcd.print("OlPassword  error");   //输入密码
              Serial.println("OriginalPassword error");
              continue;
            }


        }//if *
        else if (auxiliary == '#')
        {
          /****************'##########'*********/
          lcd.print("In password:");
          Serial.println("[state]:In_password");
          if (GetKey_Value())
            break;
          else
          {
            lcd.clear();  // 清屏
            lcd.setCursor(0, 0);
            lcd.print("#Key in password");   //输入密码
            lcd.setCursor(0, 1);
            lcd.print("*Key change password");  //改密码
            Serial.println("[state]:Input password");
            continue;
          }
        }
      }

      delay(50);

      //串口开门
      while (BT.available())
      {
        Strand_door();
         ergodic = 10;
        delay(2000);
        
      }

    }//while

Cancel_pdok:

    //密码比较 临时,用户
    if ((Password_Comparison(Temporary_password, User_Password)))
    { //相等
      lcd.clear();  // 清屏
      lcd.setCursor(0, 0);
      lcd.print("Unlocked");
      Serial.println("[state]:Password equality");

      digitalWrite(reach, LOW);
      delay(reac_time);
      digitalWrite(reach, HIGH);
    }
    else
    {
      Serial.println("Passwords are not equal");
      lcd.clear();  // 清屏
      lcd.setCursor(0, 0);
      lcd.print("[warning]:");
      lcd.setCursor(0, 1);
      lcd.print("NOPassword");

      digitalWrite(led_reachErrors, HIGH);
      delay(3000);
      digitalWrite(led_reachErrors, LOW);
      //密码比较 临时,用户
    }//else

    ergodic = 10; //
  }//if 进入条件

}//loop();
/********************************/

bool GetKey_Value()
{
  while (1)
  {
    //获得按键值
    for (ergodic = 0; ergodic < Password_Max;)
    {
      Temporary_password[ergodic] = keypad.getKey();
      //检查获得
      if ((Temporary_password[ergodic] != NO_KEY) && Temporary_password[ergodic] != '#')
      {
        if (Temporary_password[ergodic] == '*')
        {
          ergodic = 10;
          delay(20);
          return true;
        }
        lcd.setCursor(ergodic, 1);
        lcd.print("*");
        ergodic++;
      }
      else if (Temporary_password[ergodic] == '#')
      {
        Temporary_password[ergodic--] = NO_KEY;
        Temporary_password[ergodic] = NO_KEY;
        lcd.setCursor(ergodic, 1);
        lcd.print(' ');
      }

    }//FOR

    if (ergodic == Password_Max)
      return true;
    else
    { //获取失败
      Serial.println("[error]:Acquisition failed");
      lcd.clear();  // 清屏
      lcd.setCursor(0, 0);
      lcd.print("Press the '*' key");
      lcd.setCursor(0, 1);
      lcd.print("[error]:Acquisition failed");
      Failure_function();
      //获取失败
      return false;


    }//else
  }//while
}//GetKey_Value


//失败 函数
void Failure_function()
{
  while (1)
  {
    char nopd;
    digitalWrite(led_errors, HIGH);
    delay(300);
    digitalWrite(led_errors, LOW);
    nopd = keypad.getKey();

    if (nopd != NO_KEY && nopd == Keys[3][0])
    {
      lcd.clear();  // 清屏
      delay(10);
      break;
    }
  }//while
}


void Serial_PortManagement()  //串口管理
{



}



//串口开门
void Strand_door()
{
    lcd.clear();  // 清屏
    lcd.setCursor(0, 0);
    lcd.print("Serial input.....");
  BT_UserPd[0] = Serial_port(); //获取 1-开门 2-改密码
  if (BT_UserPd[0] == '1') //1-开门
  {
    while (BT.available())
    { // 当串口还有信息后
      BT.read();
    }//主要清空缓冲区

    //请输入密码
    BT.println("Please input a password:");
    delay(3500);  //3.5s等待用户输入
    //获取
    for (ergodic = 0; ergodic < Password_Max; ergodic++)
      BT_UserPd[ergodic] = Serial_port();


    delay(5);
    while (BT.available())
    { // 当串口还有信息后
       BT.read();
    }//主要清空缓冲区

    //比较
    if((Password_Comparison(BT_UserPd,BT_Password)))
    {
      BT.println("The password is correct!");

      //相等
    lcd.clear();  // 清屏
    lcd.setCursor(0, 0);
    lcd.print("Unlocked");
    BT.println("[state]:Password equality");

    digitalWrite(reach, LOW);
    delay(reac_time);
    digitalWrite(reach, HIGH);
      
    }
    else
    {
      BT.println("Password error!");

       BT.println("Passwords are not equal");
    lcd.clear();  // 清屏
    lcd.setCursor(0, 0);
    lcd.print("[warning]:");
    lcd.setCursor(0, 1);
    lcd.print("NOPassword");

    digitalWrite(led_reachErrors, HIGH);
    delay(3000);
    digitalWrite(led_reachErrors, LOW);
    }
    /****************************************/
  }

  else if (BT_UserPd[0] == '2') /******2-改密码****/
  {
    /****************************************/
    while (BT.available())
    { // 当串口还有后
       BT.read();
    }//主要清空缓冲区

    BT.println("Enter the original password:");
    delay(3500);//3.5s等待用户输入
    //获取
    for (ergodic = 0; ergodic < Password_Max; ergodic++)
      BT_UserPd[ergodic] = Serial_port();




    delay(5);
    while (BT.available())
    {
      BT.read();
    }//主要清空缓冲区

    //比较
    if((Password_Comparison(BT_UserPd,BT_Password)))
    {

      BT.println("The password is correct!");
      BT.println("Enter new password:");

      delay(3500);//3.5s等待用户输入
      //获取
      for (ergodic = 0; ergodic < Password_Max; ergodic++)
        BT_UserPd[ergodic] = Serial_port();
   
      //替换
  
      if((Password_Change(BT_UserPd,BT_Password)))
      {
        BT.println("Saved,New password:");
        //打印提示
        for (ergodic = 0; ergodic < Password_Max; ergodic++)
          BT.print(BT_Password[ergodic]);
        BT.print("\n");
      }
      else
      {
        //保存失败
        BT.println("Saved failed");
        BT.println("Password is:");
        delay(5);

        //保存失败-给与1-n(n<=Password_Max)
        for (ergodic = 0; ergodic < Password_Max; ergodic++)
          BT_Password[ergodic] = (char)(ergodic+1);
        //打印提示
        for (ergodic = 0; ergodic < Password_Max; ergodic++)
          BT.print(BT_Password[ergodic]);
        BT.print("\n");

        
      }
      delay(5);
      while (BT.available())
      { //主要清空缓冲区
       BT.read();
      }
      //可以优化处: 防止远程改了密码
      return false;
    }
    else
    {
      BT.println("Password error!");
      return false;
    }
  }

  while (BT.available())
  { //主要清空缓冲区
    BT.read();
  }
  //对Arduino的缓存区有心理阴影

  lcd.clear();  // 清屏
}


//串口接收到信息 并返回
char Serial_port()
{
  char serialData;
  //等待缓冲区拿到值
  delay(10);
  if (BT.available())
  { // 当串口接收到信息后
    serialData = BT.read();
  }
  return serialData;
}

Otherfunctions.cpp:

#include"Passwordlock.h"

//改变初始化_临时密码
bool change_init_password(char *init_password)
{
 int temporary;
  char increas='A';
  for(temporary=0;temporary<Password_Max;temporary++)
  {
    *(init_password+temporary)=increas++;  //非语法糖
  }
  if(temporary)
  return true;
  else 
  return false;
}

//密码比较 临时密码,用户密码   strcmp();
bool Password_Comparison(const char  *Temporary_pd,const char  *User_Pd)
{
  int temporary,db=1;
   for(temporary=0;temporary<Password_Max;temporary++)
   {
     db*=((User_Pd[temporary])==(Temporary_pd[temporary]));
   }
  if(db)
   return true;
  else
  return false;
} 

//密码更改   临时密码,用户密码  
bool Password_Change (char *Temporary_pd ,char *use_pdn)
{
  if(Password_Comparison(Temporary_pd,use_pdn))
    return true;
    
  int temporary ;
  for(temporary=0;temporary<Password_Max;temporary++)
  {
    use_pdn[temporary]=Temporary_pd[temporary];
  }
  
  if(Password_Comparison(Temporary_pd,use_pdn))
    return true;
   else
   {
      for(temporary=0;temporary<Password_Max;temporary++)
      {
          use_pdn[temporary]=temporary;
      }
    return false;
   }
}

Passwordlock.h:

#include<Keypad.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h> //引用I2C库
#include <SoftwareSerial.h> 

#define Password_Max 5 //密码长度
//#define Serial_PORTPassworD "8210"
//#define PC_PASSWORD 8210

//改变初始化_临时密码
bool change_init_password(char *);
//密码比较 临时密码,用户密码   strcmp();
bool Password_Comparison(const char *,const char *);
//密码更改   临时密码,用户密码  
bool Password_Change(char *,char *);

本人是自学(而且专业还不是这方面QAQ).原创内容--转载请务必说明!!

说实话还挺简单的,就是蓝牙RX(0)通讯耗了时间,还有Arduino IDE 真的不好用,个人.用的是vscode.

后续会发Windows cmd下贪吃蛇,连点器,俄罗斯方块……

个人邮箱:Starry_night_mc@outlook.com

有BUG反馈.

原创内容--转载请务必说明!

上一篇:Arduino IDE 搭建 ESP8266 开发环境及项目演示


下一篇:ADP-L610-Arduino