IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于Arduino的无接触式智能门锁(RFID和蓝牙开锁) -> 正文阅读

[嵌入式]基于Arduino的无接触式智能门锁(RFID和蓝牙开锁)

一、简单介绍

本项目基于Arduino开发,支持刷卡(复旦卡)和蓝牙串口密码发送两种方式,支持舵机和继电器(可接电磁锁等)两种开锁方式。详情见代码,代码注释很全的。

文章末尾附源程序、库文件、3D打印外壳模型链接

蓝牙开锁:

  1. 连接蓝牙
  2. 打开手机蓝牙串口助手
  3. 发送密码,初始密码为:‘123456’
  4. 舵机状态发送第一次开锁,再发送一次闭锁
  5. 电磁继电器发送一次开锁,5秒后自动关锁

RF522开锁:

????????先将卡片序列号写入程序,方法如下:

  • 连接硬件,烧录程序
  • 打开串口窗口
  • 将卡放在RF522模块识别区
  • 串口打印出卡号
  • 将16进制卡号写入程序中,方法参考示例
  1. 将卡片快速放在RF522模块上,然后快速取开,放置时间过长会导致反复开关锁,上方读卡号一样
  2. 舵机状态放置第一次开锁,再放置一次闭锁
  3. 电磁继电器放置一次开锁,5秒后自动关锁

支持蓝牙串口改密码:

  1. 连接蓝牙
  2. 打开手机蓝牙串口助手
  3. 发送改密码的高级指令,程序默认:‘1357924680’,不含引号
  4. 串口返回值后,按指示操作
  5. 切记,改密码期间,每次输入有效时间为5秒,否则弹出超时警告,然后退出改密码程序。

温馨提示:

  1. 因为舵机电源线加了电磁继电器,所以空闲状态下舵机是可以转动的,当然可以不接电磁继电器,不影响使用
  2. 蓝牙和RF522模块可以同时使用,不会冲突
  3. 每次设备重启后会重置密码
  4. 未知原因,设备长期通电,RF522模块会失效(可能是休眠了),但蓝牙正常
  5. 可以修改蓝牙模块的名字和初始连接密码,详见其他相关文章
  6. 所有密码只支持数字,但不限位数,(不建议太长,容易报错)

需要硬件:

Arduino UNO开发板、RF522读写模块、HC-05蓝牙模块、单路高电平触发继电器、舵机(或单路继电器、电磁锁)。

如果使用大舵机,需要5-9V电源、或两节18650电池(及电池仓)。

二、硬件

接线图见程序

三、程序

/*
    本程序实现通过蓝牙串口发送密码和刷卡两种方式实现无接触式开锁,目前支持两种锁,第一种可以通过驱动舵机实现自动开锁,可以用于改装旧门锁,
    第二种是使用继电器,可以驱动电磁锁等,适用于进行演示。
    该程序目前运行良好,经过检验,但仍有部分小小的bug,比如说长时间运行,RF522模块就会无法使用,复位后便可恢复正常。
    程序注释了每隔三分钟自动断开蓝牙的那一部分。
    程序默认使用舵机开锁。
    舵机旋转角度:180.
    建议舵机独立供电,只需共地。
*/
/*******************************************************************************
     * 接线定义如下

     * 继电器     Arduino
     * IN1       2              控制继电器接通舵机电源,高电平有效
     * IN2       3              控制继电器断开蓝牙电源,高电平有效

     * BT                       接蓝牙,蓝牙模块,正常使用
     * TDX       4
     * RXD       5
     * 
     * OUT                      接舵机,用于控制舵机,程序默认使用该方式开锁
     * OUT/IN    6
     * 
     * IN                       按键开锁,预留通道,暂未使用
     * IN        7
     * 
     * OUT                      连接继电器,用于控制电磁锁等,程序默认注释
     * OUT/IN    8
     * 
     * RFID                     接RFID模块
     * RST       9
     * SDA(SS)   10
     * MOSI      11
     * MISO      12
     * SCK       13
 *****************************************************************************/
#include<SoftwareSerial.h>               //蓝牙头文件
//#include<MsTimer2.h>                    //定时器库的头文件
#include<SPI.h>                          //SPI通信头文件
#include<MFRC522.h>                      //RFC522模块头文件

#define SS_PIN 10
#define RST_PIN 9

SoftwareSerial BT(4,5);                  //定义蓝牙口
//unsigned long BTOn=5000,BTOff=180000;  //定义蓝牙中断的时间长度,每180秒重置一次
//int BTStatus;                          //定义蓝牙的状态,HIGH or LOWm
MFRC522 rfid(SS_PIN, RST_PIN);           // Instance of the class
MFRC522::MIFARE_Key key; 

byte nuidPICC[4];

String str;                              //定义密码变量
String str1;
String str2;
String str3;

int servopin=6;                        //设置舵机驱动脚到数字口6
int myangle;                           //定义角度变量
int pulsewidth;                        //定义脉宽变量
int val1;                              //定义密码储存变量
int val2;
int val3=0;
int val4;
int i;

void servopulse(int servopin,int myangle)//定义一个脉冲函数,用来模拟方式产生PWM值
{
  pulsewidth=(myangle*11)+500;           //将角度转化为500-2480 的脉宽值
  digitalWrite(servopin,HIGH);           //将舵机接口电平置高
  delayMicroseconds(pulsewidth);         //延时脉宽值的微秒数
  digitalWrite(servopin,LOW);            //将舵机接口电平置低
  delay(20-pulsewidth/1000);             //延时周期内剩余时间
}

void setup()
{
  pinMode(2,OUTPUT);                      //定义舵机电源电平
  digitalWrite(2,LOW);
//  pinMode(3,OUTPUT);                    //定义蓝牙状态
//  digitalWrite(3,LOW);
//  BTStatus=LOW;
  pinMode(8,OUTPUT);
  digitalWrite(8,HIGH);                   //继电器拉高为关,拉低为开
  pinMode(servopin,OUTPUT);               //设定舵机接口为输出接口
  Serial.begin(9600);                     //设置波特率为9600
  SPI.begin();                  // Init SPI bus
  rfid.PCD_Init();              // Init MFRC522 

  for (byte i = 0; i < 6; i++)
  {
    key.keyByte[i] = 0xFF;
  }

  Serial.println(F("This code scan the MIFARE Classsic NUID."));
  Serial.print(F("Using the following key:"));
  
  printHex(key.keyByte, MFRC522::MF_KEY_SIZE);  
//*************************************************************
  str3=123456;                            //定义初始密码,只能是数字
//**************************************************************
  Serial.println("UNO is ready");         //串口打印状态
  Serial.println("RFID is ready");
  Serial.println("servo=o_seral_simple ready" ) ;
  BT.begin(9600);                         //蓝牙打印状态
  BT.println("UNO is ready!");
  BT.println("BT is ready!");
  BT.println("RFID is ready");
  BT.println("servo=o_seral_simple ready" ) ;
}

void loop()
{
  //蓝牙部分
  if (BT.available())                               //判断蓝牙串口是否有字符
  {
     while (BT.available() > 0)
      {
        val1 = BT.read();                           //将蓝牙串口的数值读取出来
        if (isDigit(val1))
        {
          str += (char)val1;
        }
        val1 = 0;
        delay(2);
      }
      Serial.println(str);
      /*************************
      *以下代码为蓝牙密码修改代码
      *默认隐藏,激活密码为
      *1357924680
      *只能是数字
      *进入密码修改界面后,请在10秒内输入回答
      *否则就会退出密码修改状态
      *蓝牙串口打印中文时,会出现乱码情况
      ************************/
      if(str=="1357924680")
      {
        str="";
        Serial.println("The page for changing the Bluetooth password is displayed");
        Serial.println("Enter '1' to change the password and '0' to exit");
        BT.println("The page for changing the Bluetooth password is displayed");
        BT.println("Enter '1' to change the password and '0' to exit");
        delay(5000);
        val1 = BT.read();
        Serial.println(val1);
         if (isDigit(val1))
         {
          str += (char)val1;
         }
        val1 = 0;
        delay(500);
        if(str=="1")
        {
          str="";
          str1="";
          str2="";
          Serial.println("Please enter your password:");
          BT.println("Please enter your password:");
          delay(5000);
          while(BT.available() > 0)
          {
            val1=BT.read();
            if (isDigit(val1))
            {
              str1 += (char)val1;
            }
            val1=0;
            delay(10);
           }
            delay(500);
            Serial.println(str1);
            Serial.println("Please enter your password again:");
            BT.println("Please enter your password again:");
            delay(5000);
            while(BT.available() > 0)
            {
              val4=BT.read();
              if (isDigit(val4))
              {
                str2 += (char)val4;
              }
              val4=0;
              delay(500);
              Serial.println(str2);
            }
            if(str1==str2)
            {
              Serial.println("The password is successfully changed. Exit 5 seconds later");
              BT.println("The password is successfully changed. Exit 5 seconds later");
              str3=str1;
              delay(5000);
            }
            else if(str1!=str2)
            {
              Serial.println("Password change failed!! Two different passwords!! Quit in 5 seconds!!");
              BT.println("Password change failed!! Two different passwords!! Quit in 5 seconds!!");
              delay(5000);
            }
          }

        else if(str=="0")
        {
          Serial.println("You have quit password change!");
          BT.println("You have quit password change!");
        }
        else
        {
          Serial.println("Timeout, exit password change interface!!");
          BT.println("Timeout, exit password change interface!!");
        }

      }
      /************************
      *以下为开锁程序
      *前部分为继电器程序
      *后部分为舵机程序
      *使用一个时,请注释另一个程序
      ************************/
      else if(str == str3)
    {
      /*
      //继电器开锁方式,可以接电磁锁
      digitalWrite(8,LOW);
      Serial.println("已开锁");
      BT.println("已开锁");
      delay(3000);
      digitalWrite(8,HIGH);
      Serial.println("已闭锁");
      BT.println("已闭锁");
      */
      str = "";
      

      //舵机
      //舵机程序默认初始位置为开锁状态
      if(val3==0)
      {
        digitalWrite(2,HIGH);
        delay(500);
        val2=0;
        val3=1;
        for(i=0;i<=50;i++) //产生PWM个数,等效延时以保证能转到响应角度
        {
          servopulse(servopin,val2);//模拟产生PWM
        }
        digitalWrite(2,LOW);
        BT.println("Open the door");
      }
      else if(val3==1)
      {
        digitalWrite(2,HIGH);
        delay(500);
        val2=180;
        val3=0;
        for(i=0;i<=50;i++) //产生PWM个数,等效延时以保证能转到响应角度
        {
          servopulse(servopin,val2);//模拟产生PWM
        }
        digitalWrite(2,LOW);
        BT.println("close the door");
      }
    }
      else str="";
  }
  //RFID部分
  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
  if ( ! rfid.PICC_IsNewCardPresent())
    return;
  
  // Verify if the NUID has been readed
  if ( ! rfid.PICC_ReadCardSerial())
    return;
  
  Serial.print(F("PICC type: "));
  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
  Serial.println(rfid.PICC_GetTypeName(piccType));
  
  // Check is the PICC of Classic MIFARE type
  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&  
    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
    Serial.println(F("Your tag is not of type MIFARE Classic."));
    return;
  }
  //下面为卡号,目前无法读取加密卡,卡号会从串口打印出来
  if (
//下面两行代码中不同的位置即使要修改的卡号‘00’‘FF’
      (rfid.uid.uidByte[0] == 0x00 && rfid.uid.uidByte[1] == 0x00 && rfid.uid.uidByte[2] == 0x00 && rfid.uid.uidByte[3] == 0x00)||
      (rfid.uid.uidByte[0] == 0xFF && rfid.uid.uidByte[1] == 0xFF && rfid.uid.uidByte[2] == 0xFF && rfid.uid.uidByte[3] == 0xFF)
    ) 
  {
    Serial.println(F("A card has been detected."));
    if(val3==0)
      {
        digitalWrite(2,HIGH);
        delay(500);
        val2=0;                     //舵机旋转角度
        val3=1;
        for(i=0;i<=50;i++)          //产生PWM个数,等效延时以保证能转到响应角度
        {
          servopulse(servopin,val2);//模拟产生PWM
        }
        digitalWrite(2,LOW);
        BT.println("Open the door");
      }
    else if(val3==1)
    {
      digitalWrite(2,HIGH);
      delay(500);
      val2=180;
      val3=0;
      for(i=0;i<=50;i++) //产生PWM个数,等效延时以保证能转到响应角度
      {
        servopulse(servopin,val2);//模拟产生PWM
      }
      digitalWrite(2,LOW);
      BT.println("close the door");
    }
  }
  Serial.println(F("The NUID tag is:"));
  Serial.print(F("In hex: "));
  printHex(rfid.uid.uidByte, rfid.uid.size);
  Serial.println();
  Serial.print(F("In dec: "));
  printDec(rfid.uid.uidByte, rfid.uid.size);
  Serial.println();    

  /*
//以下为蓝牙自动断开的程序  
  unsigned long nowtime=millis();   //获取当前的系统运行时间长度
  if(BTStatus==LOW)              //如果当前蓝牙状态为AT,则执行该程序
  {
    if(nowtime>BTOn)              //检测系统运行时间长度是否到
    {
      BTOn=nowtime;               //记录当前时间长度,第一次为500ms,赋值给ledOn
      BTOff=nowtime+5000;         //计算出下一次led灯变化的时刻,第一次运行程序时应该在1000ms时关灯
      digitalWrite(3,HIGH);        //关掉蓝牙AT模式
      BTStatus=HIGH;               //记录当前led灯状态,下一次使用     
    } 
  }

  else{       
        if(nowtime>BTOff)
        {   
        BTOff=nowtime;
        BTOn=nowtime+180000;
        digitalWrite(3,LOW);
        BTStatus=LOW;
        }
    }
    */
}

//读卡程序,勿动
void printHex(byte *buffer, byte bufferSize)
{
  for (byte i = 0; i < bufferSize; i++)
  {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

void printDec(byte *buffer, byte bufferSize)
{
  for (byte i = 0; i < bufferSize; i++)
  {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], DEC);
  }
}

如有问题请留言,看到后必会答复。

附源程序、库文件、3D打印外壳模型

基于Arduino的智能无接触式门禁系统-嵌入式文档类资源-CSDN文库icon-default.png?t=M0H8https://download.csdn.net/download/m0_56219648/77514315

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-01-24 11:03:47  更:2022-01-24 11:05:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:30:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码