文章首发及后续更新:https://mwhls.top/4066.html,无图/无目录/格式错误/更多相关请至首发页查看。
新的更新内容请到mwhls.top查看。
欢迎提出任何疑问及批评,非常感谢!
带联网功能的RFID宿舍门禁
两年后又来了次总结,为什么总结?因为有门课能拿它来扯
项目介绍
涉及技术
- 射频识别技术(Radio-frequency identification, RFID)。
- WiFi 联网。
项目出发点
- 以更低的成本实现项目所需功能。
- 物料成本低。
- 学习成本低。
- 结合 RFID 与联网功能。
设计方向
- 实现一个门禁装置,该门禁装置需要允许学生卡刷卡开门,以及联网控制开门。
- RFID的一个简单应用就是门禁装置,通过刷卡控制舵机转动,舵机拉动门锁。
- 加上联网功能后,手机连上控制设备的WiFi,打开控制网页控制舵机转动,舵机拉动门锁。
实现效果
- RFID: 在感应装置刷录入系统的学生卡后,可控制舵机转动。
- WiFi: 连上 WiFi,登录控制页面后,点击控制按钮,可控制舵机转动。
- 舵机: 舵机转动带动门锁,并打开门锁(实际实现中因舵机动力不足无法完全拉开门锁)。
实现过程
- 选择 RFID 与 WIFI 模块、实现平台、实现语言
- 测试 WIFI 模块与 RFID 模块
- 实现 WIFI 功能
- 实现 RFID 功能
- 融合 WIFI 与 RFID 功能
路径选择
资料收集
- 网上是否有现成或类似的方案?
- 该方案实现效果是否满足需求?
- 该方案所需成本是否可以接受?
确定目标
- 硬件:
- RFID 模块:MFRC522
- WiFi 模块:ESP8266
- 开发板:Arduino Nano V3 CH340G
- 舵机:SG90
- 开发平台:
- 编程语言:
首次实验
实验目的
实验结果
- Arduino 环境配置。
- 实验了 ESP8266 的烧录。
- 学习了 Lua 与 CH340 开发板通信。
测试 WiFi 模块
实验目的
实验材料
ESP8266 |
---|
WiFi 模块 |
|
实验过程
- ESP8266 环境配置
- 环境下载速度慢:
- 用连谷歌的网络下载。
- 更换第三方下载源。
- 使用默认下载,然后用其它地方发布的该文件替换它(文件数量少)。
- ESP8266 建站及开放热点
- 参考网上的代码,搞清楚各函数意义,修改为适用于本实现的代码。
- 测试连接
- 根据代码写好的 WiFi 名与密码,使用手机连接 ESP8266 的热点,并在电脑上通过串口通信查看是否连接正常。
实验代码
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer esp8266_server(80);
#define WIFISSID "ESP8266Web"
#define WIFIPSSD "123456789"
void setup(void){
Serial.begin(115200);
setAP();
esp8266_server.begin();
esp8266_server.on("/", handleRoot);
esp8266_server.onNotFound(handleNotFound);
Serial.println("HTTP esp8266_server started");
}
void loop(void){
esp8266_server.handleClient();
}
void setAP(){
WiFi.mode(WIFI_AP);
WiFi.softAP(WIFISSID,WIFIPSSD);
Serial.printf("Success!\nWIFISSID: %s \nWIFIPSSD: %s \nControlWeb: ", WIFISSID, WIFIPSSD);
Serial.println(WiFi.softAPIP());
}
void handleRoot() {
esp8266_server.send(200, "text/plain", "ESP8266 WEB CONTROL PAGE.\n -mwhls.top");
}
void handleNotFound(){
esp8266_server.send(404, "text/plain", "404: Not found");
}
实验结果
- ESP8266 开放热点并建站后,串口输出相关信息。
- 手机可通过 WiFi 连上 ESP8266,并连接至控制网站。
测试RFID模块
实验目的
实验材料及连线
SG90 9克舵机 | MFRC522 | Arduino Nano V3 CH340G |
---|
拉动门锁 | RFID 模块 | 开发板 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6caYNNGM-1668948818342)(https://s2.loli.net/2022/11/19/dY6JlMwk4hFr5SC.jpg)] | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xVdDid9L-1668948818343)(https://s2.loli.net/2022/11/19/nhprZLk5HwyXsue.jpg)] | [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aW3eCrI7-1668948818343)(https://s2.loli.net/2022/11/19/Je8Y61B3zwfNPp9.jpg)] |
Arduino Nano V3 CH340G | SG90(颜色) | RC522(顺序) |
---|
GND | GND (棕) | |
5V | 5V (红) | |
D8 | PWM信号 (黄) | |
D9 | | RST (2) |
D10 | | SDA (8) |
D11 | | MOSI (6) |
D12 | | MISO (5) |
D13 | | SCK (7) |
3V3 | | 3.3V (1) |
GND | | GND (3) |
实验过程
- 刷卡控制舵机转动。
- 添加学生卡为通行卡。
- 实现刷学生卡开门。
- 读取学生卡的 ID,并创建通行卡数组,将 ID 写入数组。
- 舵机正转反转实现。
- 实现拉动及恢复门锁。
- 正转:拉动门锁。
- 反转:恢复门锁。
实验代码
#include <SPI.h>
#include <MFRC522.h>
#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();
rfid.PCD_Init();
pinMode(SERVO_PIN, OUTPUT);
}
void loop() {
if(servoRun == 1){
servoControl();
}
if ( ! rfid.PICC_IsNewCardPresent()) return;
if ( ! rfid.PICC_ReadCardSerial()) return;
MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
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++){
if(rfid.uid.uidByte[i2] != userCard[i][i2]) break;
}
if(i2 == 4){
Serial.println("Find an accessful card.");
servoRun = 1;
break;
}
}
if(i==USER_NUM){
Serial.print("Find a unknown card, its uid:");
for(i=0; i<4; i++){
Serial.print(rfid.uid.uidByte[i], DEC);
Serial.print(" ");
}
Serial.println();
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}
void servoControl(){
Serial.println("Servo run!");
servoPulse(0);
delay(1000);
servoPulse(180);
servoRun = 0;
}
void servoPulse(int myangle)
{
int pulseWidth=(myangle*11)+500;
digitalWrite(SERVO_PIN,HIGH);
delayMicroseconds(pulseWidth);
digitalWrite(SERVO_PIN,LOW);
delay(20-pulseWidth/1000);
}
实验结果
- RC522 读取到未录入通行数组的卡时,串口会输出对应卡 ID 信息。
- RC522 读取到学生卡时,会触发舵机转动。
- 舵机触发转动后,将正转 180 度,在 1 秒后回转180度。
连接 WiFi 模块与 RFID 模块
实验目的
- 可通过 WiFi 连接至控制网站以转动舵机;也可通过刷学生卡来转动舵机。
实验材料及连线
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1EDh35rl-1668948818343)(https://s2.loli.net/2022/11/19/F78BNYIXUZ6Wcmr.jpg)]
名称 | 用途 | 数量 |
---|
Arduino Nano V3 CH340G 及配套数据线 | 开发板 | 1 |
MFRC522 | RFID 模块 | 1 |
NodeMCU(ESP8266 CH340串口) 及配套数据线 | WiFi 模块 | 1 |
SG90 | 舵机 | 1 |
母对母杜邦线 | 导线 | 13 |
公对公杜邦线 | 导线 | 3 |
支持微电流的两万毫安小米充电宝 | 电源 | 1 |
Arduino Nano V3 CH340G(引脚) | 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 (棕) |
实验过程
- 开发板开启通信端口,接收外部信号。
- WiFi 模块开放热点,并建立可交互网站。
- 与网站交互后,WiFi 模块发送舵机转动信号至开发板,开发板触发舵机转动。
- RC522 读取到学生卡后,开发板触发舵机转动。
实验环境
- 烧录平台:Arduino 1.8.13
- 开发板:NodeMCU 1.0
实验代码 - 开发板
#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h>
#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();
rfid.PCD_Init();
pinMode(SERVO_PIN, OUTPUT);
Wire.begin(8);
Wire.onReceive(receiveEvent);
}
void loop() {
if(servoRun == 1){
servoControl();
}
if ( ! rfid.PICC_IsNewCardPresent()) return;
if ( ! rfid.PICC_ReadCardSerial()) return;
MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
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++){
if(rfid.uid.uidByte[i2] != userCard[i][i2]) break;
}
if(i2 == 4){
Serial.println("Find an accessful card.");
servoRun = 1;
break;
}
}
if(i==USER_NUM){
Serial.print("Find a unknown card, its uid:");
for(i=0; i<4; i++){
Serial.print(rfid.uid.uidByte[i], DEC);
Serial.print(" ");
}
Serial.println();
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}
void servoControl(){
Serial.println("Servo run!");
servoPulse(0);
delay(1000);
servoPulse(180);
servoRun = 0;
}
void servoPulse(int myangle)
{
int pulseWidth=(myangle*11)+500;
digitalWrite(SERVO_PIN,HIGH);
delayMicroseconds(pulseWidth);
digitalWrite(SERVO_PIN,LOW);
delay(20-pulseWidth/1000);
}
void receiveEvent(int howMany){
while(0<Wire.available()){
char c = Wire.read();
if (c == '1') servoRun = 1;
Serial.println("Receive an access sign from ESP8266.");
}
}
实验代码 - WiFi 模块
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Wire.h>
ESP8266WebServer esp8266_server(80);
#define WIFISSID "ESP8266Web"
#define WIFIPSSD "123456789"
void setup(void){
Serial.begin(9600);
Wire.begin(D1,D2);
setAP();
esp8266_server.begin();
esp8266_server.on("/", HTTP_GET, handleRoot);
esp8266_server.on("/CLICK", HTTP_POST, handleClick);
esp8266_server.onNotFound(handleNotFound);
Serial.println("HTTP esp8266_server started");
}
void loop(void){
esp8266_server.handleClient();
}
void setAP(){
WiFi.mode(WIFI_AP);
WiFi.softAP(WIFISSID,WIFIPSSD);
Serial.printf("Success!\nWIFISSID: %s \nWIFIPSSD: %s \nControlWeb: ", WIFISSID, WIFIPSSD);
Serial.println(WiFi.softAPIP());
}
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();
esp8266_server.sendHeader("Location","/");
esp8266_server.send(303);
}
void clickTransmission(){
Wire.beginTransmission(8);
Wire.write('1');
Wire.endTransmission();
Serial.println("Click transmiss success.");
}
void handleNotFound(){
esp8266_server.send(404, "text/plain", "404: Not found");
}
实验结果
- RC522 读取到学生卡时,触发舵机转动。
- RC522 读取到未录入的卡时,串口输出卡 ID。
- 手机连接至 ESP8266 热点后,登录
192.168.4.1
,点击 Click
以触发舵机转动。 - 舵机收到触发信号,先正转 180 度,再回转 180 度。
成果展示
视频及图片
- 没有视频图床,以后想起来再补视频。
- [外链图片转存中…(img-BEG8pHmM-1668948818344)]
材料成本
- 合计 49.75 元,其中 RC522 因为坏了一块重买了,去掉之后只有 44.95 元。
材料 | 用途 | 数量 | 价格 |
---|
RC522 | RFID 模块 | 2 | 4.8 * 2 |
公对公杜邦线 (10cm) | 导线 | 1 | 1.9 |
母对母杜邦线 (30cm) | 导线 | 1 | 1.65 |
NodeMCU(ESP8266 CH340串口) 及配套数据线 | WiFi 模块 | 1 | 14.8 |
SG90 9克舵机 | 舵机 | 1 | 5.1 |
Arduino Nano V3 CH340G 及配套数据线 | 开发板 | 1 | 16.7 |
优点
- 完成了所需功能。
- 成本控制令我满意。
- 学习成本低,生态好,且可直接使用 C 语言实现。
缺点
- 舵机拉力太小,无法拉动门锁,中看不中用。
- RC522 质量太差,第一天正常,第二天就坏了,得刷三次卡才能触发一次,不过还好当时录了视频。