ESP8266 CH340创建NFC+网络服务器智能门禁
硬件部分
ESP8266串口wifi模块 CH340
RFID-RC522射频IC卡感应模块读卡器
MG995金属标准舵机 360度
辅件(电脑,杜邦线,能传输数据的microUSB,IC卡或ID卡)
设备接口描述
ESP8266
RFID-RC522
MG995金属标准舵机
准备
驱动下载
esp8266 CH340驱动下载链接
https://sparks.gogo.co.nz/ch340.html
无脑安装
- 检查插入的USB线是否有接收到?
- 检查是否检测到端口?
答:
- USB插入是否有提示设备被插入(最直接的判断:听到叮咚声)
- 若安装好驱动,打开设备管理器,查看COM口号。记住COM口号(没有显示就是没有安装好,确定装完驱动后,没有显示就试试重启电脑并插拔一下数据线或者换根数据线)
环境
下载Mixly(米思齐)、arduino
采用Mixly(米思齐)辅助编程。arduino作为主编译器。(本来想用vs code来写的,PlatformIO这个插件的环境给我配烂了)
arduino环境参照 http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/nodemcu-arduino-ide/
添加开发板管理网址
http://arduino.esp8266.com/stable/package_esp8266com_index.json
接线
RFID-RC522与ESP8266接线
MG995金属标准舵机 360度与ESP8266接线
就三根线,
GND------GND
3V---------3V
PWM-----D8(GPIO15)
- 3V和GND找到ESP8266的对应引脚插上,怎么接线方便怎么来
开发
ℹ️ 小测试 ESP8266 + RFID-RC522
首先,利用RC522检测我们手中的ID/IC卡,获取卡号,以便后续需要通过记录的卡控制。
从米思齐得知,SDA和RST能使用的引脚有10个,而其他的SCK、MOSI、MISO似乎只能用固定的14端口、13端口、12端口
分析代码
引入了#include <SPI.h> #include <MFRC522.h>
两个库
然后MFRC522 rfid(16, 2);
对应的就是SDA和RST
剩下的就是一些逻辑代码,注册和检测是否为新卡,后面直接CV
接着输出卡号
至此,上传,使用串口监视器查看获取的卡号,复制保存起来。如遇到卡号有存在空格也需要将它一并选上复制。
这个小测试的目的是:获取IC/ID卡号,同时测试RFID-RC522能否正常工作
ℹ️ 小测试 ESP8266 + MG995金属标准舵机 360度
- ℹ️ 小小测试_1 直接上传控制MG995金属标准舵机
首先是用到了#include <Servo.h>
库
使用.write(180);
来控制舵机转的角度
开始时用的这个180度的舵机控制,后知后觉的我才发现我买的是360度的呀,怎么只有180度?
而且还转个不停,控制不住呀
经过查阅资料发现,需要使用脉冲时长来控制.writeMicroseconds(1500);
于是改了一下代码
#include <Servo.h>
Servo servo_15;
void setup(){
servo_15.attach(15);
servo_15.writeMicroseconds(1500);
delay(2000);
}
void loop(){
}
能够控制,但是无法调节角度,通过配合delay()
控制时间的变化于是不断实验,得出以下结果
- 补充一下,这里没写如何转动90度,设置舵机为2000脉冲,delay时间延迟设置500ms-800ms,由于我舵机的问题,每次都会转到90度后会过去一点,也就是92°或者93°或者94°,不太准
了解好舵机的转动功能后,开始一点点的加强一下
’
- ℹ️ 小小测试_2 使用网络服务器控制MG995金属标准舵机
思路:网络服务器 - -> 开?关? --> MG995金属标准舵机
类似上图效果
首先是开启一个网络服务器,参照太极创客 http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-nodemcu-web-server/pin-control/* 里面写的很详细,主要用到两个库#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
也参照了大佬的博客
学会搭建好网络服务器后,就是逻辑思路了。
我自己是设计了两个页面,一个是CLOSE.html,一个是OPEN.html
根目录就是CLOSE.html,当点击后就会变成OPEN.html,再点击就是CLOSE.html;如此循环…
因为对web前端熟练,所以改html代码轻而易举
- 我自己写的那份与nfc的合并在一起了,下面会展示完整代码
ℹ️ 完整项目ESP8266 + RFID-RC522 + MG995金属标准舵机 360度
#include <ESP8266WiFi.h> // 本程序使用ESP8266WiFi库
#include <ESP8266WebServer.h>
#include <Servo.h>
#include <MFRC522.h>
#include <SPI.h>
// 基础变量、常量
const char* ssid = "WIFI_NAME"; // 连接WiFi名(此处使用taichi-maker为示例)
// 请将您需要连接的WiFi名填入引号中
const char* password = "PASSWORD"; // 连接WiFi密码(此处使用12345678为示例)
// 请将您需要连接的WiFi密码填入引号中
const char *APssid = "AP_WIFI_NAME";
const char *APpassword = "AP_PASSWORD";
ESP8266WebServer esp8266_server(80);
Servo servo_15;
String mylist[]={"253df900","136ca29f"};
String RC;
MFRC522 rfid(16, 2);
bool s = false;
// ----------------NFC业务服务------------
String MFRC522_ReadCardUID(MFRC522 *_name){
String _CardUID = "";
for (byte _i = 0; _i < _name->uid.size; _i++){
if(_name->uid.uidByte[_i] < 0x10)
_CardUID += "0";
_CardUID += String(_name->uid.uidByte[_i], HEX);
}
return _CardUID;
}
boolean MFRC522_IsNewCard(MFRC522 *_name){
if(!_name->PICC_IsNewCardPresent())
return false;
if(!_name->PICC_ReadCardSerial())
return false;
return true;
}
// -------------网络服务基础业务-----------
// 开 页面代码
const char* open_html = "\
<!DOCTYPE html>\r\n\
<html lang='en'>\r\n\
<head>\r\n\
<meta charset='UTF-8'>\r\n\
<meta name='viewport' content='width=device-width, initial-scale=1.0'>\r\n\
<title>Switch</title>\r\n\
<style>\r\n\
body {\r\n\
background-color: rgb(255, 250, 240);\r\n\
}\r\n\
.box {\r\n\
width: 200px;\r\n\
height: 110px;\r\n\
background-color: rgb(144, 238, 156);\r\n\
opacity:1;\r\n\
border: 4px solid gray;\r\n\
position: absolute;\r\n\
left: 50%;\r\n\
top: 50%;\r\n\
margin-top: -55px;\r\n\
margin-left: -100px;\r\n\
border-radius: 10px;\r\n\
font-size: 70px;\r\n\
font-weight: 500;\r\n\
color: white;\r\n\
outline: none;\r\n\
}\r\n\
</style>\r\n\
</head>\r\n\
<body>\r\n\
<form name='input' action='/CLOSE' method='POST' >\r\n\
<input type='submit' value='Open' class='box'><br>\r\n\
</form>\r\n\
</body>\r\n\
</html>\r\n\
";
// 关 页面代码
const char* close_html = "\
<!DOCTYPE html>\r\n\
<html lang='en'>\r\n\
<head>\r\n\
<meta charset='UTF-8'>\r\n\
<meta name='viewport' content='width=device-width, initial-scale=1.0'>\r\n\
<title>Switch</title>\r\n\
<style>\r\n\
body {\r\n\
background-color: rgb(255, 250, 240);\r\n\
}\r\n\
.box {\r\n\
width: 200px;\r\n\
height: 110px;\r\n\
background-color: rgb(156, 156, 156);\r\n\
opacity:1;\r\n\
border: 4px solid gray;\r\n\
position: absolute;\r\n\
left: 50%;\r\n\
top: 50%;\r\n\
margin-top: -55px;\r\n\
margin-left: -100px;\r\n\
border-radius: 10px;\r\n\
font-size: 70px;\r\n\
font-weight: 500;\r\n\
color: white;\r\n\
outline: none;\r\n\
}\r\n\
</style>\r\n\
</head>\r\n\
<body>\r\n\
<form name='input' action='/OPEN' method='POST' >\r\n\
<input type='submit' value='Open' class='box'><br>\r\n\
</form>\r\n\
</body>\r\n\
</html>\r\n\
";
// 根目录
void handleRoot(){
esp8266_server.send(200,"text/html",close_html);
}
// handleRootOPEN 触发开启功能
void handleRootOPEN(){
esp8266_server.send(200,"text/html",open_html);
esp8266_server.send(303);
Serial.println("已开启");
servoService(true);
}
// handleRootCLOSE 触发关闭功能
void handleRootCLOSE(){
esp8266_server.send(200,"text/html",close_html);
esp8266_server.send(303);
Serial.println("已关闭");
servoService(false);
}
// 404页面
void handleNotFound(){
esp8266_server.send(200,"text/plain","404:Not Found找不到页面");
}
// -------------舵机配置-----------------
void initservo_15(){
servo_15.attach(15,500,2500);
}
void servoService(bool b){
// servo_15.write(90);
// delay(2000);
// servo_15.write(0);
if(b){
servo_15.writeMicroseconds(2000);
delay(1000);
servo_15.writeMicroseconds(1500);
}else{
servo_15.writeMicroseconds(1500);
}
}
// ------------初始化------------------
void setup() {
Serial.begin(9600); // 启动串口通讯
bool STAswitch = true;
bool APswitch = false;
RC = "";
SPI.begin();
rfid.PCD_Init();
if(STAswitch){
Serial.println("------------------STA配置 状态:开启---------------------------------");
WiFi.begin(ssid, password); // 启动网络连接
Serial.print("Connecting to "); // 串口监视器输出网络连接信息
Serial.print(ssid); Serial.println(" ..."); // 告知用户NodeMCU正在尝试WiFi连接
int i = 0; // 这一段程序语句用于检查WiFi是否连接成功
while (WiFi.status() != WL_CONNECTED) { // WiFi.status()函数的返回值是由NodeMCU的WiFi连接状态所决定的。
delay(1000); // 如果WiFi连接成功则返回值为WL_CONNECTED
Serial.print(i++); Serial.print(' '); // 此处通过While循环让NodeMCU每隔一秒钟检查一次WiFi.status()函数返回值
} // 同时NodeMCU将通过串口监视器输出连接时长读秒。
// 这个读秒是通过变量i每隔一秒自加1来实现的。
Serial.println(""); // WiFi连接成功后
Serial.println("Connection established!"); // NodeMCU将通过串口监视器输出"连接成功"信息。
Serial.print("IP address: "); // 同时还将输出NodeMCU的IP地址。这一功能是通过调用
Serial.println(WiFi.localIP()); // WiFi.localIP()函数来实现的。该函数的返回值即NodeMCU的IP地址。
}else{
Serial.println("STA状态:关闭");
}
if(APswitch){
Serial.println("------------------AP配置 状态:开启---------------------------------");
WiFi.softAP(APssid, APpassword);
Serial.print("Access Point: "); // 通过串口监视器输出信息
Serial.println(ssid); // 告知用户NodeMCU所建立的WiFi名
Serial.print("IP address: "); // 以及NodeMCU的IP地址
if(!STAswitch){
Serial.println(WiFi.softAPIP()); // 通过调用WiFi.softAPIP()可以得到NodeMCU的IP地址
}
}else{
Serial.println("AP状态:关闭");
}
Serial.println("------------------网络服务---------------------------------");
esp8266_server.begin();
esp8266_server.on("/",HTTP_GET,handleRoot);
esp8266_server.on("/OPEN",HTTP_POST,handleRootOPEN);
esp8266_server.on("/CLOSE",HTTP_POST,handleRootCLOSE);
esp8266_server.onNotFound(handleNotFound);
Serial.println("初始化舵机");
initservo_15();
Serial.println("进行中...");
}
void loop() {
int num = WiFi.softAPgetStationNum();
if(WiFi.softAPgetStationNum() != num){
num = WiFi.softAPgetStationNum();
Serial.printf("Stations connected to soft-AP = %d\n",num);//显示连入esp8266的设备数量
delay(3000);
}
esp8266_server.handleClient();
// NFC
if(MFRC522_IsNewCard(&rfid)){
RC = MFRC522_ReadCardUID(&rfid);
for (int i = (0); i <= (sizeof(mylist)/sizeof(mylist[0])); i = i + (1)) {
// Serial.println("-----------------------------------");
Serial.println(1);
Serial.println(RC);
Serial.println(mylist[i]);
if (RC == mylist[i]) {
Serial.println("匹配到登记卡");
servoService(true);
}else{
servoService(false);
}
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
}
}
最后
这个项目后面可以增加一个锂电池,然后依据自己的条件设计符合门禁的装配。