[作品提交] 【2022得捷电子创新设计大赛】基于人脸识别的测温仪-作品提交

筱笙。。   2022-10-17 21:51 楼主

基于人脸识别的测温仪

作者: EEWorld-筱笙。。

一、作品简介(100-200字)(设计名称、作品照片、功能介绍等。)

本作品为基于人脸识别的测温仪,作品外观为测温枪型,作品主要由Sipeed提供的K210套件、合泰HT32F52352芯片、WIFI通信模块、云服务器、IC读卡器模块以及LDO电源模块等构成,通过HT32芯片控制K210实时采集图像,在本地对采集的图像进行处理,若采集的图像中存在人脸信息,则根据人脸模型,提取出该人脸特征,然后与图像库中人脸的特征值进行对比,将识别结果返回至HT32芯片和上位机,供我们查看测温结果。以下是整体作品的实物图以及该作品的功能介绍。

image-20221017190149-1.jpeg image-20221017190231-2.png image-20221017190244-3.png image-20221017190251-4.png         功能介绍.jpg

二、系统框图(图文结合)

2.1 硬件框图

image-20221017191737-5.png

作品由HT32芯片作为主控,协调图像处理、WIFI通信、LCD显示、IC读卡器以及LDO电源等模块的工作。当图像处理模块采集到的图像中包含人脸时,该模块会按照已训练完成的模型提取人脸的特征值,并与数据库中的人脸特征值对比,若对比结果大于阈值,则会通过串口将该人脸的身份信息返回给HT32芯片。HT32作为主控,完成图像处理模块的识别结果处理后,控制WIFI通信模块,将识别信息发送至云端服务器。移动端应用和web后台管理系统定时请求服务器中的数据,并将请求结果展示在页面中。

2.2 软件框图

image-20221017191921-6.png

HT32的工作流程图

image-20221017191940-7.jpeg

K210录入人脸的工作流程图

image-20221017192010-8.jpeg

K210删除人脸的工作流程图

三、各部分功能说明(图文结合)

image-20221017192129-9.png HT32芯片最小核心板

image-20221017192153-10.jpeg

HTPA32X32dR2L5红外测温模块

image-20221017192220-11.jpeg

ESP8266模块原理图设计

image-20221017192238-12.png

RFID读卡器模块

image-20221017192250-13.jpeg

TPS7A4701线性稳压电源电路原理图     

image-20221017192334-14.png

移动端应用以及后台管理

四、作品源码

>>  下载作品源码

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

回复评论 (3)

有创意,就是电池要选大一点,这些都是耗电大户呀!
点赞  2022-10-19 15:47

展示的很不错啊,可以研究研究。电池一直都是电子设计的硬伤,无法避免的

点赞  2022-10-20 11:59

基于人脸识别的测温仪,创意很好,有借鉴意义,值得学习

点赞  2022-10-20 14:04
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复