话不多说,咱先上图上视频
nfc门锁
使用方法还是很简单的,有当前卡id是刷卡,舵机就会动作。当没有保存当前卡时只需要按一下按钮就可以把当前卡的信息保存到eeprom中,可以实现掉电存储。
必要硬件:nodemcu开发板,rc522模块,舵机,按钮,电源模块,杜邦线若干,还可以添加蜂鸣器或者led灯
硬件接线图esp8266nodemcu连接rc522模块
用arduinoIDE编程,需要下载blinker库,esp8266支持包,mfrc522库。
blinker点灯app界面配置(当然不需要手机控制的可以不用点灯)
下面是包含blinker的代码,后面有不包含blinker的代码,不适用blinker与WiFi可以更加省电。
#include <EEPROM.h>
#include <SPI.h>
#include <MFRC522.h>
#include <BLINKER_PMSX003ST.h>
#include <Servo.h>
#define BLINKER_WIFI
#include <Blinker.h>
char auth[] = "e610c0fae090"; //点灯密钥
char ssid[] = "2-19公共wifi"; //WiFi名称
char pswd[] = "12345678"; //WiFi密码
// 新建组件对象
BlinkerButton Button1("btn-num"); //位置1 按钮 数据键名
BlinkerButton Button2("btn-max"); //位置2 按钮 数据键名
BlinkerSlider Slider1("ser-num"); //实时位置 滑块 数据键名 范围1-180
Servo myservo; //创建电机对象
int ser_num ;
int ser_max ;
#define RST_PIN 5 // 配置针脚
#define SS_PIN 4
MFRC522 mfrc522(SS_PIN, RST_PIN); // 创建新的RFID实例
//RC模块使用了D1.D2.D5.D6.D7
/*************************IO配置**************************/
int Buzzer = 16; //D0(io16)蜂鸣器,提示音,也可以用led
int btn = 15; //D8(io15)按钮,保存门禁卡ID到EEPROM
/*************************数据**************************/
//使用union结构,合并4个byte数据,转换为1个long
union long_byte
{
long long_data;
byte byte_data[4];
};
long_byte lb;
long EEPROM_RFID1 = -1;//EEPROM中保存的门禁卡ID1
long EEPROM_RFID2 = -1;
long EEPROM_RFID3 = -1;
long EEPROM_RFID4 = -1;
long EEPROM_RFID5 = -1;
long EEPROM_RFID6 = -1;
long EEPROM_RFID7 = -1;
long read_RFID = -1; //当前读取到的门禁卡ID
int num ;
void setup()
{
Serial.begin(115200);
Serial.println("");
BLINKER_DEBUG.stream(Serial);
Blinker.begin(auth, ssid, pswd);
EEPROM.begin(1024);
Button1.attach(button1_callback);
Button2.attach(button2_callback);
Slider1.attach(slider1_callback);
Blinker.attachData(dataRead);
myservo.attach(0); //servo.attach():设置舵机数据引脚
myservo.write(10); //servo.write():设置转动角度
ser_num = 100;
ser_max = 100;
//读取EEPROM索引的值 我这里设置了七张卡,不够也可以再加
for (int i = 0; i < 4; i++)
{
lb.byte_data[i] = EEPROM.read(i); //卡1
}
EEPROM_RFID1 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+4); //卡2
}
EEPROM_RFID2 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+8); //卡3
}
EEPROM_RFID3 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+12); //卡4
}
EEPROM_RFID4 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+16); //卡5
}
EEPROM_RFID5 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+20); //卡6
}
EEPROM_RFID6 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+24); //卡7
}
EEPROM_RFID7 = lb.long_data;
num = EEPROM.read(30);
IO_init();
RFID_init();
}
void loop()
{
Blinker.run();
Btn_Event();
RFID_read(); //读卡并做分析处理
}
void button1_callback(const String & state) { //位置1按钮
yunxing();
Blinker.vibrate();
}
void button2_callback(const String & state) { //位置2按钮
BLINKER_LOG("get button state: ", ser_max);
opendoor();
}
void opendoor(void){
read_RFID = -1;
int fromPos;
int toPos;
fromPos = myservo.read();
toPos = 10;
if (fromPos <= toPos){ //如果“起始角度值”小于“目标角度值”
for (int i=fromPos; i<=toPos; i++){
myservo.write(i);
delay (5);
}
} else { //否则“起始角度值”大于“目标角度值”
for (int i=fromPos; i>=toPos; i--){
myservo.write(i);
delay (5);
}
}
Blinker.vibrate();
int i;
for(i =10 ; i<= ser_max ; i++){
myservo.write(i);
delay(5);
}
Button2.text("门锁已打开");
Button2.print("门锁已打开");
Button1.color("#0000FF");
delay(1000);
for(i = ser_max ; i>=10 ; i--){
myservo.write(i);
delay(5);
}
Button2.text("门锁已关闭");
Button2.print("门锁已关闭");
}
void slider1_callback(int32_t value)
{
ser_num = value;
Blinker.delay(100);
BLINKER_LOG("get slider value: ", value);
}
void yunxing(){
int fromPos;
int toPos;
fromPos = myservo.read();
toPos = ser_num;
if (fromPos <= toPos){ //如果“起始角度值”小于“目标角度值”
for (int i=fromPos; i<=toPos; i++){
myservo.write(i);
delay (5);
}
} else { //否则“起始角度值”大于“目标角度值”
for (int i=fromPos; i>=toPos; i--){
myservo.write(i);
delay (5);
}
}
}
void dataRead(const String & data)
{
BLINKER_LOG("Blinker readString: ", data);
Blinker.vibrate();
uint32_t BlinkerTime = millis();
Blinker.print(BlinkerTime);
Blinker.print("millis", BlinkerTime);
}
//监听按钮状态,更换显示状态和值
void Btn_Event()
{
EEPROM.begin(1024);
//io15默认的有下拉,所以要判断是否为高电平
if (digitalRead(btn) == 1)
{
delay(200);
if (read_RFID == -1)
{
Serial.println("当前未读卡");
Di(3);
}
else{
switch(num){
case 0 :
lb.long_data = read_RFID;
EEPROM_RFID1 = lb.long_data;
for (int i = 0; i < 4; i++)
{
EEPROM.write(i, lb.byte_data[i]);
}
num = 1;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID1已保存");
Di(1);break;
case 1 :
lb.long_data = read_RFID;
EEPROM_RFID2 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+4, lb.byte_data[i]);
}
num=2;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID2已保存");
Di(1);
break;
case 2 :
lb.long_data = read_RFID;
EEPROM_RFID3 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+8, lb.byte_data[i]);
}
num=3;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID3已保存");
Di(1);
break;
case 3 :
lb.long_data = read_RFID;
EEPROM_RFID4 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+12, lb.byte_data[i]);
}
num=4;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID4已保存");
Di(1);
break;
case 4 :
lb.long_data = read_RFID;
EEPROM_RFID5 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+16, lb.byte_data[i]);
}
num=5;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID5已保存");
Di(1);
break;
case 5 :
lb.long_data = read_RFID;
EEPROM_RFID6 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+20, lb.byte_data[i]);
}
num=6;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID6已保存");
Di(1);
break;
case 6 :
lb.long_data = read_RFID;
EEPROM_RFID7 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+24, lb.byte_data[i]);
}
num=0;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID7已保存");
Di(1);
break;
}
}
}
}
//初始化IO
void IO_init()
{
//io15默认有硬件下拉,不要使用软件上拉模式
pinMode(btn, INPUT);
pinMode(Buzzer, OUTPUT);
digitalWrite(Buzzer, 0);
}
//蜂鸣器音效
void Di(int a)
{
for (int i = 0; i < a; i++)
{
digitalWrite(Buzzer, 1);
delay(500);
digitalWrite(Buzzer, 0);
delay(100);
}
}
/***********************RFID读卡自定义函数***********************/
//初始化读卡
void RFID_init()
{
SPI.begin(); // SPI开始
mfrc522.PCD_Init(); // 初始化
Serial.println("初始化读卡");
}
//运行读卡
void RFID_read()
{
if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial())
{
return;
}
else
{
read_RFID = RFID_toLong(mfrc522.uid.uidByte);
RFID_Handler(read_RFID);
mfrc522.PICC_HaltA();//停止 PICC
mfrc522.PCD_StopCrypto1(); //停止加密PCD
return;
}
}
//用户ID转换类型
long RFID_toLong(byte *by)
{
long data;
for (int i = 0; i < 4; i++)
{
lb.byte_data[i] = by[i];
}
data = lb.long_data;
return data;
}
//把当前读到卡的ID,对比EEPROM中的ID
void RFID_Handler(long data)
{
Serial.println(data);
if (EEPROM_RFID1 == -1&&EEPROM_RFID2 == -1&&EEPROM_RFID3 == -1&&EEPROM_RFID4 == -1&&
EEPROM_RFID5 == -1&&EEPROM_RFID6 == -1&&EEPROM_RFID7 == -1)
{
Serial.println("当前未设置卡");
Di(3);
}
else
{
if (data == EEPROM_RFID1) {
Serial.println("ID1正确,验证通过");
Di(1);
opendoor(); //开门函数
}
else if(data == EEPROM_RFID2){
Serial.println("ID2正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID3){
Serial.println("ID3正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID4){
Serial.println("ID4正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID5){
Serial.println("ID5正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID6){
Serial.println("ID6正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID7){
Serial.println("ID7正确,验证通过");
Di(1);
opendoor();
}
else
{
Di(2);
Serial.println("ID错误,验证失败");
}
}
}
下面是没有blinker的代码
#include <EEPROM.h>
#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>
Servo myservo; //创建电机对象
int ser_num ;
int ser_max ;
#define RST_PIN 5 // 配置针脚
#define SS_PIN 4
MFRC522 mfrc522(SS_PIN, RST_PIN); // 创建新的RFID实例
//RC模块使用了D1.D2.D5.D6.D7
/*************************IO配置**************************/
int Buzzer = 16; //D0(io16)蜂鸣器,提示音,也可以用led
int btn = 15; //D8(io15)按钮,保存门禁卡ID到EEPROM
/*************************数据**************************/
//使用union结构,合并4个byte数据,转换为1个long
union long_byte
{
long long_data;
byte byte_data[4];
};
long_byte lb;
long EEPROM_RFID1 = -1;//EEPROM中保存的门禁卡ID1
long EEPROM_RFID2 = -1;
long EEPROM_RFID3 = -1;
long EEPROM_RFID4 = -1;
long EEPROM_RFID5 = -1;
long EEPROM_RFID6 = -1;
long EEPROM_RFID7 = -1;
long read_RFID = -1; //当前读取到的门禁卡ID
int num ;
void setup()
{
Serial.begin(115200);
Serial.println("");
EEPROM.begin(1024);
myservo.attach(0); //servo.attach():设置舵机数据引脚
myservo.write(10); //servo.write():设置转动角度
ser_num = 100;
ser_max = 100;
//读取EEPROM索引的值 我这里设置了七张卡,不够也可以再加
for (int i = 0; i < 4; i++)
{
lb.byte_data[i] = EEPROM.read(i); //卡1
}
EEPROM_RFID1 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+4); //卡2
}
EEPROM_RFID2 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+8); //卡3
}
EEPROM_RFID3 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+12); //卡4
}
EEPROM_RFID4 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+16); //卡5
}
EEPROM_RFID5 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+20); //卡6
}
EEPROM_RFID6 = lb.long_data;
for (int i = 0 ; i<4 ; i++ )
{
lb.byte_data[i] = EEPROM.read(i+24); //卡7
}
EEPROM_RFID7 = lb.long_data;
num = EEPROM.read(30);
IO_init();
RFID_init();
}
void loop()
{
Btn_Event();
RFID_read(); //读卡并做分析处理
}
void opendoor(void){
read_RFID = -1;
int fromPos;
int toPos;
fromPos = myservo.read();
toPos = 10;
if (fromPos <= toPos){ //如果“起始角度值”小于“目标角度值”
for (int i=fromPos; i<=toPos; i++){
myservo.write(i);
delay (5);
}
} else { //否则“起始角度值”大于“目标角度值”
for (int i=fromPos; i>=toPos; i--){
myservo.write(i);
delay (5);
}
}
int i;
for(i =10 ; i<= ser_max ; i++){
myservo.write(i);
delay(5);
}
delay(1000);
for(i = ser_max ; i>=10 ; i--){
myservo.write(i);
delay(5);
}
}
//监听按钮状态,更换显示状态和值
void Btn_Event()
{
EEPROM.begin(1024);
//io15默认的有下拉,所以要判断是否为高电平
if (digitalRead(btn) == 1)
{
delay(200);
if (read_RFID == -1)
{
Serial.println("当前未读卡");
Di(3);
}
else{
switch(num){
case 0 :
lb.long_data = read_RFID;
EEPROM_RFID1 = lb.long_data;
for (int i = 0; i < 4; i++)
{
EEPROM.write(i, lb.byte_data[i]);
}
num = 1;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID1已保存");
Di(1);break;
case 1 :
lb.long_data = read_RFID;
EEPROM_RFID2 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+4, lb.byte_data[i]);
}
num=2;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID2已保存");
Di(1);
break;
case 2 :
lb.long_data = read_RFID;
EEPROM_RFID3 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+8, lb.byte_data[i]);
}
num=3;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID3已保存");
Di(1);
break;
case 3 :
lb.long_data = read_RFID;
EEPROM_RFID4 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+12, lb.byte_data[i]);
}
num=4;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID4已保存");
Di(1);
break;
case 4 :
lb.long_data = read_RFID;
EEPROM_RFID5 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+16, lb.byte_data[i]);
}
num=5;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID5已保存");
Di(1);
break;
case 5 :
lb.long_data = read_RFID;
EEPROM_RFID6 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+20, lb.byte_data[i]);
}
num=6;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID6已保存");
Di(1);
break;
case 6 :
lb.long_data = read_RFID;
EEPROM_RFID7 = lb.long_data;
for (int i = 0 ; i < 4; i++ )
{
EEPROM.write(i+24, lb.byte_data[i]);
}
num=0;
EEPROM.write(30, num);
EEPROM.commit();//执行保存EEPROM
Serial.println("门禁卡ID7已保存");
Di(1);
break;
}
}
}
}
//初始化IO
void IO_init()
{
//io15默认有硬件下拉,不要使用软件上拉模式
pinMode(btn, INPUT);
pinMode(Buzzer, OUTPUT);
digitalWrite(Buzzer, 0);
}
//蜂鸣器音效
void Di(int a)
{
for (int i = 0; i < a; i++)
{
digitalWrite(Buzzer, 1);
delay(500);
digitalWrite(Buzzer, 0);
delay(100);
}
}
/***********************RFID读卡自定义函数***********************/
//初始化读卡
void RFID_init()
{
SPI.begin(); // SPI开始
mfrc522.PCD_Init(); // 初始化
Serial.println("初始化读卡");
}
//运行读卡
void RFID_read()
{
if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial())
{
return;
}
else
{
read_RFID = RFID_toLong(mfrc522.uid.uidByte);
RFID_Handler(read_RFID);
mfrc522.PICC_HaltA();//停止 PICC
mfrc522.PCD_StopCrypto1(); //停止加密PCD
return;
}
}
//用户ID转换类型
long RFID_toLong(byte *by)
{
long data;
for (int i = 0; i < 4; i++)
{
lb.byte_data[i] = by[i];
}
data = lb.long_data;
return data;
}
//把当前读到卡的ID,对比EEPROM中的ID
void RFID_Handler(long data)
{
Serial.println(data);
if (EEPROM_RFID1 == -1&&EEPROM_RFID2 == -1&&EEPROM_RFID3 == -1&&EEPROM_RFID4 == -1&&
EEPROM_RFID5 == -1&&EEPROM_RFID6 == -1&&EEPROM_RFID7 == -1)
{
Serial.println("当前未设置卡");
Di(3);
}
else
{
if (data == EEPROM_RFID1) {
Serial.println("ID1正确,验证通过");
Di(1);
opendoor(); //开门函数
}
else if(data == EEPROM_RFID2){
Serial.println("ID2正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID3){
Serial.println("ID3正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID4){
Serial.println("ID4正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID5){
Serial.println("ID5正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID6){
Serial.println("ID6正确,验证通过");
Di(1);
opendoor();
}
else if(data == EEPROM_RFID7){
Serial.println("ID7正确,验证通过");
Di(1);
opendoor();
}
else
{
Di(2);
Serial.println("ID错误,验证失败");
}
}
}