基于STM32设计的智能防疫消毒门禁系统
项目开发背景
近年来,全球范围内爆发的COVID-19疫情对公共卫生安全构成了严峻挑战,公共场所如办公楼、学校、医院等成为病毒传播的高风险区域。为有效遏制疫情扩散,各国纷纷加强防疫措施,强调在人员密集场所实施快速、非接触式的健康监测和消毒管理。传统门禁系统虽然能实现基本的身份验证功能,但缺乏集成体温检测和自动消毒能力,难以满足疫情下的高效防控需求,往往依赖人工操作,导致效率低下且易增加交叉感染风险。
针对上述问题,智能防疫消毒门禁系统的开发应运而生。该系统结合现代物联网和嵌入式技术,旨在实现无人化、智能化的防疫管理。通过集成人脸识别与体温检测功能,系统能够快速识别人员身份并同步监测体温异常,从而在通行过程中自动联动控制消毒装置。这不仅减少了人为干预,还提升了响应速度,为公共场所提供了一层额外的安全屏障。
本系统以STM32微控制器为核心,搭配摄像头、红外测温模块和Wi-Fi通信组件,构建了一个高效可靠的硬件平台。通过实时数据上传至云平台和上位机管理界面,系统实现了对人员通行记录、体温趋势和消毒日志的全面监控。这种设计不仅适应了当前疫情防控的紧迫需求,还为未来智能建筑和公共健康管理提供了可扩展的解决方案,具有显著的社会和经济价值。
设计实现的功能
(1)使用OV2640摄像头模块实现人脸识别身份认证功能,并结合MLX90614红外测温模块进行体温检测,实现身份认证与体温异常检测联动。
(2)通过继电器控制紫外线消毒灯实现自动触发消杀功能,并记录每次消杀的日志数据。
(3)利用ESP8266-01S Wi-Fi模块实现人员通行数据(如身份、体温、时间)实时上传至华为云平台。
(4)通过QT上位机软件实现管理人员权限、查看体温趋势图及消毒记录功能。
项目硬件模块组成
(1)STM32F103C8T6最小系统核心板(主控)。
(2)OV2640摄像头模块(人脸识别)。
(3)MLX90614非接触式红外测温模块。
(4)继电器控制紫外线消毒灯(自动消杀)。
(5)ESP8266-01S Wi-Fi模块(华为云通信)。
(6)洞洞板焊接电源控制电路,杜邦线连接外设
设计意义
本系统在疫情防控背景下具有重要的实际应用价值,通过非接触式人脸识别与体温检测联动,有效减少了人员直接接触,降低了交叉感染风险,同时确保只有身份合法且体温正常的人员才能通行,提升了场所的安全性。
系统集成自动紫外线消毒功能,在人员通行后立即触发消杀,并记录详细日志,这不仅实现了高效、及时的消毒处理,还通过数据追踪为环境卫生管理提供了可靠依据,尤其适用于医院、学校等高人流区域。
通过ESP8266模块将人员通行数据和消毒记录实时上传至华为云平台,并结合QT上位机进行集中管理,使得管理人员能够远程监控体温趋势、审核权限并分析消杀情况,大幅提升了管理效率和响应速度。
整体设计以低成本、高可靠性的硬件组合实现了智能化防疫管控,强化了公共场所的健康防护能力,为常态化疫情防控提供了实用的技术解决方案。
设计思路
系统以STM32F103C8T6最小系统核心板作为主控制器,负责协调和管理各外设模块的运行。通过OV2640摄像头模块采集人脸图像,进行实时识别和身份认证,同时MLX90614非接触式红外测温模块检测人员体温,实现人脸识别与体温检测的联动。当识别成功且体温正常时,系统允许人员通行;若体温异常或识别失败,则触发警报并拒绝通行。
在人员通行后,系统自动通过继电器控制紫外线消毒灯启动,进行定时消杀操作,并将消杀时间、关联人员信息及结果记录到本地日志中,便于后续查询和分析。消杀日志的存储和管理通过STM32的内部存储器或外接SD卡实现,确保数据可追溯。
通过ESP8266-01S Wi-Fi模块,系统将人员通行数据、体温测量结果以及消毒记录实时上传至华为云平台,实现远程数据监控和存储。Wi-Fi模块与STM32通过串口通信,配置为TCP/IP协议,确保数据传输的稳定性和实时性。
QT上位机软件用于系统管理,支持管理员权限设置,如添加或删除用户信息,并可查看历史体温趋势图和消毒记录。上位机通过解析华为云平台的数据或直接与STM32通信,提供可视化界面,方便用户监控系统状态和调整参数。
硬件连接方面,采用洞洞板焊接电源控制电路,为各模块提供稳定供电,外设如摄像头、测温模块和继电器通过杜邦线与STM32核心板连接,简化了系统搭建和调试过程。整个设计注重实用性和可靠性,确保在实际环境中高效运行。
框架图
智能防疫消毒门禁系统框架图
+---------------------------------------------+
| 感知层 |
| +-------------+ +-------------+ |
| | OV2640 | | MLX90614 | |
| | 摄像头模块 | | 红外测温模块 | |
| | (人脸识别) | | (体温检测) | |
| +-------------+ +-------------+ |
| | | |
+---------------------------------------------+
| |
v v
+---------------------------------------------+
| 控制层 |
| STM32F103C8T6 |
| 核心板(主控) |
| (处理数据、联动控制、记录日志) |
+---------------------------------------------+
| | |
v v v
+-------------+ +-------------+ +-------------+
| 继电器模块 | | ESP8266-01S | | 电源控制电路 |
| (紫外线消毒灯)| | Wi-Fi模块 | | (洞洞板焊接) |
| | | (华为云通信) | | |
+-------------+ +-------------+ +-------------+
|
v
+-------------+
| 华为云平台 |
| (数据存储与 |
| 通信枢纽) |
+-------------+
|
v
+-------------+
| QT上位机 |
| (权限管理、 |
| 数据查看) |
+-------------+
系统总体设计
本系统以STM32F103C8T6最小系统核心板作为主控制器,负责协调各模块运行,实现智能防疫消毒门禁功能。系统通过OV2640摄像头模块采集人脸图像,进行身份识别认证,同时MLX90614非接触式红外测温模块实时检测人员体温,当身份验证通过且体温正常时,系统允许通行;若体温异常,则联动触发警报并限制通行。
在人员通行过程中,系统自动控制继电器驱动紫外线消毒灯进行消杀,确保环境安全,并通过STM32记录每次消杀的详细日志,包括时间、人员ID和消毒状态。所有人员通行数据及消毒记录通过ESP8266-01S Wi-Fi模块实时上传至华为云平台,实现远程数据存储与监控。
此外,系统配备QT开发的上位机软件,用于管理人员权限、查看体温变化趋势及消毒历史记录,提升管理效率。硬件连接采用洞洞板焊接电源控制电路,并通过杜邦线可靠连接各外设模块,确保系统稳定运行。
系统功能总结
| 功能模块 | 硬件组成 | 功能描述 |
|---|---|---|
| 人脸识别身份认证 | OV2640摄像头模块 | 通过摄像头采集图像,进行人脸识别验证人员身份,确保合法通行。 |
| 体温异常检测 | MLX90614非接触式红外测温模块 | 非接触式测量人员体温,检测异常情况(如高温),并与身份认证联动处理。 |
| 自动消毒与日志记录 | 继电器控制紫外线消毒灯 | 在人员通行后自动触发紫外线消毒装置,同时记录消杀时间、次数等日志信息。 |
| 云平台数据上传 | ESP8266-01S Wi-Fi模块 | 实时将人员通行数据、体温记录和消毒日志上传至华为云平台,便于远程监控。 |
| 上位机管理 | STM32主控与PC通信(QT应用) | 通过QT上位机软件管理用户权限、查看体温变化趋势、消毒记录及系统配置。 |
| 系统主控与协调 | STM32F103C8T6最小系统核心板 | 作为核心控制器,处理传感器数据、协调外设操作及执行整体系统逻辑。 |
| 电源与外围连接 | 洞洞板焊接电源控制电路,杜邦线 | 提供稳定电源供应,并通过杜邦线连接各外设模块,确保系统可靠运行。 |
设计的各个功能模块描述
STM32F103C8T6最小系统核心板作为整个系统的主控制器,负责协调和管理各个外设模块的运行。它通过处理来自摄像头和测温模块的数据,实现人脸识别与体温检测的联动逻辑,并根据结果控制消毒装置和通信模块。主控板还负责数据记录和传输任务,确保系统稳定高效地执行防疫功能。
OV2640摄像头模块用于采集人员面部图像,实现人脸识别身份认证功能。该模块将图像数据传输至STM32主控板进行处理,通过预设的算法验证人员身份,并与体温检测结果联动,决定是否允许通行或触发后续消毒操作。
MLX90614非接触式红外测温模块负责实时监测人员的体温数据。该模块通过红外传感技术获取温度值,并传送给STM32主控板进行判断;若检测到体温异常,系统会联动人脸识别结果,阻止通行并记录异常事件,为后续消毒和云平台上传提供依据。
继电器控制紫外线消毒灯模块在系统检测到人员通行后自动触发消杀操作。STM32主控板根据人脸识别和体温检测结果,通过继电器开关控制紫外线灯的启停,实现对通行区域的快速消毒,同时系统会生成消杀日志,记录每次消毒的时间和相关事件。
ESP8266-01S Wi-Fi模块用于实现系统与华为云平台的通信功能。该模块将人员通行数据、体温记录和消毒日志实时上传至云平台,支持远程数据存储和分析,确保信息可追溯,并为上位机管理提供数据基础。
QT上位机模块作为系统的管理界面,允许管理员配置人员权限、查看体温变化趋势和消毒记录。该模块通过图形化界面展示从云平台或本地获取的数据,便于用户进行实时监控和系统维护,提升管理效率。
上位机代码设计
#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QWidget>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QTableWidget>
#include <QHeaderView>
#include <QMessageBox>
#include <QChart>
#include <QChartView>
#include <QLineSeries>
#include <QDateTimeAxis>
#include <QValueAxis>
#include <QDateTime>
#include <QTimer>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
QT_CHARTS_USE_NAMESPACE
class PersonInfo {
public:
QString id;
QString name;
QString role;
QString faceData;
double temperature;
QDateTime timestamp;
PersonInfo(QString _id, QString _name, QString _role, QString _faceData)
: id(_id), name(_name), role(_role), faceData(_faceData), temperature(0.0) {}
};
class DisinfectionLog {
public:
QString id;
QDateTime startTime;
QDateTime endTime;
QString operatorId;
QString status;
DisinfectionLog(QString _id, QDateTime _start, QString _opId)
: id(_id), startTime(_start), operatorId(_opId), status("进行中") {}
};
class MainWindow : public QMainWindow {
Q_OBJECT
private:
// 网络管理器
QNetworkAccessManager *networkManager;
// 数据存储
QList<PersonInfo> personList;
QList<DisinfectionLog> disinfectionLogs;
QList<QPair<QDateTime, double>> temperatureData;
// UI组件
QWidget *centralWidget;
QTabWidget *mainTabWidget;
// 人员管理标签页
QWidget *personManageTab;
QTableWidget *personTable;
QLineEdit *personIdEdit;
QLineEdit *personNameEdit;
QLineEdit *personRoleEdit;
QPushButton *addPersonBtn;
QPushButton *deletePersonBtn;
QPushButton *editPersonBtn;
// 体温监测标签页
QWidget *temperatureTab;
QChartView *temperatureChartView;
QChart *temperatureChart;
QLineSeries *temperatureSeries;
QDateTimeAxis *axisX;
QValueAxis *axisY;
QTableWidget *temperatureTable;
// 消毒记录标签页
QWidget *disinfectionTab;
QTableWidget *disinfectionTable;
QPushButton *refreshDisinfectionBtn;
// 实时监控标签页
QWidget *monitorTab;
QLabel *currentPersonLabel;
QLabel *currentTemperatureLabel;
QLabel *disinfectionStatusLabel;
QLabel *cloudStatusLabel;
QTimer *monitorTimer;
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
setupUI();
setupConnections();
setupChart();
networkManager = new QNetworkAccessManager(this);
// 模拟初始化数据
initSampleData();
// 启动监控定时器
monitorTimer = new QTimer(this);
monitorTimer->start(5000); // 5秒更新一次
}
private:
void setupUI() {
setWindowTitle("智能防疫消毒门禁系统 - 管理平台");
setMinimumSize(1200, 800);
centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
mainTabWidget = new QTabWidget(centralWidget);
// 创建各个标签页
createPersonManageTab();
createTemperatureTab();
createDisinfectionTab();
createMonitorTab();
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
mainLayout->addWidget(mainTabWidget);
}
void createPersonManageTab() {
personManageTab = new QWidget();
QVBoxLayout *layout = new QVBoxLayout(personManageTab);
// 输入区域
QHBoxLayout *inputLayout = new QHBoxLayout();
personIdEdit = new QLineEdit();
personIdEdit->setPlaceholderText("人员ID");
personNameEdit = new QLineEdit();
personNameEdit->setPlaceholderText("姓名");
personRoleEdit = new QLineEdit();
personRoleEdit->setPlaceholderText("角色");
addPersonBtn = new QPushButton("添加");
editPersonBtn = new QPushButton("修改");
deletePersonBtn = new QPushButton("删除");
inputLayout->addWidget(new QLabel("ID:"));
inputLayout->addWidget(personIdEdit);
inputLayout->addWidget(new QLabel("姓名:"));
inputLayout->addWidget(personNameEdit);
inputLayout->addWidget(new QLabel("角色:"));
inputLayout->addWidget(personRoleEdit);
inputLayout->addWidget(addPersonBtn);
inputLayout->addWidget(editPersonBtn);
inputLayout->addWidget(deletePersonBtn);
// 人员表格
personTable = new QTableWidget();
personTable->setColumnCount(4);
personTable->setHorizontalHeaderLabels(QStringList() << "ID" << "姓名" << "角色" << "注册时间");
personTable->horizontalHeader()->setStretchLastSection(true);
layout->addLayout(inputLayout);
layout->addWidget(personTable);
mainTabWidget->addTab(personManageTab, "人员管理");
}
void createTemperatureTab() {
temperatureTab = new QWidget();
QVBoxLayout *layout = new QVBoxLayout(temperatureTab);
// 温度图表
temperatureChartView = new QChartView();
temperatureChartView->setMinimumHeight(400);
// 温度数据表格
temperatureTable = new QTableWidget();
temperatureTable->setColumnCount(4);
temperatureTable->setHorizontalHeaderLabels(QStringList() << "时间" << "人员ID" << "姓名" << "体温(℃)");
layout->addWidget(new QLabel("体温趋势图"));
layout->addWidget(temperatureChartView);
layout->addWidget(new QLabel("体温记录"));
layout->addWidget(temperatureTable);
mainTabWidget->addTab(temperatureTab, "体温监测");
}
void createDisinfectionTab() {
disinfectionTab = new QWidget();
QVBoxLayout *layout = new QVBoxLayout(disinfectionTab);
// 刷新按钮
refreshDisinfectionBtn = new QPushButton("刷新记录");
// 消毒记录表格
disinfectionTable = new QTableWidget();
disinfectionTable->setColumnCount(4);
disinfectionTable->setHorizontalHeaderLabels(QStringList() << "记录ID" << "开始时间" << "结束时间" << "状态");
layout->addWidget(refreshDisinfectionBtn);
layout->addWidget(disinfectionTable);
mainTabWidget->addTab(disinfectionTab, "消毒记录");
}
void createMonitorTab() {
monitorTab = new QWidget();
QGridLayout *layout = new QGridLayout(monitorTab);
currentPersonLabel = new QLabel("当前人员: 无");
currentTemperatureLabel = new QLabel("当前体温: --");
disinfectionStatusLabel = new QLabel("消毒状态: 待机");
cloudStatusLabel = new QLabel("云平台状态: 未连接");
currentPersonLabel->setStyleSheet("font-size: 16pt; padding: 10px;");
currentTemperatureLabel->setStyleSheet("font-size: 16pt; padding: 10px;");
disinfectionStatusLabel->setStyleSheet("font-size: 16pt; padding: 10px;");
cloudStatusLabel->setStyleSheet("font-size: 16pt; padding: 10px;");
layout->addWidget(currentPersonLabel, 0, 0);
layout->addWidget(currentTemperatureLabel, 0, 1);
layout->addWidget(disinfectionStatusLabel, 1, 0);
layout->addWidget(cloudStatusLabel, 1, 1);
mainTabWidget->addTab(monitorTab, "实时监控");
}
void setupConnections() {
connect(addPersonBtn, &QPushButton::clicked, this, &MainWindow::addPerson);
connect(deletePersonBtn, &QPushButton::clicked, this, &MainWindow::deletePerson);
connect(editPersonBtn, &QPushButton::clicked, this, &MainWindow::editPerson);
connect(refreshDisinfectionBtn, &QPushButton::clicked, this, &MainWindow::refreshDisinfectionLogs);
connect(monitorTimer, &QTimer::timeout, this, &MainWindow::updateMonitor);
connect(personTable, &QTableWidget::itemSelectionChanged, this, &MainWindow::onPersonSelectionChanged);
}
void setupChart() {
temperatureChart = new QChart();
temperatureSeries = new QLineSeries();
temperatureChart->addSeries(temperatureSeries);
temperatureChart->setTitle("体温趋势图");
temperatureChart->setAnimationOptions(QChart::SeriesAnimations);
axisX = new QDateTimeAxis();
axisX->setFormat("MM-dd hh:mm");
axisX->setTitleText("时间");
temperatureChart->addAxis(axisX, Qt::AlignBottom);
temperatureSeries->attachAxis(axisX);
axisY = new QValueAxis();
axisY->setLabelFormat("%.1f");
axisY->setTitleText("体温(℃)");
axisY->setRange(35.0, 40.0);
temperatureChart->addAxis(axisY, Qt::AlignLeft);
temperatureSeries->attachAxis(axisY);
temperatureChart->legend()->hide();
temperatureChartView->setChart(temperatureChart);
}
void initSampleData() {
// 添加示例人员
personList.append(PersonInfo("001", "张三", "员工", "face_data_001"));
personList.append(PersonInfo("002", "李四", "管理员", "face_data_002"));
personList.append(PersonInfo("003", "王五", "访客", "face_data_003"));
// 添加示例温度数据
QDateTime currentTime = QDateTime::currentDateTime();
for(int i = 0; i < 10; i++) {
temperatureData.append(QPair<QDateTime, double>(
currentTime.addSecs(-i * 3600),
36.5 + (qrand() % 10) / 10.0
));
}
refreshPersonTable();
refreshTemperatureData();
refreshDisinfectionTable();
}
private slots:
void addPerson() {
QString id = personIdEdit->text().trimmed();
QString name = personNameEdit->text().trimmed();
QString role = personRoleEdit->text().trimmed();
if(id.isEmpty() || name.isEmpty() || role.isEmpty()) {
QMessageBox::warning(this, "错误", "请填写完整的人员信息");
return;
}
// 检查ID是否重复
for(const auto &person : personList) {
if(person.id == id) {
QMessageBox::warning(this, "错误", "人员ID已存在");
return;
}
}
PersonInfo newPerson(id, name, role, "face_data_" + id);
personList.append(newPerson);
// 上传到华为云
uploadPersonToCloud(newPerson);
refreshPersonTable();
clearPersonInput();
QMessageBox::information(this, "成功", "人员添加成功");
}
void deletePerson() {
int row = personTable->currentRow();
if(row == -1) {
QMessageBox::warning(this, "错误", "请选择要删除的人员");
return;
}
QString id = personTable->item(row, 0)->text();
// 从云平台删除
deletePersonFromCloud(id);
// 从本地删除
for(int i = 0; i < personList.size(); i++) {
if(personList[i].id == id) {
personList.removeAt(i);
break;
}
}
refreshPersonTable();
QMessageBox::information(this, "成功", "人员删除成功");
}
void editPerson() {
int row = personTable->currentRow();
if(row == -1) {
QMessageBox::warning(this, "错误", "请选择要修改的人员");
return;
}
QString oldId = personTable->item(row, 0)->text();
QString newName = personNameEdit->text().trimmed();
QString newRole = personRoleEdit->text().trimmed();
if(newName.isEmpty() || newRole.isEmpty()) {
QMessageBox::warning(this, "错误", "请填写完整的修改信息");
return;
}
// 更新本地数据
for(auto &person : personList) {
if(person.id == oldId) {
person.name = newName;
person.role = newRole;
break;
}
}
// 更新云平台
updatePersonInCloud(oldId, newName, newRole);
refreshPersonTable();
clearPersonInput();
QMessageBox::information(this, "成功", "人员信息修改成功");
}
void refreshDisinfectionLogs() {
// 从华为云获取消毒记录
fetchDisinfectionLogsFromCloud();
refreshDisinfectionTable();
}
void updateMonitor() {
// 模拟实时数据更新
static int counter = 0;
counter++;
if(counter % 2 == 0) {
currentPersonLabel->setText("当前人员: 张三");
currentTemperatureLabel->setText("当前体温: 36.5℃");
disinfectionStatusLabel->setText("消毒状态: 已完成");
cloudStatusLabel->setText("云平台状态: 已连接");
// 添加新的温度数据点
QDateTime currentTime = QDateTime::currentDateTime();
double newTemp = 36.3 + (qrand() % 14) / 10.0;
temperatureData.append(QPair<QDateTime, double>(currentTime, newTemp));
// 保持数据点数量不超过20个
if(temperatureData.size() > 20) {
temperatureData.removeFirst();
}
refreshTemperatureData();
} else {
currentPersonLabel->setText("当前人员: 无");
currentTemperatureLabel->setText("当前体温: --");
disinfectionStatusLabel->setText("消毒状态: 待机");
}
}
void onPersonSelectionChanged() {
int row = personTable->currentRow();
if(row != -1) {
personIdEdit->setText(personTable->item(row, 0)->text());
personNameEdit->setText(personTable->item(row, 1)->text());
personRoleEdit->setText(personTable->item(row, 2)->text());
}
}
private:
void refreshPersonTable() {
personTable->setRowCount(personList.size());
for(int i = 0; i < personList.size(); i++) {
const PersonInfo &person = personList[i];
personTable->setItem(i, 0, new QTableWidgetItem(person.id));
personTable->setItem(i, 1, new QTableWidgetItem(person.name));
personTable->setItem(i, 2, new QTableWidgetItem(person.role));
personTable->setItem(i, 3, new QTableWidgetItem(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm")));
}
}
void refreshTemperatureData() {
// 更新图表
temperatureSeries->clear();
for(const auto &data : temperatureData) {
temperatureSeries->append(data.first.toMSecsSinceEpoch(), data.second);
}
// 更新X轴范围
if(!temperatureData.isEmpty()) {
axisX->setRange(
temperatureData.first().first.addSecs(-300),
temperatureData.last().first.addSecs(300)
);
}
// 更新表格
temperatureTable->setRowCount(temperatureData.size());
for(int i = 0; i < temperatureData.size(); i++) {
const auto &data = temperatureData[i];
temperatureTable->setItem(i, 0, new QTableWidgetItem(data.first.toString("MM-dd hh:mm")));
temperatureTable->setItem(i, 1, new QTableWidgetItem("001")); // 示例人员ID
temperatureTable->setItem(i, 2, new QTableWidgetItem("张三")); // 示例姓名
temperatureTable->setItem(i, 3, new QTableWidgetItem(QString::number(data.second, 'f', 1)));
}
}
void refreshDisinfectionTable() {
disinfectionTable->setRowCount(disinfectionLogs.size());
for(int i = 0; i < disinfectionLogs.size(); i++) {
const DisinfectionLog &log = disinfectionLogs[i];
disinfectionTable->setItem(i, 0, new QTableWidgetItem(log.id));
disinfectionTable->setItem(i, 1, new QTableWidgetItem(log.startTime.toString("yyyy-MM-dd hh:mm")));
disinfectionTable->setItem(i, 2, new QTableWidgetItem(log.endTime.toString("yyyy-MM-dd hh:mm")));
disinfectionTable->setItem(i, 3, new QTableWidgetItem(log.status));
}
}
void clearPersonInput() {
personIdEdit->clear();
personNameEdit->clear();
personRoleEdit->clear();
}
// 华为云平台相关方法
void uploadPersonToCloud(const PersonInfo &person) {
QJsonObject json;
json["id"] = person.id;
json["name"] = person.name;
json["role"] = person.role;
json["faceData"] = person.faceData;
QNetworkRequest request(QUrl("https://your-huawei-cloud-api/persons"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = networkManager->post(request, QJsonDocument(json).toJson());
connect(reply, &QNetworkReply::finished, [reply]() {
if(reply->error() == QNetworkReply::NoError) {
qDebug() << "人员数据上传成功";
} else {
qDebug() << "人员数据上传失败:" << reply->errorString();
}
reply->deleteLater();
});
}
void deletePersonFromCloud(const QString &personId) {
QNetworkRequest request(QUrl("https://your-huawei-cloud-api/persons/" + personId));
QNetworkReply *reply = networkManager->deleteResource(request);
connect(reply, &QNetworkReply::finished, [reply]() {
if(reply->error() == QNetworkReply::NoError) {
qDebug() << "人员数据删除成功";
} else {
qDebug() << "人员数据删除失败:" << reply->errorString();
}
reply->deleteLater();
});
}
void updatePersonInCloud(const QString &personId, const QString &name, const QString &role) {
QJsonObject json;
json["name"] = name;
json["role"] = role;
QNetworkRequest request(QUrl("https://your-huawei-cloud-api/persons/" + personId));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply *reply = networkManager->put(request, QJsonDocument(json).toJson());
connect(reply, &QNetworkReply::finished, [reply]() {
if(reply->error() == QNetworkReply::NoError) {
qDebug() << "人员数据更新成功";
} else {
qDebug() << "人员数据更新失败:" << reply->errorString();
}
reply->deleteLater();
});
}
void fetchDisinfectionLogsFromCloud() {
QNetworkRequest request(QUrl("https://your-huawei-cloud-api/disinfection-logs"));
QNetworkReply *reply = networkManager->get(request);
connect(reply, &QNetworkReply::finished, [this, reply]() {
if(reply->error() == QNetworkReply::NoError) {
QByteArray data = reply->readAll();
QJsonDocument doc = QJsonDocument::fromJson(data);
QJsonArray array = doc.array();
disinfectionLogs.clear();
for(const QJsonValue &value : array) {
QJsonObject obj = value.toObject();
DisinfectionLog log(
obj["id"].toString(),
QDateTime::fromString(obj["startTime"].toString(), Qt::ISODate),
obj["operatorId"].toString()
);
log.endTime = QDateTime::fromString(obj["endTime"].toString(), Qt::ISODate);
log.status = obj["status"].toString();
disinfectionLogs.append(log);
}
refreshDisinfectionTable();
qDebug() << "消毒记录获取成功";
} else {
qDebug() << "消毒记录获取失败:" << reply->errorString();
}
reply->deleteLater();
});
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}
#include "main.moc"
这个Qt上位机程序实现了以下功能:
-
人员管理:
- 添加、删除、修改人员信息
- 显示人员列表表格
- 与华为云平台同步人员数据
-
体温监测:
- 实时显示体温趋势图表
- 显示体温记录表格
- 自动更新体温数据
-
消毒记录:
- 显示消毒记录表格
- 从华为云获取消毒日志
- 手动刷新功能
-
实时监控:
- 显示当前人员信息
- 显示当前体温
- 显示消毒状态
- 显示云平台连接状态
程序使用Qt Charts显示体温趋势图,使用QNetworkAccessManager与华为云平台进行HTTP通信,支持JSON数据格式。界面采用标签页布局,用户体验良好。
模块代码设计
#include "stm32f10x.h"
// 系统时钟初始化
void RCC_Configuration(void)
{
// 开启HSE
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
while(!(RCC->CR & RCC_CR_HSERDY));
// 配置PLL 8MHz * 9 = 72MHz
RCC->CFGR |= RCC_CFGR_PLLMULL9;
RCC->CFGR |= RCC_CFGR_PLLSRC;
// 开启PLL
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));
// 设置FLASH延时
FLASH->ACR |= FLASH_ACR_LATENCY_2;
// 切换系统时钟到PLL
RCC->CFGR |= RCC_CFGR_SW_PLL;
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
// 开启外设时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN |
RCC_APB2ENR_USART1EN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN | RCC_APB1ENR_I2C1EN;
}
// GPIO初始化
void GPIO_Configuration(void)
{
// PA2-USART2_TX, PA3-USART2_RX (ESP8266)
GPIOA->CRL &= ~(GPIO_CRL_CNF2 | GPIO_CRL_CNF3 |
GPIO_CRL_MODE2 | GPIO_CRL_MODE3);
GPIOA->CRL |= GPIO_CRL_CNF2_1 | GPIO_CRL_MODE2_0 |
GPIO_CRL_CNF3_0 | GPIO_CRL_MODE3_0;
// PB6-I2C1_SCL, PB7-I2C1_SDA (MLX90614)
GPIOB->CRL &= ~(GPIO_CRL_CNF6 | GPIO_CRL_CNF7 |
GPIO_CRL_MODE6 | GPIO_CRL_MODE7);
GPIOB->CRL |= GPIO_CRL_CNF6_1 | GPIO_CRL_MODE6_0 |
GPIO_CRL_CNF7_1 | GPIO_CRL_MODE7_0;
// PC13-继电器控制
GPIOC->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_MODE13);
GPIOC->CRH |= GPIO_CRH_MODE13_0;
// PA8-状态指示灯
GPIOA->CRH &= ~(GPIO_CRH_CNF8 | GPIO_CRH_MODE8);
GPIOA->CRH |= GPIO_CRH_MODE8_0;
}
// USART2初始化 (ESP8266通信)
void USART2_Configuration(void)
{
USART2->BRR = 72000000 / 115200;
USART2->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
USART2->CR1 |= USART_CR1_RXNEIE;
NVIC_EnableIRQ(USART2_IRQn);
}
// I2C1初始化 (MLX90614)
void I2C1_Configuration(void)
{
I2C1->CR1 &= ~I2C_CR1_PE;
I2C1->CR2 = 36; // 72MHz/2 = 36MHz
I2C1->CCR = 180; // 100kHz
I2C1->TRISE = 37;
I2C1->CR1 |= I2C_CR1_PE;
}
// I2C起始信号
void I2C_Start(void)
{
I2C1->CR1 |= I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB));
}
// I2C停止信号
void I2C_Stop(void)
{
I2C1->CR1 |= I2C_CR1_STOP;
while(I2C1->CR1 & I2C_CR1_STOP);
}
// I2C发送地址
void I2C_SendAddress(uint8_t address, uint8_t direction)
{
I2C1->DR = (address << 1) | direction;
while(!(I2C1->SR1 & I2C_SR1_ADDR));
(void)I2C1->SR2;
}
// I2C发送数据
void I2C_SendData(uint8_t data)
{
I2C1->DR = data;
while(!(I2C1->SR1 & I2C_SR1_TXE));
}
// I2C接收数据
uint8_t I2C_ReceiveData(void)
{
while(!(I2C1->SR1 & I2C_SR1_RXNE));
return I2C1->DR;
}
// MLX90614读取温度
float MLX90614_ReadTemperature(void)
{
uint8_t data[3];
float temperature;
I2C_Start();
I2C_SendAddress(0x5A, 0); // 写模式
I2C_SendData(0x07); // 读取物体温度寄存器
I2C_Start();
I2C_SendAddress(0x5A, 1); // 读模式
data[0] = I2C_ReceiveData(); // 低字节
data[1] = I2C_ReceiveData(); // 高字节
data[2] = I2C_ReceiveData(); // PEC
I2C_Stop();
// 计算温度值
temperature = (float)((data[1] << 8) | data[0]);
temperature = temperature * 0.02 - 273.15;
return temperature;
}
// 继电器控制紫外线灯
void UV_Lamp_Control(uint8_t state)
{
if(state)
GPIOC->BSRR = GPIO_BSRR_BS13; // 开启
else
GPIOC->BSRR = GPIO_BSRR_BR13; // 关闭
}
// 状态指示灯
void LED_Indicator(uint8_t state)
{
if(state)
GPIOA->BSRR = GPIO_BSRR_BS8;
else
GPIOA->BSRR = GPIO_BSRR_BR8;
}
// USART2发送数据
void USART2_SendString(char *str)
{
while(*str)
{
while(!(USART2->SR & USART_SR_TXE));
USART2->DR = *str++;
}
}
// ESP8266发送数据到华为云
void ESP8266_SendToCloud(float temperature, uint8_t person_id, uint8_t access_status)
{
char buffer[128];
// 构造JSON数据
sprintf(buffer, "{\"temp\":%.1f,\"id\":%d,\"status\":%d}\r\n",
temperature, person_id, access_status);
USART2_SendString("AT+CIPSEND=0,");
USART2_SendString(itoa(strlen(buffer), buffer, 10));
USART2_SendString("\r\n");
Delay_ms(100);
USART2_SendString(buffer);
}
// 系统延时函数
void Delay_ms(uint32_t ms)
{
SysTick->LOAD = 72000; // 72MHz/1000 = 72000
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
for(uint32_t i=0; i<ms; i++)
{
while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
}
SysTick->CTRL = 0;
}
// 主函数
int main(void)
{
float temperature;
uint8_t access_granted = 0;
// 系统初始化
RCC_Configuration();
GPIO_Configuration();
USART2_Configuration();
I2C1_Configuration();
// ESP8266初始化
USART2_SendString("AT+RST\r\n");
Delay_ms(2000);
USART2_SendString("AT+CWMODE=1\r\n");
Delay_ms(1000);
USART2_SendString("AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n");
Delay_ms(5000);
USART2_SendString("AT+CIPSTART=\"TCP\",\"192.168.1.100\",1883\r\n");
Delay_ms(3000);
while(1)
{
LED_Indicator(1); // 系统运行指示
// 人脸识别检测 (此处为伪代码,实际需要调用摄像头模块)
// if(FaceRecognition_Success())
// {
// access_granted = 1;
// }
// 读取体温
temperature = MLX90614_ReadTemperature();
if(access_granted && temperature < 37.5f)
{
// 允许通行并消毒
UV_Lamp_Control(1);
Delay_ms(5000); // 消毒5秒
UV_Lamp_Control(0);
// 上传数据到云平台
ESP8266_SendToCloud(temperature, 1, 1);
}
else
{
// 拒绝通行
ESP8266_SendToCloud(temperature, 0, 0);
}
Delay_ms(1000);
LED_Indicator(0);
Delay_ms(1000);
}
}
// USART2中断服务函数
void USART2_IRQHandler(void)
{
if(USART2->SR & USART_SR_RXNE)
{
uint8_t data = USART2->DR;
// 处理ESP8266返回数据
}
}
项目核心代码
#include "stm32f10x.h"
#include "ov2640.h"
#include "mlx90614.h"
#include "esp8266.h"
#include "relay.h"
#include "usart.h"
#include "systick.h"
#include <stdio.h>
#include <string.h>
// 系统状态定义
#define SYS_READY 0
#define FACE_RECOG 1
#define TEMP_CHECK 2
#define DOOR_OPEN 3
#define DISINFECT 4
#define DATA_UPLOAD 5
// 温度阈值
#define TEMP_NORMAL_MAX 37.3
#define TEMP_HIGH_MAX 38.0
// 全局变量
volatile uint8_t system_state = SYS_READY;
volatile uint8_t face_id = 0;
volatile float current_temp = 0.0;
volatile uint8_t auth_result = 0;
volatile uint32_t disinfect_timer = 0;
// 函数声明
void System_Init(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void Process_FaceRecognition(void);
void Process_TemperatureCheck(void);
void Process_DoorControl(void);
void Process_Disinfection(void);
void Process_DataUpload(void);
void LED_Indicator(uint8_t state);
int main(void)
{
// 系统初始化
System_Init();
// 主循环
while(1)
{
switch(system_state)
{
case SYS_READY:
LED_Indicator(0); // 待机指示灯
if(OV2640_DetectFace()) // 检测到人脸
{
system_state = FACE_RECOG;
}
break;
case FACE_RECOG:
Process_FaceRecognition();
break;
case TEMP_CHECK:
Process_TemperatureCheck();
break;
case DOOR_OPEN:
Process_DoorControl();
break;
case DISINFECT:
Process_Disinfection();
break;
case DATA_UPLOAD:
Process_DataUpload();
break;
default:
system_state = SYS_READY;
break;
}
delay_ms(10); // 系统延时
}
}
// 系统初始化
void System_Init(void)
{
// 配置系统时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
// 初始化各模块
GPIO_Configuration();
NVIC_Configuration();
USART1_Init(115200);
OV2640_Init();
MLX90614_Init();
ESP8266_Init();
Relay_Init();
SysTick_Init();
printf("Smart Disinfection Access Control System Started!\r\n");
}
// GPIO配置
void GPIO_Configuration(void)
{
// LED指示灯配置 (PC13)
GPIOC->CRH &= 0xFF0FFFFF;
GPIOC->CRH |= 0x00300000;
GPIOC->BSRR = GPIO_BSRR_BR13; // 初始熄灭
// 门锁控制 (PB12)
GPIOB->CRH &= 0xFFF0FFFF;
GPIOB->CRH |= 0x00030000;
GPIOB->BSRR = GPIO_BSRR_BR12; // 初始关闭
// 消毒灯控制 (PB13)
GPIOB->CRH &= 0xFF0FFFFF;
GPIOB->CRH |= 0x00300000;
GPIOB->BSRR = GPIO_BSRR_BR13; // 初始关闭
}
// NVIC配置
void NVIC_Configuration(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
}
// 人脸识别处理
void Process_FaceRecognition(void)
{
LED_Indicator(1); // 识别中指示灯
// 调用人脸识别算法
face_id = OV2640_FaceRecognition();
if(face_id != 0)
{
auth_result = 1;
printf("Face Recognition Success! User ID: %d\r\n", face_id);
system_state = TEMP_CHECK;
}
else
{
auth_result = 0;
printf("Face Recognition Failed!\r\n");
system_state = SYS_READY;
}
}
// 体温检测处理
void Process_TemperatureCheck(void)
{
LED_Indicator(2); // 测温中指示灯
// 读取体温数据
current_temp = MLX90614_ReadTemperature();
printf("Current Temperature: %.1f°C\r\n", current_temp);
if(current_temp <= TEMP_NORMAL_MAX)
{
// 体温正常,开门
system_state = DOOR_OPEN;
}
else if(current_temp <= TEMP_HIGH_MAX)
{
// 体温偏高,开门但启动消毒
system_state = DOOR_OPEN;
}
else
{
// 体温过高,拒绝通行
printf("Temperature Too High! Access Denied!\r\n");
system_state = SYS_READY;
}
}
// 门控处理
void Process_DoorControl(void)
{
LED_Indicator(3); // 开门指示灯
// 开门
GPIOB->BSRR = GPIO_BSRR_BS12;
printf("Door Opened!\r\n");
// 延时保持开门状态
delay_ms(3000);
// 关门
GPIOB->BSRR = GPIO_BSRR_BR12;
printf("Door Closed!\r\n");
// 根据体温决定是否消毒
if(current_temp > TEMP_NORMAL_MAX)
{
system_state = DISINFECT;
}
else
{
system_state = DATA_UPLOAD;
}
}
// 消毒处理
void Process_Disinfection(void)
{
LED_Indicator(4); // 消毒中指示灯
// 开启消毒灯
GPIOB->BSRR = GPIO_BSRR_BS13;
printf("Disinfection Started!\r\n");
// 消毒计时 (30秒)
disinfect_timer = 0;
while(disinfect_timer < 3000) // 3000 * 10ms = 30s
{
delay_ms(10);
disinfect_timer++;
// 每5秒打印进度
if(disinfect_timer % 500 == 0)
{
printf("Disinfecting... %ld%%\r\n", (disinfect_timer * 100) / 3000);
}
}
// 关闭消毒灯
GPIOB->BSRR = GPIO_BSRR_BR13;
printf("Disinfection Completed!\r\n");
system_state = DATA_UPLOAD;
}
// 数据上传处理
void Process_DataUpload(void)
{
LED_Indicator(5); // 上传数据指示灯
char upload_data[128];
// 构建上传数据
if(current_temp > TEMP_NORMAL_MAX)
{
snprintf(upload_data, sizeof(upload_data),
"{\"user_id\":%d,\"temp\":%.1f,\"status\":\"high_temp\",\"disinfect\":1}",
face_id, current_temp);
}
else
{
snprintf(upload_data, sizeof(upload_data),
"{\"user_id\":%d,\"temp\":%.1f,\"status\":\"normal\",\"disinfect\":0}",
face_id, current_temp);
}
// 上传到华为云
if(ESP8266_SendToCloud(upload_data))
{
printf("Data Upload Success: %s\r\n", upload_data);
}
else
{
printf("Data Upload Failed!\r\n");
}
// 返回待机状态
system_state = SYS_READY;
}
// LED指示灯控制
void LED_Indicator(uint8_t state)
{
// 先熄灭所有状态灯
GPIOC->BSRR = GPIO_BSRR_BR13;
switch(state)
{
case 0: // 待机 - 慢闪
if(SysTick->VAL % 1000 < 500)
GPIOC->BSRR = GPIO_BSRR_BS13;
break;
case 1: // 人脸识别 - 快闪
if(SysTick->VAL % 200 < 100)
GPIOC->BSRR = GPIO_BSRR_BS13;
break;
case 2: // 测温 - 常亮
GPIOC->BSRR = GPIO_BSRR_BS13;
break;
case 3: // 开门 - 双闪
if(SysTick->VAL % 400 < 100)
GPIOC->BSRR = GPIO_BSRR_BS13;
break;
case 4: // 消毒 - 呼吸灯效果
{
static uint8_t breath_dir = 0;
static uint16_t breath_val = 0;
if(breath_dir == 0)
{
breath_val += 10;
if(breath_val >= 1000) breath_dir = 1;
}
else
{
breath_val -= 10;
if(breath_val <= 0) breath_dir = 0;
}
if(SysTick->VAL % 1000 < breath_val)
GPIOC->BSRR = GPIO_BSRR_BS13;
}
break;
case 5: // 上传数据 - 三闪
if(SysTick->VAL % 600 < 100)
GPIOC->BSRR = GPIO_BSRR_BS13;
break;
default:
break;
}
}
// 系统滴答定时器中断服务函数
void SysTick_Handler(void)
{
// 滴答计数更新
static uint32_t tick_count = 0;
tick_count++;
}
总结
本系统基于STM32微控制器设计,实现了智能防疫消毒门禁的全面功能。通过人脸识别与体温异常检测的联动机制,系统能够快速识别授权人员并实时监测体温,有效防止疫情传播,同时自动触发紫外线消毒装置,确保通行环境的安全卫生,并记录详细的消杀日志以备查验。
在硬件组成上,系统采用STM32F103C8T6最小系统核心板作为主控单元,搭配OV2640摄像头模块进行人脸识别,MLX90614非接触式红外测温模块负责体温检测,继电器控制紫外线消毒灯实现自动消杀功能,ESP8266-01S Wi-Fi模块则用于将人员通行数据实时上传至华为云平台,整体通过洞洞板焊接电源控制电路和杜邦线连接外设,确保了系统的稳定运行和高效集成。
此外,系统还通过QT上位机软件实现了管理人员权限、查看体温趋势及消毒记录等功能,为用户提供了便捷的远程监控和数据管理界面,进一步提升了系统的实用性和可扩展性,为各类公共场所的防疫工作提供了可靠的技术支持。
- 点赞
- 收藏
- 关注作者
评论(0)