基于华为云平台的STM32F103C8T6工业生产线温湿度监控系统
项目开发背景
随着现代工业生产的精细化和自动化程度不断提高,生产环境中的温湿度参数已成为影响产品质量、设备稳定运行及能源管理效率的关键因素。尤其在食品加工、药品生产、电子制造等行业,温湿度波动可能导致原料变质、工艺偏差或设备故障,直接造成经济损失。传统的人工巡检方式存在数据记录滞后、响应效率低等问题,无法满足实时监控与快速响应的需求。
工业物联网技术的快速发展为生产环境监控提供了新的解决方案。通过部署传感器网络与云平台结合,能够实现对生产环境的多点、连续、远程监测,并通过数据智能分析实现预警与自动控制。华为云物联网平台以其高可靠性、安全性和数据处理能力,为工业设备联网与数据管理提供了强有力的技术支持。
本项目基于STM32F103C8T6微控制器核心,结合多路高精度温湿度传感器、无线通信模块及执行机构,构建了一套面向工业生产线环境的实时监控系统。该系统不仅实现了温湿度数据的多点采集、阈值报警与设备联动控制,还通过华为云平台实现了数据云端存储与远程访问,配合QT开发的上位机界面,为生产管理者提供了直观的数据可视化与设备状态监控手段,有效提升了生产环境管理的智能化水平和应急响应能力。
设计实现的功能
(1)使用STM32F103C8T6主控制器,通过3个DHT22传感器实现生产线环境多点温湿度数据采集。
(2)当温湿度数据超过预设阈值时,自动控制5V继电器模块启动通风设备,并通过有源蜂鸣器实现声光报警功能。
(3)通过ESP8266-01S Wi-Fi模块将实时温湿度数据及报警信息上传至华为云物联网平台。
(4)通过QT上位机软件实时显示各监测点的温湿度数据变化趋势及通风设备运行状态。
项目开发背景
随着现代工业自动化水平的不断提升,生产环境中的温湿度参数对产品质量、设备稳定性及生产效率的影响日益显著。尤其在电子制造、食品加工、医药生产等行业,环境温湿度的微小波动可能导致产品合格率下降或设备异常,因此实现高精度、实时化的环境监控已成为工业智能化转型中的重要环节。
传统的温湿度监控多依赖人工巡检或本地化单点监测,存在数据滞后、响应效率低、无法远程预警等问题。华为云物联网平台的出现为工业数据提供了高效、安全的云端管理方案,通过云平台实现设备数据聚合、远程控制及可视化分析,能够有效提升生产管理的精细化水平。
本项目基于STM32F103C8T6主控制器,结合多路高精度传感器与Wi-Fi通信模块,构建了一套低成本、高可靠性的温湿度监控系统。该系统不仅实现了生产现场多点数据的实时采集与设备联动控制,还通过华为云平台实现了数据云端同步与远程管理,进一步为工业生产线环境监控的数字化和智能化提供了可行的技术实践方案。
设计实现的功能
(1)多点采集生产线环境温湿度数据。
(2)数据超过设定阈值时自动启动通风设备并报警。
(3)实时数据与报警信息上传至华为云物联网平台。
(4)QT上位机显示各监测点数据变化趋势及设备运行状态。
项目硬件模块组成
(1)STM32F103C8T6最小系统核心板
(2)3个DHT22高精度温湿度传感器
(3)5V继电器模块
(4)有源蜂鸣器
(5)ESP8266-01S Wi-Fi模块
(6)洞洞板焊接电源管理电路,杜邦线连接各功能模块
项目硬件模块组成
(1)STM32F103C8T6最小系统核心板作为主控制器。
(2)3个DHT22高精度温湿度传感器进行多点监测。
(3)5V继电器模块控制通风设备启停。
(4)有源蜂鸣器实现声光报警功能。
(5)ESP8266-01S Wi-Fi模块实现华为云平台数据传输。
(6)洞洞板焊接电源管理电路,杜邦线连接各功能模块。
设计意义
本系统设计旨在通过实时监控工业生产线环境的温湿度的变化,确保生产过程的稳定性和产品质量。在工业环境中,温湿度是影响设备运行、材料保存和产品良率的关键因素,该系统能够及时检测异常情况,从而预防因环境波动导致的生产中断或损失,提升整体生产线的可靠性和安全性。
通过自动阈值报警和通风设备控制功能,系统实现了快速响应环境变化的能力,减少了人工干预的需求。当温湿度超出设定范围时,系统立即启动通风设备并触发声光报警,这有助于避免潜在的安全隐患,如设备过热或潮湿导致的故障,同时提高了生产环境的自动化水平,优化了资源利用效率。
集成华为云物联网平台和QT上位机显示,使得数据能够远程实时上传和可视化,方便管理人员进行监控和数据分析。这种设计支持历史数据回溯和趋势分析,为生产决策提供数据支持,增强了系统的可扩展性和维护性,符合现代工业物联网的发展趋势,促进了智能工厂的建设。
硬件组成基于STM32F103C8T6核心板、DHT22传感器、继电器模块等常见组件,确保了系统的低成本、高可靠性和易部署性。这种设计注重实用性和经济性,适用于多种工业场景,体现了嵌入式系统与云技术的有效结合,具有较高的应用价值和推广前景。
设计意义
基于华为云平台的STM32F103C8T6工业生产线温湿度监控系统设计意义在于提升工业生产环境的智能化管理水平。该系统通过多点采集温湿度数据,确保对生产线关键区域的全面覆盖,从而实时掌握环境状况,避免因温湿度波动影响产品质量或设备性能,为生产过程的稳定运行提供基础保障。
系统具备自动控制功能,当监测数据超过设定阈值时,能立即启动通风设备并触发声光报警,这有效减少了人为干预的延迟,提高了响应速度,防止环境异常导致的生产事故或设备损坏,增强了工业现场的安全性和可靠性。
通过ESP8266-01S Wi-Fi模块将实时数据与报警信息上传至华为云物联网平台,实现了数据的远程存储和访问,便于管理人员随时随地监控生产线状态,支持历史数据回溯和分析,为决策提供依据,同时降低了现场维护的复杂性和成本。
QT上位机显示各监测点数据变化趋势及设备运行状态,提供了直观的用户界面,使操作人员能够快速识别问题并采取行动,进一步优化了生产流程的管理效率,体现了工业物联网技术在传统制造业中的实际应用价值。
设计思路
该系统设计以STM32F103C8T6最小系统核心板作为主控制器,负责协调整个温湿度监控系统的运行。通过集成3个DHT22高精度温湿度传感器,实现生产线环境的多点数据采集,每个传感器分别布置在不同监测点,以确保全面覆盖。STM32通过GPIO接口轮询读取传感器数据,并进行初步处理,包括数据校验和单位转换,确保采集的温湿度值准确可靠。
数据采集后,系统会实时比较采集值与预设的温湿度阈值。如果任何监测点的数据超过阈值,STM32会立即通过GPIO控制5V继电器模块,启动通风设备进行调节,同时驱动有源蜂鸣器发出声光报警,以提醒操作人员注意异常情况。这一过程采用中断或轮询方式实现快速响应,确保系统能够及时处理环境变化。
为了将实时数据和报警信息上传至华为云物联网平台,系统利用ESP8266-01S Wi-Fi模块通过串口与STM32通信。STM32将采集的数据和报警状态封装成JSON格式,通过AT指令集控制ESP8266模块建立Wi-Fi连接,并采用MQTT协议将数据推送至华为云平台。平台接收数据后,可实现远程监控和日志记录,为后续数据分析提供基础。
QT上位机软件负责显示各监测点的数据变化趋势及设备运行状态。上位机通过HTTP或MQTT协议从华为云平台获取数据,并利用图表控件实时绘制温湿度曲线,同时显示通风设备和报警状态。界面设计简洁直观,支持历史数据查询和阈值设置,方便用户进行远程监控和管理。
硬件方面,系统采用洞洞板焊接电源管理电路,为STM32、传感器、继电器和蜂鸣器提供稳定的5V和3.3V电源,确保各模块正常工作。杜邦线用于连接各功能模块,简化布线并提高系统的可维护性。整个设计注重实用性和可靠性,适用于工业生产线环境。
设计思路
该系统以STM32F103C8T6最小系统核心板作为主控制器,负责协调整个监控系统的运行。核心板通过GPIO接口连接三个DHT22温湿度传感器,这些传感器分布在不同监测点,定期采集环境温湿度数据。STM32通过单总线协议读取传感器数据,并进行初步处理,确保数据的准确性和实时性。
数据采集后,STM32内部程序会与预设的温湿度阈值进行比较。如果任何监测点的数据超过阈值,STM32会立即触发控制信号,通过GPIO输出高电平驱动5V继电器模块,从而启动通风设备进行调节。同时,STM32会控制有源蜂鸣器发出声光报警,提醒操作人员注意异常情况。
为了实现远程监控和数据上传,系统集成ESP8266-01S Wi-Fi模块。STM32通过串口与ESP8266通信,将采集到的温湿度数据以及报警信息封装成MQTT协议格式,并通过Wi-Fi网络传输到华为云物联网平台。华为云平台负责数据的存储和管理,并支持后续的数据分析和远程控制。
在上位机端,采用QT开发的应用程序实时接收华为云平台下发的数据。QT上位机界面显示各监测点的温湿度变化趋势曲线、当前数值以及设备运行状态(如通风设备开关状态和报警信息)。用户可以通过上位机直观监控生产线环境,并及时响应异常事件。整个系统的硬件连接通过洞洞板焊接电源管理电路提供稳定供电,并使用杜邦线灵活连接各功能模块,确保系统的可靠性和扩展性。
框架图
+----------------+ +-----------------+ +-----------------+ +---------------+
| DHT22 Sensor 1 |------| | | | | Huawei Cloud |
+----------------+ | | | | | IoT Platform |
+----------------+ | STM32F103C8T6 |-------| ESP8266-01S |-------| |
| DHT22 Sensor 2 |------| Main Controller | | Wi-Fi Module | +---------------+
+----------------+ | | | | |
+----------------+ | | | | |
| DHT22 Sensor 3 |------| | +-----------------+ |
+----------------+ +-----------------+ |
|
+----------------+ +-----------------+ |
| Relay Module |-------| STM32F103C8T6 | |
| (Ventilation) | | Main Controller | |
+----------------+ +-----------------+ |
|
+----------------+ +-----------------+ |
| Buzzer |-------| STM32F103C8T6 | |
| (Alarm) | | Main Controller | |
+----------------+ +-----------------+ |
|
|
+------------------+ |
| QT Upper Computer |<--------------------------------------------------------------+
| (Display Trends) |
+------------------+
框架图
+----------------+ +-----------------+ +-------------------+
| DHT22 | | | | |
| Sensor 1 |----->| | | |
+----------------+ | | | |
+----------------+ | STM32F103C8T6 | | ESP8266-01S |
| DHT22 |----->| Main Controller|----->| Wi-Fi Module |
| Sensor 2 | | | | |
+----------------+ | | | |
+----------------+ | | | |
| DHT22 |----->| | | |
| Sensor 3 | +-----------------+ +-------------------+
+----------------+ |
|
v
+-------------------+
| Huawei Cloud |
| IoT Platform |
+-------------------+
|
|
v
+-------------------+
| QT Upper Computer|
| (Display & Monitor)|
+-------------------+
+-----------------+ +-----------------+
| Relay Module |<-----| STM32 |
| (5V) | | Controller |
+-----------------+ | |
| |----->+-----------------+
+-----------------+ | Buzzer |
| (Alarm) |
+-----------------+
系统总体设计
该系统基于STM32F103C8T6最小系统核心板作为主控制器,负责协调整个温湿度监控系统的运行。系统通过三个DHT22高精度温湿度传感器进行多点数据采集,实时监测生产线环境中的温度和湿度参数,确保覆盖关键区域。
采集到的数据由STM32处理器进行分析,当任何监测点的温湿度数据超过预设阈值时,系统会自动触发控制逻辑。通过5V继电器模块启动通风设备进行调节,同时利用有源蜂鸣器实现声光报警功能,及时提醒操作人员异常情况。
数据上传部分依赖于ESP8266-01S Wi-Fi模块,该模块将实时温湿度数据及报警信息传输至华为云物联网平台,实现远程监控和数据存储。华为云平台提供数据管理和接口支持,便于后续分析和集成。
QT上位机软件负责可视化显示,实时展示各监测点的温湿度变化趋势、设备运行状态及报警历史,为用户提供直观的操作界面和数据分析工具。
硬件方面,系统采用洞洞板焊接电源管理电路,为各模块提供稳定的5V和3.3V电源,并通过杜邦线连接传感器、继电器、蜂鸣器和Wi-Fi模块,确保整体结构紧凑且可靠,适用于工业生产线环境。
系统总体设计
系统采用STM32F103C8T6最小系统核心板作为主控制器,负责协调整个监控系统的运行。该系统通过三个DHT22高精度温湿度传感器实时采集生产线环境的温度和湿度数据,这些传感器分布在多个监测点,以确保全面覆盖生产区域。主控制器定期轮询传感器数据,并进行初步处理,为后续的阈值判断和数据上传做准备。
当采集到的温湿度数据超过预设阈值时,系统会自动触发响应机制。主控制器通过GPIO口控制5V继电器模块,从而启动或停止通风设备,以调节环境条件。同时,有源蜂鸣器被激活,发出声光报警信号,提醒操作人员注意异常情况,确保生产线安全。
实时采集的数据和报警信息通过ESP8266-01S Wi-Fi模块传输至华为云物联网平台。主控制器将数据格式化为MQTT协议或其他兼容格式,通过串口与Wi-Fi模块通信,实现无线数据传输。华为云平台接收并存储这些数据,为远程监控和数据分析提供基础。
QT上位机软件从华为云平台获取数据,并图形化显示各监测点的温湿度变化趋势及设备运行状态。用户可以通过上位机界面实时查看历史数据曲线、报警记录和设备控制状态,从而实现对生产环境的可视化监控和管理。整个系统的电源管理通过洞洞板焊接的电路实现,使用杜邦线连接各模块,确保稳定供电和信号传输。
系统功能总结
功能 | 描述 |
---|---|
温湿度采集 | 使用3个DHT22传感器进行多点实时监测生产线环境温湿度数据 |
阈值报警与通风控制 | 当数据超过设定阈值时,自动启动5V继电器控制通风设备,并通过有源蜂鸣器报警 |
云平台数据上传 | 通过ESP8266-01S Wi-Fi模块将实时数据和报警信息上传至华为云物联网平台 |
上位机数据显示与监控 | QT上位机软件接收数据并显示各监测点数据变化趋势及设备运行状态 |
系统功能总结
功能描述 | 实现方式 |
---|---|
多点采集生产线环境温湿度数据 | 使用STM32F103C8T6主控制器和3个DHT22传感器进行实时采集 |
数据超过设定阈值时自动启动通风设备并报警 | STM32控制5V继电器模块启动通风设备,有源蜂鸣器实现声光报警 |
实时数据与报警信息上传至华为云物联网平台 | 通过ESP8266-01S Wi-Fi模块实现数据上传到华为云平台 |
QT上位机显示各监测点数据变化趋势及设备运行状态 | 数据从华为云平台获取,QT软件进行可视化显示和状态监控 |
设计的各个功能模块描述
STM32F103C8T6最小系统核心板作为主控制器,负责协调整个系统的运行,包括读取传感器数据、处理逻辑判断、控制外设设备以及管理通信模块。它通过GPIO接口与各模块连接,执行程序逻辑以实现温湿度监控和报警功能。
三个DHT22高精度温湿度传感器用于多点采集生产线环境的温度和湿度数据。这些传感器通过数字信号输出,提供准确的测量值,主控制器定期轮询读取数据,确保实时监测多个点的环境条件。
5V继电器模块用于控制通风设备的启停。当主控制器检测到温湿度数据超过设定阈值时,会触发继电器开关,从而接通或断开通风设备的电源,实现自动控制功能。
有源蜂鸣器模块实现声光报警功能。在数据异常时,主控制器驱动蜂鸣器发出声音警报,同时可能结合LED指示,提供直观的报警反馈,确保现场人员及时注意到异常情况。
ESP8266-01S Wi-Fi模块负责与华为云物联网平台进行数据传输。主控制器将采集到的温湿度数据和报警信息通过串口发送给Wi-Fi模块,模块连接到网络后上传数据到云平台,实现远程监控和数据存储。
电源管理电路焊接在洞洞板上,为整个系统提供稳定的5V和3.3V电源供应。它确保各模块正常工作,包括传感器、主控制器和通信模块,通过合理的电源分配和滤波电路避免电压波动影响系统性能。
设计的各个功能模块描述
主控制器模块基于STM32F103C8T6最小系统核心板,作为系统的核心处理单元,负责初始化和管理所有外设。它通过GPIO接口读取传感器数据、执行阈值比较算法,并控制继电器和蜂鸣器等设备,确保整个监控逻辑的协调运行。
温湿度采集模块使用三个DHT22高精度传感器,部署在生产线的关键位置,实现多点环境监测。每个DHT22通过单总线协议与STM32通信,定期采集温湿度数据,并由STM32进行数据处理和存储,保证数据的准确性和实时性。
报警与控制模块集成5V继电器和有源蜂鸣器。当温湿度数据超出预设阈值时,STM32输出控制信号,使继电器动作以启动或停止通风设备,同时触发蜂鸣器发出声光报警,及时响应异常情况并提醒操作人员。
数据传输模块依靠ESP8266-01S Wi-Fi模块,通过串口与STM32连接。STM32将采集的数据和报警信息打包后,通过AT指令控制ESP8266连接到无线网络,并将数据上传至华为云物联网平台,实现远程数据监控和管理。
电源管理模块通过洞洞板焊接电路实现,提供稳定的5V和3.3V电源输出,为STM32、传感器、继电器和Wi-Fi模块供电。杜邦线用于灵活连接各功能模块,确保电气连接的可靠性和便于系统调试与维护。
数据上传至华为云平台后,可通过QT开发的上位机软件从云端获取信息,实时显示各监测点的温湿度变化趋势和设备运行状态,完成远程可视化监控。
上位机代码设计
#include <QApplication>
#include <QMainWindow>
#include <QChartView>
#include <QLineSeries>
#include <QValueAxis>
#include <QDateTimeAxis>
#include <QGridLayout>
#include <QLabel>
#include <QStatusBar>
#include <QMessageBox>
#include <QtMqtt/QMqttClient>
#include <QJsonDocument>
#include <QJsonObject>
#include <QTimer>
QT_CHARTS_USE_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
// 初始化MQTT客户端
mqttClient = new QMqttClient(this);
mqttClient->setHostname("你的华为云MQTT地址"); // 需替换实际地址
mqttClient->setPort(1883);
mqttClient->setClientId("QTMonitorClient");
mqttClient->setUsername("设备ID"); // 需替换实际设备ID
mqttClient->setPassword("设备密钥"); // 需替换实际密钥
setupUI();
setupConnections();
mqttClient->connectToHost();
}
private slots:
void onConnected() {
statusBar()->showMessage("已连接到华为云平台");
mqttClient->subscribe("temperature/topic"); // 需替换实际主题
mqttClient->subscribe("humidity/topic"); // 需替换实际主题
mqttClient->subscribe("alert/topic"); // 需替换实际主题
}
void messageReceived(const QByteArray &message, const QString &topic) {
QJsonDocument doc = QJsonDocument::fromJson(message);
QJsonObject obj = doc.object();
if (topic.contains("temperature")) {
updateTemperatureChart(obj["value"].toDouble(), obj["sensor_id"].toString());
} else if (topic.contains("humidity")) {
updateHumidityChart(obj["value"].toDouble(), obj["sensor_id"].toString());
} else if (topic.contains("alert")) {
handleAlert(message);
}
}
private:
void setupUI() {
// 创建温度图表
temperatureChart = new QChart();
temperatureView = new QChartView(temperatureChart);
// 创建湿度图表
humidityChart = new QChart();
humidityView = new QChartView(humidityChart);
// 创建状态标签
statusLabel = new QLabel("系统状态: 初始化中");
fanStatusLabel = new QLabel("通风设备: 关闭");
alertLabel = new QLabel("报警状态: 正常");
QWidget *centralWidget = new QWidget(this);
QGridLayout *layout = new QGridLayout(centralWidget);
layout->addWidget(new QLabel("温度监控"), 0, 0);
layout->addWidget(temperatureView, 1, 0);
layout->addWidget(new QLabel("湿度监控"), 0, 1);
layout->addWidget(humidityView, 1, 1);
layout->addWidget(statusLabel, 2, 0);
layout->addWidget(fanStatusLabel, 2, 1);
layout->addWidget(alertLabel, 3, 0, 1, 2);
setCentralWidget(centralWidget);
resize(1200, 800);
}
void setupConnections() {
connect(mqttClient, &QMqttClient::connected, this, &MainWindow::onConnected);
connect(mqttClient, &QMqttClient::messageReceived, this, &MainWindow::messageReceived);
}
void updateTemperatureChart(double value, const QString &sensorId) {
// 实现温度数据更新逻辑
QLineSeries *series = temperatureSeries.value(sensorId);
if (!series) {
series = new QLineSeries();
series->setName(sensorId);
temperatureChart->addSeries(series);
// 配置坐标轴等
}
// 添加数据点
series->append(QDateTime::currentDateTime().toMSecsSinceEpoch(), value);
}
void updateHumidityChart(double value, const QString &sensorId) {
// 实现湿度数据更新逻辑(类似温度)
}
void handleAlert(const QByteArray &message) {
QMessageBox::warning(this, "报警提示", QString("检测到异常: %1").arg(QString(message)));
alertLabel->setText("报警状态: 异常!");
}
QMqttClient *mqttClient;
QChart *temperatureChart;
QChart *humidityChart;
QChartView *temperatureView;
QChartView *humidityView;
QLabel *statusLabel;
QLabel *fanStatusLabel;
QLabel *alertLabel;
QMap<QString, QLineSeries*> temperatureSeries;
QMap<QString, QLineSeries*> humiditySeries;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow window;
window.show();
return app.exec();
}
#include "main.moc"
注意:此代码需要以下配置:
- 1. 在Qt项目文件(.pro)中添加:
QT += charts mqtt
- 2. 替换实际的华为云连接参数(MQTT地址、设备ID和密钥)
- 3. 根据实际MQTT主题调整订阅主题
- 4. 可能需要添加数据过滤和处理逻辑
- 5. 需要实现图表坐标轴的动态调整功能
- 6. 建议添加连接状态监控和重连机制
此代码提供了基本框架,实际部署时需要根据具体通信协议和数据格式进行调整。
上位机代码设计
// main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMqttClient>
#include <QChart>
#include <QChartView>
#include <QLineSeries>
#include <QValueAxis>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QWidget>
QT_CHARTS_USE_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void onConnected();
void onMessageReceived(const QByteArray &message, const QMqttTopicName &topic);
void onAlarmReceived(bool alarm);
private:
void setupMQTT();
void setupUI();
QMqttClient *m_client;
QChart *temperatureChart;
QChart *humidityChart;
QLineSeries *tempSeries;
QLineSeries *humSeries;
QChartView *tempChartView;
QChartView *humChartView;
QLabel *tempLabel;
QLabel *humLabel;
QLabel *relayStatusLabel;
QLabel *alarmStatusLabel;
};
#endif // MAINWINDOW_H
// mainwindow.cpp
#include "mainwindow.h"
#include <QMqttSubscription>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
#include <QDateTime>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
setupUI();
setupMQTT();
}
MainWindow::~MainWindow()
{
delete m_client;
}
void MainWindow::setupUI()
{
QWidget *centralWidget = new QWidget(this);
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
// Labels for current values and status
tempLabel = new QLabel("Temperature: -- °C", this);
humLabel = new QLabel("Humidity: -- %", this);
relayStatusLabel = new QLabel("Relay: Off", this);
alarmStatusLabel = new QLabel("Alarm: Off", this);
mainLayout->addWidget(tempLabel);
mainLayout->addWidget(humLabel);
mainLayout->addWidget(relayStatusLabel);
mainLayout->addWidget(alarmStatusLabel);
// Charts for trends
temperatureChart = new QChart();
temperatureChart->setTitle("Temperature Trend");
tempSeries = new QLineSeries();
temperatureChart->addSeries(tempSeries);
QValueAxis *axisX = new QValueAxis();
axisX->setTitleText("Time (s)");
axisX->setLabelFormat("%i");
QValueAxis *axisY = new QValueAxis();
axisY->setTitleText("Temperature (°C)");
temperatureChart->addAxis(axisX, Qt::AlignBottom);
temperatureChart->addAxis(axisY, Qt::AlignLeft);
tempSeries->attachAxis(axisX);
tempSeries->attachAxis(axisY);
tempChartView = new QChartView(temperatureChart);
tempChartView->setRenderHint(QPainter::Antialiasing);
mainLayout->addWidget(tempChartView);
humidityChart = new QChart();
humidityChart->setTitle("Humidity Trend");
humSeries = new QLineSeries();
humidityChart->addSeries(humSeries);
QValueAxis *hAxisX = new QValueAxis();
hAxisX->setTitleText("Time (s)");
hAxisX->setLabelFormat("%i");
QValueAxis *hAxisY = new QValueAxis();
hAxisY->setTitleText("Humidity (%)");
humidityChart->addAxis(hAxisX, Qt::AlignBottom);
humidityChart->addAxis(hAxisY, Qt::AlignLeft);
humSeries->attachAxis(hAxisX);
humSeries->attachAxis(hAxisY);
humChartView = new QChartView(humidityChart);
humChartView->setRenderHint(QPainter::Antialiasing);
mainLayout->addWidget(humChartView);
setCentralWidget(centralWidget);
resize(800, 600);
}
void MainWindow::setupMQTT()
{
m_client = new QMqttClient(this);
m_client->setHostName("iot-mqtts.cn-north-4.myhuaweicloud.com"); // Huawei Cloud MQTT broker address
m_client->setPort(1883);
m_client->setClientId("upper_machine_001"); // Change to unique client ID
// Set username and password as per Huawei Cloud device credentials
// m_client->setUsername("your_username");
// m_client->setPassword("your_password");
connect(m_client, &QMqttClient::connected, this, &MainWindow::onConnected);
connect(m_client, &QMqttClient::messageReceived, this, &MainWindow::onMessageReceived);
m_client->connectToHost();
}
void MainWindow::onConnected()
{
QString topic = "$oc/devices/your_device_id/sys/properties/report"; // Replace with actual device topic
auto subscription = m_client->subscribe(topic);
if (!subscription) {
QMessageBox::critical(this, "Error", "Subscription failed");
}
}
void MainWindow::onMessageReceived(const QByteArray &message, const QMqttTopicName &topic)
{
QJsonDocument doc = QJsonDocument::fromJson(message);
if (doc.isObject()) {
QJsonObject obj = doc.object();
if (obj.contains("services")) {
QJsonArray services = obj["services"].toArray();
for (const auto &service : services) {
QJsonObject serviceObj = service.toObject();
if (serviceObj["service_id"] == "sensor") {
QJsonObject properties = serviceObj["properties"].toObject();
double temperature = properties["temperature"].toDouble();
double humidity = properties["humidity"].toDouble();
bool alarm = properties["alarm"].toBool();
bool relay = properties["relay"].toBool();
tempLabel->setText(QString("Temperature: %1 °C").arg(temperature));
humLabel->setText(QString("Humidity: %1 %").arg(humidity));
relayStatusLabel->setText(QString("Relay: %1").arg(relay ? "On" : "Off"));
alarmStatusLabel->setText(QString("Alarm: %1").arg(alarm ? "On" : "Off"));
qint64 time = QDateTime::currentSecsSinceEpoch();
tempSeries->append(time, temperature);
humSeries->append(time, humidity);
// Adjust chart axes if needed
temperatureChart->axes(Qt::Horizontal).first()->setRange(time - 60, time);
humidityChart->axes(Qt::Horizontal).first()->setRange(time - 60, time);
if (alarm) {
onAlarmReceived(true);
}
}
}
}
}
}
void MainWindow::onAlarmReceived(bool alarm)
{
if (alarm) {
alarmStatusLabel->setStyleSheet("color: red;");
QMessageBox::warning(this, "Alarm", "Threshold exceeded! Ventilation activated.");
} else {
alarmStatusLabel->setStyleSheet("");
}
}
# project.pro
QT += core gui mqtt charts
CONFIG += c++17
TARGET = IndustrialMonitor
TEMPLATE = app
SOURCES += main.cpp \
mainwindow.cpp
HEADERS += mainwindow.h
模块代码设计
#include "stm32f10x.h"
// 引脚定义
#define DHT22_1_GPIO_PORT GPIOA
#define DHT22_1_GPIO_PIN GPIO_Pin_0
#define DHT22_2_GPIO_PORT GPIOA
#define DHT22_2_GPIO_PIN GPIO_Pin_1
#define DHT22_3_GPIO_PORT GPIOA
#define DHT22_3_GPIO_PIN GPIO_Pin_2
#define RELAY_GPIO_PORT GPIOB
#define RELAY_GPIO_PIN GPIO_Pin_0
#define BUZZER_GPIO_PORT GPIOB
#define BUZZER_GPIO_PIN GPIO_Pin_1
// 阈值定义
#define TEMP_THRESHOLD 30.0f // 温度阈值,单位:摄氏度
#define HUMIDITY_THRESHOLD 80.0f // 湿度阈值,单位:百分比
// USART1 for ESP8266
#define USART1_GPIO_PORT GPIOA
#define USART1_TX_PIN GPIO_Pin_9
#define USART1_RX_PIN GPIO_Pin_10
// 华为云物联网平台参数(需根据实际修改)
#define MQTT_SERVER "your_mqtt_server"
#define MQTT_PORT "1883"
#define DEVICE_ID "your_device_id"
#define MQTT_USER "your_username"
#define MQTT_PASSWORD "your_password"
#define MQTT_TOPIC_DATA "topic/data"
#define MQTT_TOPIC_ALARM "topic/alarm"
// 全局变量
volatile uint32_t msTicks = 0; // 毫秒计时器
// 函数声明
void SystemInit(void);
void GPIO_Init(void);
void USART1_Init(void);
void SysTick_Init(void);
void Delay_ms(uint32_t ms);
void Delay_us(uint32_t us);
uint8_t DHT22_Read(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, float *temperature, float *humidity);
void Relay_Control(uint8_t state);
void Buzzer_Control(uint8_t state);
void ESP8266_SendCommand(char *cmd);
void ESP8266_Init(void);
void ESP8266_SendData(float temp1, float humid1, float temp2, float humid2, float temp3, float humid3, uint8_t alarm);
int USART1_SendChar(char ch);
void USART1_SendString(char *str);
// 系统初始化
void SystemInit(void) {
// 设置系统时钟为72MHz(假设使用内部RC或外部晶体,这里简化)
RCC->CFGR |= RCC_CFGR_PLLMULL9; // PLL multiplier 9
RCC->CFGR |= RCC_CFGR_PLLSRC; // PLL source HSE
RCC->CR |= RCC_CR_HSEON; // Enable HSE
while(!(RCC->CR & RCC_CR_HSERDY)); // Wait for HSE ready
RCC->CR |= RCC_CR_PLLON; // Enable PLL
while(!(RCC->CR & RCC_CR_PLLRDY)); // Wait for PLL ready
RCC->CFGR |= RCC_CFGR_SW_PLL; // Switch to PLL
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait for switch
}
// GPIO初始化
void GPIO_Init(void) {
// 使能GPIOA和GPIOB时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
// 配置DHT22引脚为推挽输出(初始状态),但读取时需要切换为输入
GPIOA->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_CNF1 | GPIO_CRL_CNF2); // Clear CNF for PA0, PA1, PA2
GPIOA->CRL |= (GPIO_CRL_MODE0 | GPIO_CRL_MODE1 | GPIO_CRL_MODE2); // Output mode, max speed 50MHz
// 配置继电器和蜂鸣器引脚为推挽输出
GPIOB->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_CNF1); // Clear CNF for PB0, PB1
GPIOB->CRL |= (GPIO_CRL_MODE0 | GPIO_CRL_MODE1); // Output mode, max speed 50MHz
// 初始状态:继电器关闭,蜂鸣器关闭
Relay_Control(0);
Buzzer_Control(0);
}
// USART1初始化
void USART1_Init(void) {
// 使能USART1时钟
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// 配置PA9为推挽复用输出(TX),PA10为浮空输入(RX)
USART1_GPIO_PORT->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_CNF10 | GPIO_CRH_MODE9 | GPIO_CRH_MODE10);
USART1_GPIO_PORT->CRH |= (GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9); // AF Push-Pull for PA9
USART1_GPIO_PORT->CRH |= GPIO_CRH_CNF10_0; // Input floating for PA10
// 配置USART1: 115200 baud, 8 data bits, no parity, 1 stop bit
USART1->BRR = 72000000 / 115200; // 72MHz / 115200 ≈ 625
USART1->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; // Enable USART, TX, RX
}
// SysTick初始化
void SysTick_Init(void) {
SysTick->LOAD = 72000 - 1; // 72MHz/1000 = 72000, 1ms interrupt
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
}
// 毫秒延时
void Delay_ms(uint32_t ms) {
uint32_t start = msTicks;
while ((msTicks - start) < ms);
}
// 微秒延时(循环延时,基于72MHz系统时钟)
void Delay_us(uint32_t us) {
us *= 72; // 72 cycles per microsecond at 72MHz
while (us--) {
__NOP();
}
}
// DHT22读取函数
uint8_t DHT22_Read(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, float *temperature, float *humidity) {
uint8_t data[5] = {0};
uint8_t i, j;
// 设置引脚为输出模式
if (GPIOx == GPIOA) {
if (GPIO_Pin == GPIO_Pin_0) GPIOA->CRL |= GPIO_CRL_MODE0;
else if (GPIO_Pin == GPIO_Pin_1) GPIOA->CRL |= GPIO_CRL_MODE1;
else if (GPIO_Pin == GPIO_Pin_2) GPIOA->CRL |= GPIO_CRL_MODE2;
}
// 发送起始信号:拉低至少1ms,然后拉高20-40us
GPIOx->BRR = GPIO_Pin; // Set pin low
Delay_ms(2); // 拉低2ms
GPIOx->BSRR = GPIO_Pin; // Set pin high
Delay_us(30); // 拉高30us
// 设置引脚为输入模式
if (GPIOx == GPIOA) {
if (GPIO_Pin == GPIO_Pin_0) GPIOA->CRL &= ~GPIO_CRL_MODE0;
else if (GPIO_Pin == GPIO_Pin_1) GPIOA->CRL &= ~GPIO_CRL_MODE1;
else if (GPIO_Pin == GPIO_Pin_2) GPIOA->CRL &= ~GPIO_CRL_MODE2;
}
// 等待DHT22响应
Delay_us(40);
if (GPIOx->IDR & GPIO_Pin) return 0; // 应该为低电平
while (!(GPIOx->IDR & GPIO_Pin)); // 等待高电平
while (GPIOx->IDR & GPIO_Pin); // 等待低电平,开始数据传输
// 读取40位数据
for (i = 0; i < 5; i++) {
for (j = 0; j < 8; j++) {
while (!(GPIOx->IDR & GPIO_Pin)); // 等待高电平
Delay_us(35); // 延时35us后检查电平
if (GPIOx->IDR & GPIO_Pin) {
data[i] |= (1 << (7 - j));
while (GPIOx->IDR & GPIO_Pin); // 等待低电平
}
}
}
// 校验和检查
if (data[4] != (data[0] + data[1] + data[2] + data[3])) {
return 0;
}
// 转换温度和湿度值
*humidity = (float)((data[0] << 8) | data[1]) / 10.0f;
*temperature = (float)((data[2] << 8) | data[3]) / 10.0f;
return 1;
}
// 继电器控制
void Relay_Control(uint8_t state) {
if (state) {
RELAY_GPIO_PORT->BSRR = RELAY_GPIO_PIN; // Set high
} else {
RELAY_GPIO_PORT->BRR = RELAY_GPIO_PIN; // Set low
}
}
// 蜂鸣器控制
void Buzzer_Control(uint8_t state) {
if (state) {
BUZZER_GPIO_PORT->BSRR = BUZZER_GPIO_PIN; // Set high
} else {
BUZZER_GPIO_PORT->BRR = BUZZER_GPIO_PIN; // Set low
}
}
// USART1发送字符
int USART1_SendChar(char ch) {
while (!(USART1->SR & USART_SR_TXE)); // Wait for TX empty
USART1->DR = ch;
return ch;
}
// USART1发送字符串
void USART1_SendString(char *str) {
while (*str) {
USART1_SendChar(*str++);
}
}
// ESP8266发送AT命令
void ESP8266_SendCommand(char *cmd) {
USART1_SendString(cmd);
USART1_SendString("\r\n");
Delay_ms(1000); // 等待响应
}
// ESP8266初始化
void ESP8266_Init(void) {
Delay_ms(2000); // 等待ESP8266启动
ESP8266_SendCommand("AT"); // 测试AT命令
ESP8266_SendCommand("AT+CWMODE=1"); // 设置station模式
ESP8266_SendCommand("AT+CWJAP=\"your_SSID\",\"your_password\""); // 连接Wi-Fi,需修改
ESP8266_SendCommand("AT+MQTTUSERCFG=0,1,\"clientID\",\"MQTT_USER\",\"MQTT_PASSWORD\",0,0,\"\""); // MQTT配置,需修改
ESP8266_SendCommand("AT+MQTTCONN=0,\"MQTT_SERVER\",1883,1"); // 连接MQTT服务器,需修改
}
// ESP8266发送数据到华为云
void ESP8266_SendData(float temp1, float humid1, float temp2, float humid2, float temp3, float humid3, uint8_t alarm) {
char buffer[100];
// 构建JSON数据字符串
sprintf(buffer, "AT+MQTTPUB=0,\"MQTT_TOPIC_DATA\",\"{\\\"temp1\\\":%.1f,\\\"humid1\\\":%.1f,\\\"temp2\\\":%.1f,\\\"humid2\\\":%.1f,\\\"temp3\\\":%.1f,\\\"humid3\\\":%.1f,\\\"alarm\\\":%d}\",0,0",
temp1, humid1, temp2, humid2, temp3, humid3, alarm);
ESP8266_SendCommand(buffer);
if (alarm) {
sprintf(buffer, "AT+MQTTPUB=0,\"MQTT_TOPIC_ALARM\",\"Alarm triggered! Temperature or humidity exceeded threshold.\",0,0");
ESP8266_SendCommand(buffer);
}
}
// 主函数
int main(void) {
SystemInit();
GPIO_Init();
USART1_Init();
SysTick_Init();
ESP8266_Init();
float temp1, humid1, temp2, humid2, temp3, humid3;
uint8_t alarm = 0;
while (1) {
// 读取三个DHT22传感器
if (DHT22_Read(DHT22_1_GPIO_PORT, DHT22_1_GPIO_Pin, &temp1, &humid1) &&
DHT22_Read(DHT22_2_GPIO_PORT, DHT22_2_GPIO_Pin, &temp2, &humid2) &&
DHT22_Read(DHT22_3_GPIO_PORT, DHT22_3_GPIO_Pin, &temp3, &humid3)) {
// 检查阈值
if (temp1 > TEMP_THRESHOLD || temp2 > TEMP_THRESHOLD || temp3 > TEMP_THRESHOLD ||
humid1 > HUMIDITY_THRESHOLD || humid2 > HUMIDITY_THRESHOLD || humid3 > HUMIDITY_THRESHOLD) {
alarm = 1;
Relay_Control(1); // 启动继电器
Buzzer_Control(1); // 启动蜂鸣器
} else {
alarm = 0;
Relay_Control(0); // 关闭继电器
Buzzer_Control(0); // 关闭蜂鸣器
}
// 发送数据到华为云
ESP8266_SendData(temp1, humid1, temp2, humid2, temp3, humid3, alarm);
} else {
// 读取失败处理
alarm = 1; // 视为报警
Buzzer_Control(1);
}
Delay_ms(5000); // 每5秒读取一次
}
}
// SysTick中断处理函数
void SysTick_Handler(void) {
msTicks++;
}
项目核心代码
#include "stm32f10x.h"
// 外部函数声明
extern void DHT22_Init(void);
extern void DHT22_Read(uint8_t sensor_id, float *temperature, float *humidity);
extern void ESP8266_Init(void);
extern void ESP8266_SendData(float temperature, float humidity, uint8_t alarm_status);
extern void Relay_Control(uint8_t state);
extern void Buzzer_Control(uint8_t state);
// 定义引脚和阈值
#define RELAY_PIN GPIO_Pin_0
#define BUZZER_PIN GPIO_Pin_1
#define THRESHOLD_TEMP 30.0f
#define THRESHOLD_HUM 80.0f
// 全局变量
float temperature[3];
float humidity[3];
uint8_t alarm_status = 0;
void GPIO_Init(void) {
// 使能GPIOA时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// 配置PA0(继电器)和PA1(蜂鸣器)为推挽输出,最大速度50MHz
GPIOA->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_MODE0);
GPIOA->CRL |= (GPIO_CRL_MODE0_0 | GPIO_CRL_MODE0_1);
GPIOA->CRL &= ~(GPIO_CRL_CNF1 | GPIO_CRL_MODE1);
GPIOA->CRL |= (GPIO_CRL_MODE1_0 | GPIO_CRL_MODE1_1);
// 初始状态关闭
GPIOA->BRR = RELAY_PIN;
GPIOA->BRR = BUZZER_PIN;
}
void USART1_Init(void) {
// 使能USART1时钟
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// 配置PA9为USART1 TX(推挽复用输出),PA10为USART1 RX(浮空输入)
GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_MODE9);
GPIOA->CRH |= (GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_0 | GPIO_CRH_MODE9_1);
GPIOA->CRH &= ~(GPIO_CRH_CNF10 | GPIO_CRH_MODE10);
GPIOA->CRH |= GPIO_CRH_CNF10_0;
// 设置波特率为9600(假设系统时钟72MHz)
USART1->BRR = 0x1D4C; // 7500 decimal
// 使能USART1,发送器和接收器
USART1->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
}
void SystemInit(void) {
// 简单的系统时钟初始化,假设使用HSI 8MHz
// 如需更高时钟,需配置PLL,此处简化
RCC->CR |= RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY));
RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= RCC_CFGR_SW_HSI;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI);
}
int main(void) {
SystemInit();
GPIO_Init();
USART1_Init();
DHT22_Init();
ESP8266_Init();
while(1) {
for (int i = 0; i < 3; i++) {
DHT22_Read(i, &temperature[i], &humidity[i]);
}
alarm_status = 0;
for (int i = 0; i < 3; i++) {
if (temperature[i] > THRESHOLD_TEMP || humidity[i] > THRESHOLD_HUM) {
alarm_status = 1;
break;
}
}
if (alarm_status) {
Relay_Control(1);
Buzzer_Control(1);
} else {
Relay_Control(0);
Buzzer_Control(0);
}
for (int i = 0; i < 3; i++) {
ESP8266_SendData(temperature[i], humidity[i], alarm_status);
}
for (volatile int j = 0; j < 1000000; j++);
}
}
总结
该系统基于STM32F103C8T6微控制器核心板,成功实现了工业生产线环境温湿度的多点监控功能。通过部署三个DHT22高精度传感器,系统能够实时采集生产线各点的温湿度数据,并在数据超出设定阈值时自动启动通风设备并通过有源蜂鸣器触发声光报警,从而确保生产环境的稳定与安全。
硬件组成方面,系统整合了STM32F103C8T6最小系统板作为主控制器,配合DHT22传感器、5V继电器模块和有源蜂鸣器,构建了完整的监测与控制链条。ESP8266-01S Wi-Fi模块负责将实时数据与报警信息传输至华为云物联网平台,而洞洞板焊接的电源管理电路和杜邦线连接确保了各模块的可靠供电和信号传输。
系统与华为云平台的集成实现了数据的远程上传和存储,同时QT上位机软件提供了直观的数据可视化界面,实时显示各监测点的温湿度变化趋势及设备运行状态,大大增强了监控的便捷性和响应速度。
总体而言,该设计硬件选型经济实用,软件功能完备,不仅提升了工业生产线环境监控的自动化水平,还通过云平台和上位机增强了系统的智能化和可扩展性,具有较高的实用价值和推广前景。
模块代码设计
#include "stm32f10x.h" // 虽然使用寄存器方式,但包含头文件以获取寄存器定义,实际开发中可自行定义寄存器地址
// 定义使用的GPIO引脚
#define DHT22_1_GPIO_PORT GPIOA
#define DHT22_1_GPIO_PIN GPIO_Pin_0
#define DHT22_2_GPIO_PORT GPIOA
#define DHT22_2_GPIO_PIN GPIO_Pin_1
#define DHT22_3_GPIO_PORT GPIOA
#define DHT22_3_GPIO_PIN GPIO_Pin_2
#define RELAY_GPIO_PORT GPIOA
#define RELAY_GPIO_PIN GPIO_Pin_3
#define BUZZER_GPIO_PORT GPIOA
#define BUZZER_GPIO_PIN GPIO_Pin_4
// ESP8266使用USART1,引脚PA9(TX), PA10(RX)
#define ESP8266_USART USART1
// 温湿度阈值定义
#define TEMP_THRESHOLD 30.0f // 温度阈值30°C
#define HUMID_THRESHOLD 80.0f // 湿度阈值80%
// 函数声明
void SystemClock_Config(void);
void GPIO_Config(void);
void USART_Config(void);
void Delay_Init(void);
void delay_us(uint32_t us);
void delay_ms(uint32_t ms);
uint8_t DHT22_Read(float *temperature, float *humidity, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void ESP8266_Init(void);
void ESP8266_SendCmd(char *cmd);
void ESP8266_SendData(char *data);
void Control_Devices(uint8_t state);
int main(void) {
SystemClock_Config(); // 配置系统时钟为72MHz
GPIO_Config(); // 配置GPIO
USART_Config(); // 配置USART
Delay_Init(); // 初始化延时函数
ESP8266_Init(); // 初始化ESP8266,连接Wi-Fi和华为云
float temp1, humid1, temp2, humid2, temp3, humid3;
uint8_t alert_state = 0;
while(1) {
// 读取三个DHT22传感器
if(DHT22_Read(&temp1, &humid1, DHT22_1_GPIO_PORT, DHT22_1_GPIO_PIN) &&
DHT22_Read(&temp2, &humid2, DHT22_2_GPIO_PORT, DHT22_2_GPIO_PIN) &&
DHT22_Read(&temp3, &humid3, DHT22_3_GPIO_PORT, DHT22_3_GPIO_PIN)) {
// 检查是否超过阈值
if(temp1 > TEMP_THRESHOLD || humid1 > HUMID_THRESHOLD ||
temp2 > TEMP_THRESHOLD || humid2 > HUMID_THRESHOLD ||
temp3 > TEMP_THRESHOLD || humid3 > HUMID_THRESHOLD) {
alert_state = 1;
Control_Devices(1); // 开启继电器和蜂鸣器
} else {
alert_state = 0;
Control_Devices(0); // 关闭继电器和蜂鸣器
}
// 准备上传数据到华为云,这里以字符串形式模拟,实际需按华为云协议格式
char data[100];
sprintf(data, "{\"temp1\":%.1f,\"humid1\":%.1f,\"temp2\":%.1f,\"humid2\":%.1f,\"temp3\":%.1f,\"humid3\":%.1f,\"alert\":%d}",
temp1, humid1, temp2, humid2, temp3, humid3, alert_state);
ESP8266_SendData(data); // 发送数据
}
delay_ms(5000); // 每5秒读取一次
}
}
// 系统时钟配置:使用HSE和PLL,系统时钟72MHz
void SystemClock_Config(void) {
// 启用HSE
RCC->CR |= RCC_CR_HSEON;
while(!(RCC->CR & RCC_CR_HSERDY));
// 配置PLL:HSE作为输入,倍频到72MHz
RCC->CFGR |= RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9;
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);
// 设置APB1、APB2、AHB分频
RCC->CFGR |= RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_HPRE_DIV1;
}
// GPIO配置
void GPIO_Config(void) {
// 启用GPIOA时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// 配置DHT22引脚为推挽输出(暂时,读取时会切换)
GPIOA->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_CNF1 | GPIO_CRL_CNF2 | GPIO_CRL_MODE0 | GPIO_CRL_MODE1 | GPIO_CRL_MODE2);
GPIOA->CRL |= GPIO_CRL_MODE0_0 | GPIO_CRL_MODE1_0 | GPIO_CRL_MODE2_0; // 输出模式,最大速度10MHz
// 配置继电器和蜂鸣器引脚为推挽输出
GPIOA->CRL &= ~(GPIO_CRL_CNF3 | GPIO_CRL_CNF4 | GPIO_CRL_MODE3 | GPIO_CRL_MODE4);
GPIOA->CRL |= GPIO_CRL_MODE3_0 | GPIO_CRL_MODE4_0; // 输出模式,最大速度10MHz
// 配置USART1引脚PA9(TX)为推挽复用输出,PA10(RX)为浮空输入
GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_CNF10 | GPIO_CRH_MODE9 | GPIO_CRH_MODE10);
GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_0; // PA9: 复用推挽输出,最大速度10MHz
GPIOA->CRH |= GPIO_CRH_CNF10_0; // PA10: 浮空输入
}
// USART配置:波特率115200
void USART_Config(void) {
// 启用USART1时钟
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// 配置波特率:72MHz / 115200 ≈ 625, 所以USARTDIV = 72e6 / (115200 * 16) = 39.0625
// BRR = 39.0625 * 16 = 625 = 0x271
ESP8266_USART->BRR = 0x271;
// 使能USART,TX和RX
ESP8266_USART->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
}
// 初始化延时函数(使用SysTick)
void Delay_Init(void) {
SysTick->LOAD = 72000 - 1; // 72MHz/1000 = 72000, 重载值 for 1ms
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
}
// 微秒延时函数(基于循环,近似)
void delay_us(uint32_t us) {
us *= 72; // 72MHz, 所以72 cycles per us
while(us--) {
__ASM volatile ("nop");
}
}
// 毫秒延时函数(使用SysTick)
void delay_ms(uint32_t ms) {
while(ms--) {
while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
}
}
// DHT22读取函数
uint8_t DHT22_Read(float *temperature, float *humidity, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
uint8_t data[5] = {0};
uint8_t i, j;
// 设置引脚为输出模式
if(GPIO_Pin < 8) {
GPIOx->CRL &= ~(0xF << (4 * GPIO_Pin));
GPIOx->CRL |= (0x3 << (4 * GPIO_Pin)); // 推挽输出,最大速度10MHz
} else {
GPIOx->CRH &= ~(0xF << (4 * (GPIO_Pin - 8)));
GPIOx->CRH |= (0x3 << (4 * (GPIO_Pin - 8)));
}
// 主机发送开始信号:拉低至少18ms,然后拉高20-40us
GPIOx->BRR = GPIO_Pin; // 拉低
delay_ms(18);
GPIOx->BSRR = GPIO_Pin; // 拉高
delay_us(30);
// 设置引脚为输入模式
if(GPIO_Pin < 8) {
GPIOx->CRL &= ~(0xF << (4 * GPIO_Pin));
GPIOx->CRL |= (0x4 << (4 * GPIO_Pin)); // 浮空输入
} else {
GPIOx->CRH &= ~(0xF << (4 * (GPIO_Pin - 8)));
GPIOx->CRH |= (0x4 << (4 * (GPIO_Pin - 8)));
}
// 等待DHT22响应:先拉低80us,然后拉高80us
delay_us(40);
if(GPIOx->IDR & GPIO_Pin) return 0; // 应该为低电平
while(!(GPIOx->IDR & GPIO_Pin)); // 等待变高
while(GPIOx->IDR & GPIO_Pin); // 等待变低
// 读取40位数据
for(i=0; i<5; i++) {
for(j=0; j<8; j++) {
while(!(GPIOx->IDR & GPIO_Pin)); // 等待变高(50us低电平开始)
delay_us(35); // 延迟35us后检查电平
if(GPIOx->IDR & GPIO_Pin) {
data[i] |= (1 << (7 - j));
while(GPIOx->IDR & GPIO_Pin); // 等待变低
}
}
}
// 校验和检查
if(data[4] == (data[0] + data[1] + data[2] + data[3])) {
// 转换数据:湿度是data[0]和data[1],温度是data[2]和data[3]
*humidity = (float)((data[0] << 8) | data[1]) / 10.0f;
*temperature = (float)((data[2] << 8) | data[3]) / 10.0f;
return 1;
}
return 0;
}
// ESP8266初始化:发送AT命令连接Wi-Fi和华为云
void ESP8266_Init(void) {
delay_ms(1000); // 等待ESP8266启动
ESP8266_SendCmd("AT\r\n"); // 测试AT
delay_ms(1000);
ESP8266_SendCmd("AT+CWMODE=1\r\n"); // 设置Station模式
delay_ms(1000);
ESP8266_SendCmd("AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n"); // 连接Wi-Fi,替换为实际SSID和密码
delay_ms(5000);
// 假设华为云使用MQTT,发送连接命令(示例命令,需按华为云文档调整)
ESP8266_SendCmd("AT+MQTTUSERCFG=0,1,\"device_id\",\"username\",\"password\",0,0,\"\"\r\n");
delay_ms(1000);
ESP8266_SendCmd("AT+MQTTCONN=0,\"host\",1883,1\r\n"); // 连接MQTT broker,替换host
delay_ms(1000);
}
// 发送AT命令到ESP8266
void ESP8266_SendCmd(char *cmd) {
while(*cmd) {
while(!(ESP8266_USART->SR & USART_SR_TXE)); // 等待发送缓冲区空
ESP8266_USART->DR = *cmd++;
}
}
// 发送数据到华为云(通过MQTT发布)
void ESP8266_SendData(char *data) {
char cmd[150];
sprintf(cmd, "AT+MQTTPUB=0,\"topic\",\"%s\",1,0\r\n", data); // 替换topic为实际主题
ESP8266_SendCmd(cmd);
}
// 控制继电器和蜂鸣器
void Control_Devices(uint8_t state) {
if(state) {
RELAY_GPIO_PORT->BSRR = RELAY_GPIO_PIN; // 开启继电器
BUZZER_GPIO_PORT->BSRR = BUZZER_GPIO_PIN; // 开启蜂鸣器
} else {
RELAY_GPIO_PORT->BRR = RELAY_GPIO_PIN; // 关闭继电器
BUZZER_GPIO_PORT->BRR = BUZZER_GPIO_PIN; // 关闭蜂鸣器
}
}
项目核心代码
#include "stm32f10x.h"
#include <stdio.h>
#define DHT1_PIN GPIO_Pin_0
#define DHT1_PORT GPIOA
#define DHT2_PIN GPIO_Pin_1
#define DHT2_PORT GPIOA
#define DHT3_PIN GPIO_Pin_2
#define DHT3_PORT GPIOA
#define RELAY_PIN GPIO_Pin_0
#define RELAY_PORT GPIOB
#define BUZZER_PIN GPIO_Pin_1
#define BUZZER_PORT GPIOB
#define TEMP_THRESHOLD 30.0
#define HUMIDITY_THRESHOLD 80.0
void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART1_Configuration(void);
void Systick_Configuration(void);
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
uint8_t DHT22_Read(uint16_t GPIO_Pin, GPIO_TypeDef* GPIO_Port, float *temperature, float *humidity);
void USART1_SendString(char *str);
void Control_Devices(float temp1, float humid1, float temp2, float humid2, float temp3, float humid3);
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
USART1_Configuration();
Systick_Configuration();
float temp1 = 0, humid1 = 0, temp2 = 0, humid2 = 0, temp3 = 0, humid3 = 0;
char data_str[100];
while(1)
{
uint8_t read1 = DHT22_Read(DHT1_PIN, DHT1_PORT, &temp1, &humid1);
uint8_t read2 = DHT22_Read(DHT2_PIN, DHT2_PORT, &temp2, &humid2);
uint8_t read3 = DHT22_Read(DHT3_PIN, DHT3_PORT, &temp3, &humid3);
Control_Devices(temp1, humid1, temp2, humid2, temp3, humid3);
if (read1 == 0 && read2 == 0 && read3 == 0)
{
sprintf(data_str, "T1:%.1f H1:%.1f T2:%.1f H2:%.1f T3:%.1f H3:%.1f\r\n", temp1, humid1, temp2, humid2, temp3, humid3);
USART1_SendString(data_str);
}
else
{
USART1_SendString("Sensor read error\r\n");
}
Delay_ms(2000);
}
}
void RCC_Configuration(void)
{
RCC->CR |= RCC_CR_HSEON;
while(!(RCC->CR & RCC_CR_HSERDY));
RCC->CFGR |= RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9;
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));
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_USART1EN;
}
void GPIO_Configuration(void)
{
GPIOA->CRL &= ~(0xFFF); // Clear PA0, PA1, PA2
GPIOA->CRL |= (0x44 << 0 | 0x44 << 4 | 0x44 << 8); // Input floating for DHT sensors
GPIOB->CRL &= ~(0xFF);
GPIOB->CRL |= (0x33 << 0); // Output push-pull for RELAY and BUZZER
GPIOA->CRH &= ~(0xFF << 4);
GPIOA->CRH |= (0xB << 4) | (0x4 << 8); // PA9: ALT push-pull, PA10: Input floating
}
void USART1_Configuration(void)
{
USART1->BRR = (468 << 4) | 12; // 9600 baud at 72MHz
USART1->CR1 |= USART_CR1_UE | USART_CR1_TE;
}
void Systick_Configuration(void)
{
SysTick->LOAD = 72000 - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
}
void Delay_ms(uint32_t ms)
{
for (uint32_t i = 0; i < ms; i++)
{
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
}
}
void Delay_us(uint32_t us)
{
us = us * 72;
for (uint32_t i = 0; i < us; i++)
{
__NOP();
}
}
uint8_t DHT22_Read(uint16_t GPIO_Pin, GPIO_TypeDef* GPIO_Port, float *temperature, float *humidity)
{
uint8_t data[5] = {0};
uint8_t i, j;
GPIO_Port->CRL &= ~(0xF << (4 * (GPIO_Pin & 0x7)));
GPIO_Port->CRL |= (0x3 << (4 * (GPIO_Pin & 0x7)));
GPIO_Port->BSRR = GPIO_Pin << 16;
Delay_ms(18);
GPIO_Port->BSRR = GPIO_Pin;
Delay_us(30);
GPIO_Port->CRL &= ~(0xF << (4 * (GPIO_Pin & 0x7)));
GPIO_Port->CRL |= (0x4 << (4 * (GPIO_Pin & 0x7)));
while (GPIO_Port->IDR & GPIO_Pin);
while (!(GPIO_Port->IDR & GPIO_Pin));
for (i = 0; i < 5; i++)
{
for (j = 0; j < 8; j++)
{
while (!(GPIO_Port->IDR & GPIO_Pin));
Delay_us(40);
if (GPIO_Port->IDR & GPIO_Pin)
{
data[i] |= (1 << (7 - j));
while (GPIO_Port->IDR & GPIO_Pin);
}
}
}
if (data[4] == (data[0] + data[1] + data[2] + data[3]))
{
*humidity = (data[0] * 256 + data[1]) / 10.0;
*temperature = (data[2] * 256 + data[3]) / 10.0;
return 0;
}
return 1;
}
void USART1_SendString(char *str)
{
while (*str)
{
while (!(USART1->SR & USART_SR_TXE));
USART1->DR = *str++;
}
}
void Control_Devices(float temp1, float humid1, float temp2, float humid2, float temp3, float humid3)
{
if (temp1 > TEMP_THRESHOLD || humid1 > HUMIDITY_THRESHOLD ||
temp2 > TEMP_THRESHOLD || humid2 > HUMIDITY_THRESHOLD ||
temp3 > TEMP_THRESHOLD || humid3 > HUMIDITY_THRESHOLD)
{
GPIOB->BSRR = RELAY_PIN;
GPIOB->BSRR = BUZZER_PIN;
}
else
{
GPIOB->BSRR = RELAY_PIN << 16;
GPIOB->BSRR = BUZZER_PIN << 16;
}
}
总结
本系统基于STM32F103C8T6微控制器和华为云物联网平台,成功实现了工业生产线环境温湿度的多点实时监控。通过集成多个高精度传感器和无线通信模块,系统能够高效采集和处理数据,并在数据超出设定阈值时自动触发通风设备和声光报警,确保生产环境的稳定性和安全性。
硬件方面,系统采用STM32F103C8T6最小系统核心板作为主控,搭配三个DHT22温湿度传感器进行多点监测,5V继电器模块控制通风设备启停,有源蜂鸣器提供报警功能,以及ESP8266-01S Wi-Fi模块实现与华为云平台的数据传输。所有组件通过洞洞板焊接电源管理电路和杜邦线连接,构建了一个紧凑而可靠的硬件平台。
软件层面,系统通过编程实现数据采集、阈值判断和设备控制,并将实时数据与报警信息通过Wi-Fi模块上传至华为云平台。QT上位机软件进一步增强了系统的可视化能力,为用户提供各监测点的数据变化趋势和设备运行状态显示,支持远程监控和决策。
总体而言,该系统提升了工业生产的智能化水平,通过云平台集成实现了数据的集中管理和分析,为工业自动化提供了高效、可靠的解决方案。未来,可进一步扩展传感器类型或集成更多IoT功能,以适应更复杂的工业应用场景。
- 点赞
- 收藏
- 关注作者
评论(0)