带联网功能的RFID宿舍门禁(五)-项目总结_esp8266 读取id卡-程序员宅基地

技术标签: 单片机  

文章首发及后续更新:https://mwhls.top/1075.html
新的更新内容请到mwhls.top查看。
无图/格式错误请到上方的文章首发页面查看。

带联网功能的RFID宿舍门禁项目目录

Github项目地址

效果展示视频

http://pan-yz.chaoxing.com/preview/showpreview_536535694800277504.html?v=1605849878000

完成效果

舵机转动:收到转动信号后,舵机正转180°,后逆转180°复原。

读卡转动舵机:RC522读卡器读到已知卡时,会向舵机发送转动信号。

联网控制舵机:ESP8266启动wifi后,使用任意带无线网卡的主机连接到ESP8266Web网络后,打开192.168.4.1后,可进入舵机控制页面,点击控制键后,可向舵机发送转动信号。

未知卡ID读取:将nano板连接至电脑,可显示串口信息后,将未知的卡放在读卡器上,可输出卡ID。

新卡添加:将卡ID加入nano代码的userCard数组中,再将USER_NUM加一,即可添加新卡,可添加校园卡并正常刷卡转动。

不足与改进方向

舵机环形转动,拉动宿舍门栓时会转到一个地方卡主,即因为不能平行拉动,无法正常拉动门栓,于是换了一栋楼尝试。
舵机力量太小,在另一栋楼又无法拉动门栓。
改进方向:改用平移的舵机,或使用拉力更大的舵机。

RC522质量差,在使用时,第一片RC522可正常转动,但一天后损坏,
而后又买了一片RC522,在示例程序中也无法正常使用,只能读三次卡后,转动一次舵机,然后只能重启后才能继续读卡。
但wifi模块始终正常运行。
改进方向:更换读卡芯片,或换一家质量好的店铺。

电源使用小米20000毫安微电流充电宝,价格将近整套材料三倍。
改进方向:使用电池供电。

材料及费用

除自带的充电宝作为电源外,零件理论共44.6元,但实际使用中,RC522坏了一块,于是重新购买,再扣去红包折扣,实际花费44.82元。
当然,如果直接用电脑,也是不用电源的。

名称 用途 数量 价格/元
Arduino Nano V3 及配套数据线 开发板 1 16.7
MFRC522 RFID读卡器 1 4.8
NodeMCU(CH340串口) 及配套数据线 ESP8266模块 1 14.8
SG90 舵机 1 5.1
母对母杜邦线 导线 13 1.6
公对公杜邦线 导线 3 1.6
支持微电流的两万毫安小米充电宝 电源 1 -
连线
Arduino(引脚) NodeMCU(引脚) RC522(顺序) SG90(颜色)
GND GND
A4 D1
A5 D2
D9 RST (2)
D10 SDA (8)
D11 MOSI (6)
D12 MISO (5)
D13 SCK (7)
3V3 3.3V (1)
GND GND (3)
5V 5V(红)
D8 PWM信号(黄)
GND GND (棕)
Arduino Nano代码及功能介绍

Arduino 1.8.13
开发板:Arduino Nano
处理器:ATmega328P (Old Bootloader)

代码功能介绍:

基于MFRC522.h提供的实例库,实例库提供了寻卡、卡类型识别、卡验证、防碰撞等基本功能,
加入了卡的存储管理数组userCard,用于存储卡ID的十进制数据。
加入了舵机控制函数,收到信号后,控制舵机转动180°后,回转180°回到原位,舵机使用脉冲控制替换了舵机库控制,因此不限于特定引脚发送信号。
加入了读特定卡后舵机转动功能,读到卡后,与userCard中数据对比,若相同,则向舵机发送转动信号。
加入了读未知卡后串口输出卡ID功能,将卡ID添加至userCard数组后,将USER_NUM加一,即可添加新卡。
加入了I2C通信函数,NodeMCU板通过I2C通信,将信号传输到Nano版,验证信号后,向舵机发送转动信号。

/* 作者:MWHLS,主页MWHLS.TOP
 * 链接:http://mwhls.top/?p=1075
 * 因为使用的不是SERVO.H库,舵机的PWM控制端口并不局限于9/10两个端口,且也不局限于仅控制两个舵机。
 * 通行卡的存储使用二维数组,将卡的UID转为十进制保存。
 * 卡的对比使用for函数遍历二维数组,对比UID是否相同。
 * 舵机启动由舵机控制变量servoRun控制,若值为1,则启动,其余不运行。
 * 接受到NodeMCU传来的信号时,舵机控制变量置1。
 * 发现通行卡时,舵机控制变量置1。
 * 参考文章:
 * 网页控制:https://blog.csdn.net/qq_46292418/article/details/106605366
 * I2C通信:https://blog.csdn.net/qq_44506730/article/details/90578507
 * RC522读卡:https://blog.csdn.net/leytton/article/details/73480974
 * 舵机控制:https://blog.csdn.net/sss_369/article/details/52894347
 */ 

#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h>              //使用Wire.h进行I2C通信

#define SS_PIN 10
#define RST_PIN 9
#define SERVO_PIN 8
#define USER_NUM 3

byte servoRun = 0;              // 舵机控制变量。
MFRC522 rfid(SS_PIN, RST_PIN);  // 实例化类
byte userCard[USER_NUM][4] = {  // 通行卡存储数组。
  {28,   184,  119,  33},
  {249,  231,  71,   179},
  {109,  242,  234,  235}
};
 
void setup() { 
  Serial.begin(9600);           // 波特率设置
  SPI.begin();                  // 初始化SPI总线
  rfid.PCD_Init();              // 初始化 MFRC522 
  pinMode(SERVO_PIN, OUTPUT);   // 舵机控制端口。
  Wire.begin(8);                // 设置与NodeMCU的通信I2C端口。
  Wire.onReceive(receiveEvent); // 信号接受处理。
}
 
void loop() {
  if(servoRun == 1){            // 舵机运行变量若为1,则运行。
    servoControl();             // 舵机控制函数。
  }
  
  if ( ! rfid.PICC_IsNewCardPresent()) return;       // 找卡
  if ( ! rfid.PICC_ReadCardSerial())   return;       // 验证NUID是否可读
  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&  // 检查是否MIFARE卡类型
    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
    Serial.println("Can identify this card!");
    return;
  }

  byte i;
  for (i=0; i<USER_NUM;  i++){    // 判断卡是否为通行卡。
    byte i2;
    for(i2=0;  i2<4; i2++){       // 遍历userCard中所有卡。
      if(rfid.uid.uidByte[i2] != userCard[i][i2]) break;  
    }                             // break时,表示此卡不是通行卡。
    if(i2 == 4){                  // i2为4,表示此卡的四位值都验证通过。
      Serial.println("Find an accessful card.");  // 输出成功信息。
      servoRun = 1;               // 将开门变量置1。
      break;                      // 已找到通行卡,跳出循环。
    }
  }
  if(i==USER_NUM){                // 若i等于通行用户数量,则上层循环未找到通行卡。
    Serial.print("Find a unknown card, its uid:");
    for(i=0;  i<4;  i++){         // 输出此卡UID,便于后期新增通行卡。
      Serial.print(rfid.uid.uidByte[i], DEC);
      Serial.print(" ");
    }
    Serial.println();
  }
  
  rfid.PICC_HaltA();              // 使放置在读卡区的IC卡进入休眠状态,不再重复读卡
  rfid.PCD_StopCrypto1();         // 停止读卡模块编码

}

void servoControl(){              // 舵机控制函数。
  Serial.println("Servo run!");   // 函数运行输出标识。
  servoPulse(0);                  // 舵机转至0度。
  delay(1000);                    // 等待舵机运转。
  servoPulse(180);                // 舵机转至180度。
  servoRun = 0;                   // 舵机运行变量置零。
}

void servoPulse(int myangle)      // 定义一个脉冲函数,作者:https://blog.csdn.net/sss_369/article/details/52894347
{
  int pulseWidth=(myangle*11)+500;// 将角度转化为500-2480 的脉宽值
  digitalWrite(SERVO_PIN,HIGH);   // 将舵机接口电平至高
  delayMicroseconds(pulseWidth);  // 延时脉宽值的微秒数weimiao
  digitalWrite(SERVO_PIN,LOW);    // 将舵机接口电平至低
  delay(20-pulseWidth/1000);
}

void receiveEvent(int howMany){   // 定义接受联网信息函数,参考:https://blog.csdn.net/qq_44506730/article/details/90578507
  while(0<Wire.available()){      
    char c = Wire.read();
    if (c == '1')  servoRun = 1;  // 如果传入数据为1,则舵机运行变量置1。
    Serial.println("Receive an access sign from ESP8266.");  
  }
}
NodeMCU代码及功能介绍

Arduino 1.8.13
开发板:NodeMCU 1.0
其余设置默认。

代码功能介绍:

NodeMCU通电后自动运行代码,
将使用AP模式开启一个ESP8266Web的wifi,
并建立一个简单网页,
网页中有一个基于I2C通信的按钮,在按下后,NodeMCU会向Nano板发送信号。
将NodeMCU与主机连接,监听串口信息,在wifi开启后,串口会输出wifi相关信息,包括wifi名称,wifi密码以及控制页面地址。

/* 作者:MWHLS,主页MWHLS.TOP
 * 链接:http://mwhls.top/?p=1075
 * 通过主机连接上ESP8266热点,进入通信网址,点击CLICK按钮后,
 * 一个消息会使用I2C通信传输给Arduino,这个消息会触发舵机转动。
 * 参考文章:
 * I2C通信:https://blog.csdn.net/qq_44506730/article/details/90578507
 * 网页控制:https://blog.csdn.net/qq_46292418/article/details/106605366
 */
#include <ESP8266WiFi.h>            // 本程序使用 ESP8266WiFi库
#include <ESP8266WebServer.h>       // ESP8266WebServer库
#include <Wire.h>                   // 使用Wire.h进行I2C通信

ESP8266WebServer esp8266_server(80);// 建立ESP8266WebServer对象,对象名称为esp8266_server
                                    // 括号中的数字是网路服务器响应http请求的端口号
                                    // 网络服务器标准http端口号为80,因此这里使用80为端口号
#define WIFISSID "ESP8266Web"       // 设定ESP8266 wifi名称
#define WIFIPSSD "123456789"        // 设定wifi密码
 
void setup(void){
  Serial.begin(9600);               // 启动串口通讯
  Wire.begin(D1,D2);                // I2C通信端口
  setAP();                          // 设定AP模式,并建立热点。
  
//--------"启动网络服务功能"程序部分开始--------           // 此部分为程序为本示例程序重点1
  esp8266_server.begin();                             // 详细讲解请参见太极创客网站《零基础入门学用物联网》
  esp8266_server.on("/", HTTP_GET, handleRoot);       // 第3章-第2节 ESP8266-NodeMCU网络服务器-1
  esp8266_server.on("/CLICK", HTTP_POST, handleClick);// 处理用户点击消息。
  esp8266_server.onNotFound(handleNotFound);          // 404处理。
//--------"启动网络服务功能"程序部分结束--------
  Serial.println("HTTP esp8266_server started");      // 告知用户ESP8266网络服务功能已经启动
}
 
void loop(void){
  esp8266_server.handleClient();                      // 处理http服务器访问
}
                                                                          
void setAP(){
  WiFi.mode(WIFI_AP);                                 // 设定ESP8266的AP模式
  WiFi.softAP(WIFISSID,WIFIPSSD);                     // 设定ESP8266热点
  Serial.printf("Success!\nWIFISSID:  %s \nWIFIPSSD:  %s \nControlWeb:  ", WIFISSID, WIFIPSSD);
  Serial.println(WiFi.softAPIP());                    // 接上行,输出WIFI信息与通信网址。
}

void handleRoot() {                                   // 处理网站根目录“/”的访问请求 
  esp8266_server.send(200, "text/html", "<form action=\"/CLICK\" method=\"POST\"><input type=\"submit\" value=\"CLICK\"></form>");
}

void handleClick(){                                   // 点击消息处理函数
  Serial.println("Click.");                           
  clickTransmission();                                // 传输点击消息到Arduino板。
  esp8266_server.sendHeader("Location","/");          // 跳转回页面根目录
  esp8266_server.send(303);                           // 发送Http相应代码303 跳转  
}

void clickTransmission(){                             // 点击消息传输函数
  Wire.beginTransmission(8);                          // 开始传输
  Wire.write('1');                                    // 传 1 至Arduino版
  Wire.endTransmission();                             // 结束传输
  Serial.println("Click transmiss success.");         // 输出成功信息
}
 
// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){                                        // 当浏览器请求的网络资源无法在服务器找到时,
  esp8266_server.send(404, "text/plain", "404: Not found");   // NodeMCU将调用此函数。
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/asd123pwj/article/details/109962577

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法