基于人脸识别的测温仪
作者: EEWorld-筱笙。。
一、作品简介(100-200字)(设计名称、作品照片、功能介绍等。)
本作品为基于人脸识别的测温仪,作品外观为测温枪型,作品主要由Sipeed提供的K210套件、合泰HT32F52352芯片、WIFI通信模块、云服务器、IC读卡器模块以及LDO电源模块等构成,通过HT32芯片控制K210实时采集图像,在本地对采集的图像进行处理,若采集的图像中存在人脸信息,则根据人脸模型,提取出该人脸特征,然后与图像库中人脸的特征值进行对比,将识别结果返回至HT32芯片和上位机,供我们查看测温结果。以下是整体作品的实物图以及该作品的功能介绍。
二、系统框图(图文结合)
2.1 硬件框图
作品由HT32芯片作为主控,协调图像处理、WIFI通信、LCD显示、IC读卡器以及LDO电源等模块的工作。当图像处理模块采集到的图像中包含人脸时,该模块会按照已训练完成的模型提取人脸的特征值,并与数据库中的人脸特征值对比,若对比结果大于阈值,则会通过串口将该人脸的身份信息返回给HT32芯片。HT32作为主控,完成图像处理模块的识别结果处理后,控制WIFI通信模块,将识别信息发送至云端服务器。移动端应用和web后台管理系统定时请求服务器中的数据,并将请求结果展示在页面中。
2.2 软件框图
HT32的工作流程图
K210录入人脸的工作流程图
K210删除人脸的工作流程图
三、各部分功能说明(图文结合)
HTPA32X32dR2L5红外测温模块
ESP8266模块原理图设计
RFID读卡器模块
TPS7A4701线性稳压电源电路原理图
移动端应用以及后台管理
四、作品源码
>> 下载作品源码
K210实现LCD屏幕驱动、摄像头驱动,加载三个训练模型(面部特征模型、人脸五官特征模型、额外特征模型),初始化两路串口分别用于驱动HTPA32X32红外测温模块和与HT32芯片串口通信,刷IC卡之后,对准要录入的人脸,将人脸录入,再次对准人脸,在LCD屏上将会显示出对应人脸的特征信息,按下按键之后相应的取出当前人的温度信息,并传递给HT32做数据处理。
import sensor,image,lcd,uos,ure
import KPU as kpu
import time,gc,utime
from Maix import FPIOA, GPIO
from fpioa_manager import fm
from board import board_info
from machine import UART
import time
from machine import Timer
#初始化
task_fd = kpu.load(0x300000)
task_ld = kpu.load(0x400000)
task_fe = kpu.load(0x500000)
clock = time.clock()
#映射串口引脚
fm.register(6, fm.fpioa.UART1_TX, force=True)
fm.register(7, fm.fpioa.UART1_RX, force=True)
fm.register(9, fm.fpioa.UART2_RX, force=True)
fm.register(10, fm.fpioa.UART2_TX, force=True)
#初始化串口
uart1 = UART(UART.UART1, 115200, read_buf_len=4096)
uart2 = UART(UART.UART2, 115200, 8, None, 1, timeout=1000, read_buf_len=4096)
BOUNCE_PROTECTION = 50
start_processing = False
#将蓝灯引脚IO12配置到GPIO0,K210引脚支持任意配置
fm.register(12, fm.fpioa.GPIO0)
LED_B = GPIO(GPIO.GPIO0, GPIO.OUT) #构建LED对象
LED_B.value(0) #点亮LED
lcd.init()
lcd.rotation(2)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_hmirror(1)
sensor.set_vflip(1)
sensor.run(1)
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437,
6.92275, 6.718375, 9.01025) # anchor for face detect
dst_point = [(44, 59), (84, 59), (64, 82), (47, 105),
(81, 105)] # standard face key point position
a = kpu.init_yolo2(task_fd, 0.5, 0.3, 5, anchor)
img_lcd = image.Image()
img_face = image.Image(size=(128, 128))
a = img_face.pix_to_ai()
record_ftr = []
record_ftrs = []
names = []
temp = 36.55
Iindex = -1
ACCURACY = 78 #人脸识别阈值
#全局时间戳
timestamp = 1654513893 - 946656000
#海曼32x32的四个指令
Temp_query = bytearray([0xa5, 0x55, 0x01, 0xfb])#温度查询指令
TargetFrame_set = bytearray([0xa9, 0xee, 0x01, 0xfb])#设置温度检测目标框
ThreeTemp_query = bytearray([0xa5, 0x58, 0x01, 0xfb])#查询环境、物体、人体温度
ArrayTemp_query = bytearray([0x51, 0x75, 0x65, 0x72, 0x79, 0x54, 0x0d, 0x0a])#阵列温度查询
#一些标识类型包头
TempFlag = bytearray([0xEE])
StuFlag = bytearray([0xDD])
ADD_READY_Flag = bytearray([0x10])
ADD_COMPLETE_Flag = bytearray([0x11])
DELETE_READY_Flag = bytearray([0x20])
DELETE_COMPLETE_Flag = bytearray([0x21])
TIME_READY_Flag = bytearray([0x30])
ERROR_Flag = bytearray([0xFF])
#加载人脸
def load_face():
global record_ftrs
record_ftrs = []
print('加载人脸')
i = 0
temp_num = ''
with open("recordftr.txt", "r") as f:
while True:
line = f.readline()
if not line:
break
stu_num = line[0:line.index('#')] #获取学号
names.append(stu_num) #追加到姓名列表
line = line[line.index('#')+1:] #截取人脸特征
record_ftrs.append(eval(line)) #向人脸特征列表中添加已存特征
if stu_num != temp_num:
temp_num = stu_num
i = i + 1
print("%d:%s"%(i,stu_num),line)
return 0
#录入人脸
#A01 输入学号
#A11 录入完成
def input_face(feature):
global names
print("录入人脸")
uart1.write(ADD_READY_Flag + '\r\n') #输入学号
print('请输入学号')
while True:
text=uart1.read() #读取数据
if text: #如果读取到了数据
#uart1.write(text)
stu_num = str(text)
break
#写入SD卡
with open("recordftr.txt", "a") as f:
f.write(stu_num+'#'+str(feature)) #信息写入SD卡
record_ftrs.append(feature) #人脸特征追加到record_ftrs列表
names.append(stu_num) #追加到姓名列表
f.write("\n")
f.close()
uart1.write(ADD_COMPLETE_Flag + '\r\n') #录入完成
print('录入成功')
return 0
#删除人脸
#B00 输入学号
#B01 删除成功
def delete_face():
print("删除人脸")
uart1.write(DELETE_READY_Flag + '\r\n') #输入学号
print('请输入学号')
while True:
text=uart1.read() #读取数据
if text: #如果读取到了数据
#uart1.write(text+'\r\n')
stu_num = str(text)
break
#写入SD卡
lines = [i for i in open("recordftr.txt", "r") if i.find(stu_num, 0, len(stu_num)) != 0] #删除指定行
print(str(lines))
fd = open("recordftr.txt", "w")
for j in range(0,len(lines)):
fd.write(lines[j])
fd.close()
print('删除成功')
uart1.write(DELETE_COMPLETE_Flag + '\r\n')
load_face()
def TempMeasure(order):
if order == bytearray([0xa5, 0x55, 0x01, 0xfb]):
uart2.write(order)
tmp = uart2.read()
if tmp:
temp = float((int(tmp[2])+int(tmp[3])*255)/100)
return temp
else:
return None
elif order == bytearray([0xa9, 0xee, 0x01, 0xfb]):
uart2.write(order)
elif order == bytearray([0xa5, 0x58, 0x01, 0xfb]):
uart2.write(order)
elif order == bytearray([0x51, 0x75, 0x65, 0x72, 0x79, 0x54, 0x0d, 0x0a]):
uart2.write(order)
def send_data(sdimg):
global temp,Iindex
if Iindex == -1:
a = sdimg.draw_string(0, 0, str('Face not recognized!'), color=(255, 0, 0), scale=2)
uart1.write(ERROR_Flag)
uart1.write('\r\n')
else:
uart1.write(StuFlag)
uart1.write(names[Iindex][2:12])
uart1.write(TempFlag)
uart1.write(str(temp)+'\r\n')
#时间显示
def GetTime():
global timestamp
time_local = utime.localtime(timestamp)
time_str = "%d-%d-%d %d:%d:%d" % (time_local[0],time_local[1],time_local[2],time_local[3],time_local[4],time_local[5])
return time_str
def Fun_Timestamp_Inc(Timestamp_Inc):
global timestamp
timestamp = timestamp + 1
#主函数
#A 录入人脸
#B 删除人脸
def main():
global start_processing,temp,Iindex
global timestamp
Timestamp_Inc = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PERIODIC, period=1000, callback=Fun_Timestamp_Inc)
load_face()
while True:
img = sensor.snapshot()
timeshow = GetTime()
img.draw_string(120, 218, timeshow,color=(0, 0,255), scale=2)
clock.tick()
code = kpu.run_yolo2(task_fd, img)
if code:
for i in code:
#print(code)
# 裁剪一个128x128的图像框
a = img.draw_rectangle(i.rect())
face_cut = img.cut(i.x(), i.y(), i.w(), i.h())
face_cut_128 = face_cut.resize(128, 128)
a = face_cut_128.pix_to_ai()
face_cut_64 = face_cut.resize(64, 80)
a = img.draw_image(face_cut_64, (0,0))#在左上角画出采集到的人脸
# 画出面部的鼻子的位置
fmap = kpu.forward(task_ld, face_cut_128)
plist = fmap[:]
le = (i.x() + int(plist[0] * i.w() - 10), i.y() + int(plist[1] * i.h()))
re = (i.x() + int(plist[2] * i.w()), i.y() + int(plist[3] * i.h()))
nose = (i.x() + int(plist[4] * i.w()), i.y() + int(plist[5] * i.h()))
lm = (i.x() + int(plist[6] * i.w()), i.y() + int(plist[7] * i.h()))
rm = (i.x() + int(plist[8] * i.w()), i.y() + int(plist[9] * i.h()))
temp_last = TempMeasure(Temp_query)
if temp_last:
temp = temp_last
#画出面部五官的位置
#a = img.draw_circle(le[0], le[1], 4)
#a = img.draw_circle(re[0], re[1], 4)
a = img.draw_circle(nose[0], nose[1], 4)
if temp_last:
if temp_last > 37.3:
a = img.draw_string(i.x()+int(i.w()/3), i.y()+int(i.h()), str(temp_last)
, color=(255, 0, 0), scale=2)
else:
a = img.draw_string(i.x()+int(i.w()/3), i.y()+int(i.h()), str(temp_last)
, color=(0, 255, 0), scale=2)
else:
if temp > 37.3:
a = img.draw_string(i.x()+int(i.w()/3), i.y()+int(i.h()), str(temp)
, color=(255, 0, 0), scale=2)
else:
a = img.draw_string(i.x()+int(i.w()/3), i.y()+int(i.h()), str(temp)
, color=(0, 255, 0), scale=2)
#a = img.draw_circle(lm[0], lm[1], 4)
#a = img.draw_circle(rm[0], rm[1], 4)
# 将人脸与标准位置对齐
src_point = [le, re, nose, lm, rm]
T = image.get_affine_transform(src_point, dst_point)
a = image.warp_affine_ai(img, img_face, T)
a = img_face.ai_to_pix()
del (face_cut_128)
del (face_cut_64)
# 计算人脸特征向量
fmap = kpu.forward(task_fe, img_face) #计算已加载的网络模型到指定层数,输出目标层的特征图
feature = kpu.face_encode(fmap[:]) #将 forward 返回的特征图进行量化
reg_flag = False
scores = []
for j in range(len(record_ftrs)):
score = kpu.face_compare(record_ftrs[j], feature) #将 face_encode 返回的量化值与已录入的人脸进行比较
scores.append(score)
max_score = 0
index = 0
for k in range(len(scores)): #寻找最大的匹配值
if max_score < scores[k]:
max_score = scores[k]
index = k
if max_score > ACCURACY:
a = img.draw_string(i.x(), i.y(), ("%s :%2.1f" % (
names[Iindex][2:12], max_score)), color=(0, 255, 0), scale=2)
Iindex = index
else:
a = img.draw_string(i.x(), i.y(), ("X :%2.1f" % (
max_score)), color=(255, 0, 0), scale=2)
Iindex = -1
if start_processing == True:
input_face(feature)
start_processing = False
text=uart1.read() #读取数据
if text: #如果读取到了数据
rec_str = str(text)
print(rec_str[2])
if rec_str[2] == 'A': #录入人脸
start_processing = True
elif rec_str[2] == 'D': #删除人脸
delete_face()
elif rec_str[2] == 'C':
send_data(img)
Iindex = -1
elif rec_str[2] == 'T':
uart1.write(TIME_READY_Flag + '\r\n') #输入学号
while True:
text=uart1.read() #读取数据
if text: #如果读取到了数据
print(text)
print(int(text))
print(timestamp)
timestamp = int(text) - 946656000 #校准
print(timestamp)
break
a = lcd.display(img)
gc.collect()
main()
HT32主要用于接收K210发送来的信息与数据,将数据通过esp8266上传至移动端。
#include "main.h"
#include "RFID.h"
#include "K210.h"
#include "ESP8266.h"
#include "char_conversion.h"
#include "key.h"
#include "BY8302.h"
// PA6 for key button
void Send_String(HT_USART_TypeDef *USARTx, char *str);
static void Func_Short_Press(void);
static void Func_Long_Press(void);
static void Func_IC_Check(void);
//static void RTC_Init(void);
int main(void)
{
BY8302_Init();
RFID_Init();
K210_Init();
ESP8266_Init();
KEY_Init();
// RTC_Init();
while (1)
{
Key_Type key = Key_Get();
if (key == SHORT_PRESS)
{
Func_Short_Press();
}
else if (key == LONG_PRESS)
{
Func_Long_Press();
}
Func_IC_Check();
}
}
static void Func_Short_Press(void)
{
//短按发送查询温度指令
USART_SendData(K210_PORT, K210_CMD_QUERY);
while (K210_MSG_Check() != SET)
;
char Stu_ID[10] = {0};
char Temperature[5] = {0};
if (K210_MSG_Type_Get() == STU_ID_MSG)
{
K210_MSG_IDandTemperature_Get(Stu_ID, Temperature);
ESP8266_Stu_Check(Stu_ID, Temperature);
}
K210_MSG_Complete_Clear();
//待测试
double temper = (Temperature[0]-0x30) * 10 + (Temperature[1]-0x30) + (Temperature[3]-0x30) * 0.1 + (Temperature[4]-0x30) * 0.01;
//待测试
if (temper > 35.8 && temper < 37.8)
{
BY8302_Voice_Face_Check();
}
else
{
BY8302_Voice_Face_Alarm();
}
BY8302_Voice_Number(Temperature);
}
static void Func_Long_Press(void)
{
//长按更新时间
static char UpdateTime[11] = {0};
ESP8266_MSG_Complete_Clear();
USART_SendData(ESP8266_USART, STU_CMD_UDATETIME);
while (ESP8266_MSG_Check() != SET)
;
if (ESP8266_MSG_Type_Get() == ESP_UPDATETIME)
{
ESP8266_MSG_UpdateTime_Get(UpdateTime);
delay_ms(100);
K210_UpdateTime(UpdateTime);
BY8302_Voice_UpdateTime();
}
}
static void Func_IC_Check(void)
{
// 刷卡
if (RFID_Complete_Check() == SET)
{
//防止重复刷卡
USART_IntConfig(RFID_USART, USART_INT_RXDR, DISABLE);
RFIDInfo info = RFID_IcMsgGet();
RFID_Complete_Clear();
//语音播报
BY8302_Voice_IC_Check();
while (Key_Flag_Check() != SET)
;
Key_Type temp_key = Key_Get();
Key_Flag_Clear();
if (temp_key == SHORT_PRESS) //人脸录入
{
K210_Add(info.stu_id);
//将姓名由GB2312转UTF-8
char str_name[40] = {0};
gb2312ToUtf8(str_name, 40, info.stu_name, sizeof(info.stu_name));
ESP8266_Stu_Add(info.stu_id, str_name);
BY8302_Voice_Face_Record();
}
else if (temp_key == LONG_PRESS) //人脸删除
{
K210_Delete(info.stu_id);
//将姓名由GB2312转UTF-8
char str_name[40] = {0};
gb2312ToUtf8(str_name, 40, info.stu_name, sizeof(info.stu_name));
ESP8266_Stu_Delete(info.stu_id);
USART_IntConfig(RFID_USART, USART_INT_RXDR, ENABLE);
BY8302_Voice_Face_Delete();
}
USART_IntConfig(RFID_USART, USART_INT_RXDR, ENABLE);
}
}
void Send_String(HT_USART_TypeDef *USARTx, char *str)
{
while (*str != '\0')
{
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXDE) != SET)
{
};
USART_SendData(USARTx, *str++);
}
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXC) != SET)
;
}
void BY8302_Init(void)
{
{ /* Enable peripheral clock of AFIO, UxART */
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.AFIO = 1;
CKCUClock.Bit.BY8302_RX_GPIO_CLK = 1;
CKCUClock.Bit.BY8302_CLK = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
/* Turn on UxART Rx internal pull up resistor to prevent unknow state */
GPIO_PullResistorConfig(BY8302_RX_GPIO_PORT, BY8302_RX_GPIO_PIN, GPIO_PR_UP);
/* Config AFIO mode as UxART function. */
AFIO_GPxConfig(BY8302_TX_GPIO_ID, BY8302_TX_AFIO_PIN, AFIO_FUN_USART_UART);
AFIO_GPxConfig(BY8302_RX_GPIO_ID, BY8302_RX_AFIO_PIN, AFIO_FUN_USART_UART);
{
USART_InitTypeDef USART_InitStructure = {0};
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;
USART_InitStructure.USART_StopBits = USART_STOPBITS_1;
USART_InitStructure.USART_Parity = USART_PARITY_NO;
USART_InitStructure.USART_Mode = USART_MODE_NORMAL;
USART_Init(BY8302_USART, &USART_InitStructure);
}
USART_IntConfig(BY8302_USART, USART_INT_RXDR, ENABLE);
NVIC_EnableIRQ(BY8302_IRQn);
/* Enable UxART Tx and Rx function */
USART_TxCmd(BY8302_USART, ENABLE);
USART_RxCmd(BY8302_USART, ENABLE);
}
void RFID_Init(void)
{
{ /* Enable peripheral clock of AFIO, UxART */
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.AFIO = 1;
CKCUClock.Bit.RFID_RX_GPIO_CLK = 1;
CKCUClock.Bit.RFID_CLK = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
/* Turn on UxART Rx internal pull up resistor to prevent unknow state */
GPIO_PullResistorConfig(RFID_RX_GPIO_PORT, RFID_RX_GPIO_PIN, GPIO_PR_UP);
/* Config AFIO mode as UxART function. */
AFIO_GPxConfig(RFID_TX_GPIO_ID, RFID_TX_AFIO_PIN, AFIO_FUN_USART_UART);
AFIO_GPxConfig(RFID_RX_GPIO_ID, RFID_RX_AFIO_PIN, AFIO_FUN_USART_UART);
{
USART_InitTypeDef USART_InitStructure = {0};
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;
USART_InitStructure.USART_StopBits = USART_STOPBITS_1;
USART_InitStructure.USART_Parity = USART_PARITY_NO;
USART_InitStructure.USART_Mode = USART_MODE_NORMAL;
USART_Init(RFID_USART, &USART_InitStructure);
}
USART_IntConfig(RFID_USART, USART_INT_RXDR, ENABLE);
NVIC_EnableIRQ(RFID_IRQn);
/* Enable UxART Tx and Rx function */
USART_TxCmd(RFID_USART, ENABLE);
USART_RxCmd(RFID_USART, ENABLE);
}
void K210_Init(void)
{
{ /* Enable peripheral clock of AFIO, UxART */
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.AFIO = 1;
CKCUClock.Bit.K210_RX_GPIO_CLK = 1;
CKCUClock.Bit.K210_CLK = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
/* Turn on UxART Rx internal pull up resistor to prevent unknow state */
GPIO_PullResistorConfig(K210_RX_GPIO_PORT, K210_RX_GPIO_PIN, GPIO_PR_UP);
/* Config AFIO mode as UxART function. */
AFIO_GPxConfig(K210_TX_GPIO_ID, K210_TX_AFIO_PIN, AFIO_FUN_USART_UART);
AFIO_GPxConfig(K210_RX_GPIO_ID, K210_RX_AFIO_PIN, AFIO_FUN_USART_UART);
{
USART_InitTypeDef USART_InitStructure = {0};
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;
USART_InitStructure.USART_StopBits = USART_STOPBITS_1;
USART_InitStructure.USART_Parity = USART_PARITY_NO;
USART_InitStructure.USART_Mode = USART_MODE_NORMAL;
USART_Init(K210_PORT, &USART_InitStructure);
}
USART_IntConfig(K210_PORT, USART_INT_RXDR, ENABLE);
NVIC_EnableIRQ(K210_IRQn);
USART_TxCmd(K210_PORT, ENABLE);
USART_RxCmd(K210_PORT, ENABLE);
}
void ESP8266_Init(void)
{
{ /* Enable peripheral clock of AFIO, UxART */
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.AFIO = 1;
CKCUClock.Bit.ESP8266_RX_GPIO_CLK = 1;
CKCUClock.Bit.ESP8266_CLK = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
/* Turn on UxART Rx internal pull up resistor to prevent unknow state */
GPIO_PullResistorConfig(ESP8266_RX_GPIO_PORT, ESP8266_RX_GPIO_PIN, GPIO_PR_UP);
/* Config AFIO mode as UxART function. */
AFIO_GPxConfig(ESP8266_TX_GPIO_ID, ESP8266_TX_AFIO_PIN, AFIO_FUN_USART_UART);
AFIO_GPxConfig(ESP8266_RX_GPIO_ID, ESP8266_RX_AFIO_PIN, AFIO_FUN_USART_UART);
{
USART_InitTypeDef USART_InitStructure = {0};
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WORDLENGTH_8B;
USART_InitStructure.USART_StopBits = USART_STOPBITS_1;
USART_InitStructure.USART_Parity = USART_PARITY_NO;
USART_InitStructure.USART_Mode = USART_MODE_NORMAL;
USART_Init(ESP8266_USART, &USART_InitStructure);
}
USART_IntConfig(ESP8266_USART, USART_INT_RXDR, ENABLE);
NVIC_EnableIRQ(ESP8266_IRQn);
/* Enable UxART Tx and Rx function */
USART_TxCmd(ESP8266_USART, ENABLE);
USART_RxCmd(ESP8266_USART, ENABLE);
}
static void TM_Configuration(void)
{
#if 0 // Use following function to configure the IP clock speed.
CKCU_SetPeripPrescaler(CKCU_PCLK_GPTM0, CKCU_APBCLKPRE_DIV2);
#endif
{ /* Enable peripheral clock */
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.GPTM0 = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
{ /* Time base configuration */
/* !!! NOTICE !!!
Notice that the local variable (structure) did not have an initial value.
Please confirm that there are no missing members in the parameter settings below in this function.
*/
TM_TimeBaseInitTypeDef TimeBaseInit;
TimeBaseInit.Prescaler = 1000 - 1; // Timer clock = CK_AHB / 1
TimeBaseInit.CounterReload = 480 - 1;
TimeBaseInit.RepetitionCounter = 0;
TimeBaseInit.CounterMode = TM_CNT_MODE_UP;
TimeBaseInit.PSCReloadTime = TM_PSC_RLD_IMMEDIATE;
TM_TimeBaseInit(HT_GPTM0, &TimeBaseInit);
/* Clear Update Event Interrupt flag since the "TM_TimeBaseInit()" writes the UEV1G bit */
TM_ClearFlag(HT_GPTM0, TM_FLAG_UEV);
}
/* Enable Update Event interrupt */
NVIC_EnableIRQ(GPTM0_IRQn);
TM_IntConfig(HT_GPTM0, TM_INT_UEV, ENABLE);
TM_Cmd(HT_GPTM0, ENABLE);
}
static void GPIO_Configuration(void)
{
{ /* Enable peripheral clock */
CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
CKCUClock.Bit.AFIO = 1;
CKCUClock.Bit.KEY_GPIO_CLK = 1;
CKCU_PeripClockConfig(CKCUClock, ENABLE);
}
{ /* Configure GPIO as input mode */
/* Configure AFIO mode as GPIO */
AFIO_GPxConfig(KEY_GPIO_ID, KEY_AFIO_PIN, AFIO_FUN_GPIO);
/* Configure GPIO pull resistor */
GPIO_PullResistorConfig(KEY_PORT, KEY_GPIO_PIN, GPIO_PR_UP);
/* Configure GPIO direction as input */
GPIO_DirectionConfig(KEY_PORT, KEY_GPIO_PIN, GPIO_DIR_IN);
/* Enable input function for read */
GPIO_InputConfig(KEY_PORT, KEY_GPIO_PIN, ENABLE);
}
}
五、作品功能演示视频
点击查看>> 演示视频
六、项目总结(项目文字总结+帖子分享链接汇总)
该作品我认为有的创新点:
1、运用光电检测技术进行温度测量和人脸识别,可精准识别人员身份。
2、在测温系统中增加了IC读卡功能、人脸识别功能和物联网功能,使测温的同时进行身份信息对比和温度数据保存,是一款智能测温系统。
3、提供一种新型防疫测温模式,让防疫人员无需手动登记测温结果,同时解决了测量温度与被测人身份无法自动关联的问题,为防疫工作者提供了便捷。
4、用户可通过APP提前上传健康码和行程码,简化监管场所防疫人员的验证流程,避免人员聚集从而防止交叉传染。
5、扩大应用范围,具有测温和人脸识别功能,可应用于监管场所的身份信息验证、考勤打卡、真人识别等。
该作品做的时间周期非常的长,我在从中学习到了非常多的知识,从k210和HT32的代码编写,驱动编写,到移动端前后端的代码编写,以及包括电源电路的设计和3D打印的使用,都令我受益匪浅,通过本次的大赛,不仅将自己的基础打牢,还学习到了更多对自己有莫大的帮助的工具;当然这个作品还是有非常多的问题:
1、现在作品的功耗还非常的大,约2.3W~2.7W,对5000mA/h的电池消耗带载负担过大,还需要优化电路,希望以后能将HT32更换成TI低功耗芯片。
2、3D打印的结构属于盖盒式,没有卡扣与螺丝的设计,不容易安装,需要之后设计更好安装的机械设计。
3、K210的LCD没有加入GUI人机交互功能,缺少一定的互动性。
4、移动端APP的健康码上传在过多人使用的情况下,会导致APP崩溃报错的现象,之后一定得优化。
5、HTPA32X32红外测温模块由于是模块化产品,精度和误码率已经得以修正,但是在速度不尽人意,打算买单独模块,自己编写驱动程序加速读取过程,在人脸识别测温的基础上加入热成像功能。
七、其他
K210人脸识别环境搭建流程 https://bbs.eeworld.com.cn/thread-1209909-1-1.html
物料开箱 K210 & STM32F7508-DK https://bbs.eeworld.com.cn/thread-1208961-1-1.html