学生使用NFC打卡,显示在屏幕上,显示前十名的名字,每天显示两次;有个按键,一按就可以显示每个人一周前十名的总次数
1、项目简介
2、实现逻辑
#NFC检测到id卡,将卡号通过串口传送给mcu #mcu获取卡号的最后一位做为识别人的标志,列一个数组将卡号最后一位和真人对应起来 #nodemcu正常联网成功会进行指示灯闪烁 #nodemcu一段时间连不上网会重启 #人员刷卡时间为上午和下午某个时间段,超出这个时间认为迟到,超出时间的或者不在打卡前十名的不显示在屏幕上 #串口屏上有10个位置,正常情况为空,在时间段内有人打卡就显示人名,超出时间段,会在屏幕右下角显示这个人迟到,屏幕人名会在上午和下午统计前清除上一次状态 #有一个按键,按键按下显示周排名前十的人名,并进行次数多少排序以及将进前十的次数显示出来,在周日的某个时间清零 #再次按显示周排名按键,重新显示当日某时间段进前十的人名
3、应用场景
#学生打卡 #nfc签到
4、核心代码梳理
uint8_t *data_nfc = (uint8_t *) malloc(50);
uint8_t stu_nums_t[STU_SUB] = {
0xF0, 0x05, 0x21, 0x20, 0xBB, 0x4F, 0x70, 0xE9, 0x25,
0xEF, 0x64, 0xD4, 0xDF, 0x0F, 0xFC, 0xED, 0x23, 0x98,
0x68, 0x0A, 0x4B, 0x3B, 0x1B, 0xCC, 0x47, 0xE8, 0x77,
0x71, 0xC1, 0xE3, 0x9F, 0xF2, 0x7A, 0x1A, 0x8E, 0x10,
0x2E, 0xDE, 0x7B, 0x63, 0xB2, 0xE7, 0xC7, 0xE2, 0xAD,
0x09, 0xF8, 0x8D, 0x08, 0x1E, 0x33, 0xBC, 0x4D, 0x61,
0x3C, 0x86, 0x2A
};
const char *ssid = "fei";
const char *password = "0123456789";
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8*3600;
const int daylightOffset_sec = 0;
void printLocalTime()
{
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
return;
}
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
}
void setup(void)
{
Serial.begin(115200);
Serial2.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
pinMode(KEY1, INPUT);
pinMode(KEY1, INPUT_PULLUP);
Serial.print("START");
Serial2.print("START");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if(rst_num++ > 20)
{
esp_restart();
}
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
for(uint8_t i=0; i<10; i++)
{
stus_early_day[i] = 0xff;
}
}
void loop(void)
{
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
check = digitalRead(KEY1);
if(check == 0)
{
delay(100);
check = digitalRead(KEY1);
while(!check)
{
check = digitalRead(KEY1);
delay(100);
}
check_flag = !check_flag;
if(check_flag)
{
uint8_t b[STU_SUB];
for(uint8_t i=0; i<STU_SUB; i++)
{
b[i] = i;
}
for(uint8_t i=1; i<STU_SUB; i++)
{
for(uint8_t j=0; j<STU_SUB-i; j++)
{
if(stus_sub_num[b[j]] < stus_sub_num[b[j+1]])
{
uint8_t t = b[j];
b[j] = b[j+1];
b[j+1] = t;
}
}
}
for(uint8_t i=0; i<10; i++)
{
if(stus_sub_num[b[i]] == 0)
{
break;
}
stus_early_wek[i] = b[i];
}
for(uint8_t i=0; i<10; i++)
{
delay(50);
tx_data[5] = i+1;
tx_data[7] = stus_early_day[i];
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
delay(50);
tx_data[5] = i+16;
if(tx_data[7] == 58)
tx_data[7] = 0;
else tx_data[7] = stus_sub_num[stus_early_wek[i]];
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
}
}
else
{
for(uint8_t i=0; i<10; i++)
{
delay(50);
tx_data[5] = i+1;
tx_data[7] = stus_early_day[i];
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
delay(50);
tx_data[5] = i+16;
tx_data[7] = 0;
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
}
}
}
int len = Serial2.readBytes(data_nfc, 50);
struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
Serial.println("Failed to obtain time");
}
if((timeinfo.tm_hour == 21) && (timeinfo.tm_min >= 0) && (timeinfo.tm_min <= 39))
{
if(len > 0)
{
if((data_nfc[0] == 0x04) && (data_nfc[1] == 0x0C))
{
uint8_t card_d = 0;
uint8_t stu_num = STU_SUB + 1;
for(uint8_t i=0; i<STU_SUB; i++)
{
if(stu_nums_t[i] == data_nfc[11])
{
stu_num = i;
break;
}
}
for(uint8_t i=0; i<10; i++)
{
if(stus_early_day[i] == stu_num)
card_d = 1;
}
if(!card_d)
{
if(name_add < 10)
{
stus_early_day[name_add++] = stu_num;
stus_sub_num[stu_num] ++;
}
}
for(uint8_t i=0; i<10; i++)
{
delay(50);
tx_data[5] = i+1;
tx_data[7] = stus_early_day[i];
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
}
}
}
}
else if((timeinfo.tm_hour == 21) && (timeinfo.tm_min >= 40) && (timeinfo.tm_min <= 58))
{
if(len > 0)
{
if((data_nfc[0] == 0x04) && (data_nfc[1] == 0x0C))
{
uint8_t card_d = 0;
uint8_t stu_num = STU_SUB + 1;
for(uint8_t i=0; i<STU_SUB; i++)
{
if(stu_nums_t[i] == data_nfc[11])
{
stu_num = i;
break;
}
}
for(uint8_t i=0; i<10; i++)
{
if(stus_early_day[i] == stu_num)
card_d = 1;
}
if(!card_d)
{
if(name_add < 10)
{
stus_early_day[name_add++] = stu_num;
}
}
stus_sub_num[stu_num] ++;
for(uint8_t i=0; i<10; i++)
{
delay(50);
tx_data[5] = i+1;
tx_data[7] = stus_early_day[i];
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
}
}
}
}
else if((timeinfo.tm_hour == 22) && (timeinfo.tm_min == 00))
{
for(uint8_t i=0; i<10; i++)
{
delay(50);
stus_early_day[i] = 58;
if(!check_flag)
{
tx_data[5] = i+1;
tx_data[7] = stus_early_day[i];
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
}
}
name_add = 0;
}
else
{
if(len > 0)
{
if((data_nfc[0] == 0x04) && (data_nfc[1] == 0x0C))
{
uint8_t stu_num = STU_SUB + 1;
for(uint8_t i=0; i<STU_SUB; i++)
{
if(stu_nums_t[i] == data_nfc[11])
{
stu_num = i;
break;
}
}
delay(50);
tx_data[5] = 11;
tx_data[7] = stu_num;
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
delay(1000);
tx_data[5] = 11;
tx_data[7] = STU_SUB;
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
delay(1000);
tx_data[5] = 11;
tx_data[7] = 58;
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
}
}
}
if((timeinfo.tm_hour == 22) && (timeinfo.tm_wday == 7))
{
for(uint8_t i=0; i<STU_SUB; i++)
{
stus_sub_num[i] = 0;
}
for(uint8_t i=0; i<10; i++)
{
stus_early_wek[i] = 58;
delay(50);
tx_data[5] = i+1;
tx_data[7] = stus_early_day[i];
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
delay(50);
tx_data[5] = i+16;
tx_data[7] = 0;
for(uint8_t j=0; j<8; j++)
{
Serial.printf("%c", tx_data[j]);
}
}
}
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if(rst_num++ > 20)
{
esp_restart();
}
}
}
5、部分参考资料
#修改卡号使用HF高频读写测试软件V1.0.4.exe #串口屏使用sd卡烧录固件,因为屏太大使用外部供电 #需要在资料包中看一下esp32接线和串口屏通信接口相关的内容
6、注意事项
#显示屏使用外部12v供电,nodemcu是5v,中间加了一个电压转换 #按键识别使用的算法不需要加外部电容滤波,但需要长按一会,在弹起的那一刻识别 #现程序中在打卡时间外打卡没显示迟到字样,只显示一下刷卡的人名然后消失,可以取消那部分注释进行显示
|