带联网功能的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

智能推荐

JAVA实现Linux网卡绑定_Linux双网卡绑定脚本的方法示例-程序员宅基地

文章浏览阅读209次。linux运维及配置工作中,常常会用到双网卡绑定,少数几台服务器的配置还好,如果是需要配置几十甚至上百台,难免会枯燥乏味,易于出错,我编写了这个双网卡绑定的辅助脚本,可傻瓜式地完成linux双网卡绑定工作,当然,该脚本主要还是用于小批量的系统配置,如需配置大量的服务器,可提取脚本中的bonding函数,稍作修改即可,你值得一试!1.适用范围该shell脚本可在以下linux系统创建多个绑定网卡,用..._java master网卡

2023年华数杯赛题浅析_隔热材料的结构优化控制研究-程序员宅基地

文章浏览阅读2.5k次。为了方便大家跟更好的选题,这里首先对华数杯的三道题目进行简要浅析,分析三个问题未来做题阶段可能遇到的难点,已经可能涉及所需要的数模知识。问题二根据给出的数据建立优化模型,以整体热导率为目标函数,单根A纤维的直径及调整织物的经密、纬密、弯曲角度等作为约束条件进行求解​;问题三,问题二优化模型的延深,引入新的条件进行求解。该题,为纯粹的优化类型题目,因此对于大家的优化模型掌握能力是个考验。与目标样的色差最接近为目标,构建优化模型​,约束条件有色差要求等等;问题四,依旧是问题二三优化模型的深入,寻找。_隔热材料的结构优化控制研究

TCP/IP 端口号大全_ldap端口363-程序员宅基地

文章浏览阅读4.3k次,点赞2次,收藏8次。*备查之用 *本贴连接 http://www.douban.com/group/topic/7647051 1 tcpmux TCP 端口服务多路复用 5 rje 远程作业入口 7 echo Echo 服务 9 discard 用于连接测试的空服务 11 systat 用于列举连接了的端口的系统状态 13 daytime 给请求主机发送日期和时间 17 qo_ldap端口363

【Hyper-V】1.在Windows11启用Hyper-V_win11 hyper-v-程序员宅基地

文章浏览阅读6.7k次,点赞3次,收藏14次。Hyper-V是微软提出的一种系统管理程序虚拟化技术,能够实现桌面虚拟化,让用户在windows系统上以虚拟机的方式使用多个不同的操作系统。_win11 hyper-v

私有化部署-程序员宅基地

文章浏览阅读7.5k次。私有化部署_私有化部署

github action 基于个人项目实践_github action实战-程序员宅基地

文章浏览阅读1.4k次。自动化构建自己的服务_github action实战

随便推点

空间数据分析知识点_geray c-程序员宅基地

文章浏览阅读9.6k次,点赞9次,收藏102次。【转】http://blog.sina.com.cn/s/blog_54388b8301011cxp.html空间数据分析 1. 空间分析:(spatial analysis,SA)是基于地理对性的位置和形态特征的空间数据分析技术,其目的在于提取和传输空间信息,是地理信息系统的主要特征,同时也是评价一个地理信息系统功能的主要指标之一,是各类综合性地学分析模型的基础,_geray c

IntelliJ Idea 常用11款插件(提高开发效率),附优秀主题插件_idea 像西红柿插件-程序员宅基地

文章浏览阅读679次。插件安装方式:新版本IDE安装方式略有不同,不一一赘述1、Background Image Plus这款插件并不能直接提高你的开发效率,但是可以让你面对的IDE不再单调,当把背景设置成你自己心仪的的图片,是不是会感觉很赏心悦目,编码效率会不会因此间接的提高?!使用方法:注意,如果是IDEA版本是2020.1版本以上就不需要再额外装这个插件,这个插件是已经内置安装了。2、Mybatis Log PluginMybatis现在是java中操作数据库的首选,在开发..._idea 像西红柿插件

java ajax实现增删改查,03.bootstrap+Ajax+SSM(maven搭建)实现增删改查-程序员宅基地

文章浏览阅读666次。功能点:分页数据校验ajaxRest风格的URI:使用HTTP协议请求方式的动词,来表示对资源的操作(GET(查询),POST(新增),PUT(修改),DELETE(删除))技术点基础框架-ssm数据库mysql前端框架-bootstrap项目依赖 -Maven分页 -pagehelper逆向工程-Mybatis Generator实现效果添加按钮弹出模态框编辑按钮弹出模态框删除基础环境搭建1)新..._ssmajax删除

Oracle 如何使用时间日期字段计算时间差_oracle sql 查询的日期差8小时-程序员宅基地

文章浏览阅读1k次。Oracle 如何使用时间日期字段计算时间差因为业务需要计算耗时,在检查数据库的时候发现时间是分成两个字段来存储的,日期和时间,字段类型都是字符串。思路:将两个字符串连接起来,通过TO_DATE转换成时间,TO_NUMBER将两个时间差转为数值。得到的结果是以‘天’为单位。TO_NUMBER(TO_DATE((WC.OPERATEDATE || ’ ’ || WC.OPERATETIME),..._oracle sql 查询的日期差8小时

Vuex报错:[vuex] must call Vue.use(Vuex) before creating a store instance.解决方法-程序员宅基地

文章浏览阅读1.2k次。Vuex报错:[vuex] must call Vue.use(Vuex) before creating a store instance._[vuex] must call vue.use(vuex) before creating a store instance.

java中类、对象、实例的关系_java类和实例的关系-程序员宅基地

文章浏览阅读1w次,点赞4次,收藏13次。java中类、对象、实例的关系 (刚刚接触java,难免有许多错误,欢迎指正) java作为面向对象编程语言,作为初学者首先要分清类、对象、实例之间的关系是必要的。 正所谓物以类聚,类就是一些具有某些相同特性的“物”的集合,比如“人”这样的类,每个人都有姓名、年龄、性别等特性。对象就是某一个人,比如说“张三”,“人”这个类是很多的像“张三”、“李四”这样的对象的集合。对象是一个抽象的概念_java类和实例的关系

推荐文章

热门文章

相关标签