基于STM32的智慧农业温室环境监测与联动控制系统
项目开发背景
传统农业温室环境调控主要依赖人工经验,存在监测滞后、控制不精准、人力成本高等问题。尤其在规模化管理中,种植者难以及时掌握每个温室的实时参数变化,导致作物生长环境波动,影响产量和品质。同时,水资源、光照资源和电能的粗放式管理也造成了浪费。
物联网技术的快速发展为解决上述问题提供了契机。将传感器、微控制器、无线通信和云端数据处理相结合,构建智能化监控系统,成为提升现代农业温室管理效率与精准度的必然趋势。通过实时采集关键环境数据并实现远程监控与自动控制,可显著优化作物生长条件。
本项目基于STM32F103C8T6微控制器,整合空气温湿度、土壤湿度、光照强度等传感器,并利用ESP8266模块连接华为云物联网平台,构建了一套完整的智慧农业温室环境监测与联动控制系统。系统不仅能实现环境数据的实时采集、云端存储与远程可视化展示,还提供了手动与自动双模式控制功能,可根据预设阈值自动联动灌溉、补光、通风等设备,并在异常情况时及时报警。该设计旨在提高温室管理的智能化水平,降低人工干预强度,实现精准调控,最终达到增产、提质、节能的目标。
设计实现的功能
(1)STM32F103C8T6主控芯片处理传感器数据并执行控制逻辑。
(2)DHT11传感器采集空气温湿度,YL-69土壤湿度传感器检测土壤水分。
(3)BH1750光照传感器监测温室光照强度。
(4)继电器模块驱动水泵(DC 5V)、补光灯(AC 220V)和通风电机(DC 12V)。
(5)ESP8266 Wi-Fi模块通过MQTT协议连接华为云物联网平台。
(6)QT上位机使用Qt Charts绘制历史数据曲线,通过QMQTT库订阅/发布云平台消息。
项目硬件模块组成
(1)核心控制器:STM32F103C8T6最小系统板
(2)环境传感器:DHT11(温湿度)、YL-69(土壤湿度)、BH1750(光照强度)
(3)执行设备:5V继电器模块(控制水泵)、2路继电器模块(控制补光灯/通风)
(4)通信模块:ESP8266-01S Wi-Fi模组(串口AT指令)
(5)电源模块:LM2596降压模块(输入12V,输出5V/3A)
(6)辅助电路:4×4矩阵键盘(本地模式切换)、0.96寸OLED显示屏(本地参数预览)
设计意义
该智慧农业温室系统的设计意义体现在多个方面。首先,通过实时采集空气温湿度、土壤湿度及光照强度等关键环境参数,并借助华为云物联网平台实现数据的远程上传与存储,系统为农业生产提供了精准的环境监测能力。这使得农户能够突破地域限制,随时随地掌握温室内部状态,为精细化种植决策提供了坚实的数据支撑。
其次,系统集成了手动与自动双模式控制功能,通过QT上位机实现灌溉、补光、通风设备的远程操控。结合预设的阈值联动机制(如土壤湿度低于30%自动灌溉、光照不足时自动补光),显著降低了人工干预的强度和频次,大幅提升了温室管理的自动化水平和响应效率,有效保障作物生长环境的稳定性。
再者,异常报警功能的加入强化了风险防控能力。当环境参数超出安全范围(如温度超过40℃),系统通过QT界面弹窗及时警示并记录事件,帮助农户快速定位并处置突发状况,避免因环境失控导致的作物损失,从而降低生产风险,提升农业生产的可靠性与安全性。
此外,本地化交互设计(如OLED显示屏实时预览参数、矩阵键盘切换模式)与远程监控相结合,兼顾了现场操作的便捷性与云端管理的灵活性。这种多层级、立体化的管控方式,不仅优化了水、电等资源的利用效率,也为现代农业向智能化、数字化转型升级提供了可落地的技术范例。
设计思路
本系统以STM32F103C8T6为核心控制器,负责协调传感器数据采集、控制逻辑执行及通信任务。该芯片通过GPIO接口连接各类传感器,包括DHT11用于实时获取空气温湿度、YL-69检测土壤湿度以及BH1750测量光照强度,确保环境参数的高频采集与本地处理。数据采集后,STM32进行滤波和校准,并通过内部逻辑判断是否触发自动控制或报警条件。
控制策略支持手动与自动双模式切换,由QT上位机远程设定或本地4×4矩阵键盘选择。在自动模式下,STM32基于预设阈值执行联动:当土壤湿度低于30%时驱动5V继电器启动水泵,光照低于200 Lux时控制继电器开启补光灯;手动模式下,QT界面可直接发送指令控制水泵、补光灯(220V AC)和通风电机(12V DC),继电器模块响应这些指令执行设备开关。
通信环节通过ESP8266 Wi-Fi模组实现,STM32利用串口发送AT指令,使ESP8266以MQTT协议连接华为云物联网平台,上传实时环境数据(如温湿度、土壤湿度、光照值)并接收来自云端的控制命令。数据在华为云存储后,为QT上位机提供历史记录基础,确保远程监控的可靠性。
QT上位机基于QMQTT库订阅云平台消息,动态显示实时数据并利用Qt Charts组件绘制历史曲线图,直观展示参数变化趋势。同时,QT界面提供手动控制面板,允许用户远程操作设备;当环境参数超限(如温度超过40℃)时,QT自动弹窗报警,并将事件记录到本地或云存储中,便于后续分析。
本地辅助界面包括0.96寸OLED显示屏,用于预览关键参数(如当前温湿度、土壤湿度值)和系统状态;4×4矩阵键盘支持现场切换控制模式或调整阈值,增强系统的灵活性与可操作性。整体电源由LM2596降压模块提供,确保12V输入转换为稳定5V/3A输出,满足所有硬件模块的供电需求。
异常处理机制集成在STM32和QT端:STM32实时监测传感器数据,一旦检测到超限(如高温),立即触发QT报警;QT记录事件时间及参数值,形成日志文件,便于故障回溯。系统设计注重实时性与安全性,所有功能均基于硬件模块实现,无额外功能添加。
框架图
Lexical error on line 10. Unrecognized text. ...机] A --> I[4×4矩阵键盘] A -- ----------------------^框架说明:
- 感知层:DHT11、YL-69、BH1750传感器实时采集环境参数
- 控制层:
- STM32处理传感器数据并执行自动控制逻辑(阈值联动)
- 继电器模块驱动执行设备(水泵/补光灯/通风)
- 矩阵键盘和OLED提供本地交互
- 通信层:ESP8266通过MQTT协议连接华为云,实现双向数据传输
- 云端:华为云物联网平台进行数据存储和消息路由
- 应用层:QT上位机实现数据可视化、设备控制和异常报警
- 电源:LM2596模块提供系统所需5V/3A电源
系统总体设计
系统总体设计围绕STM32F103C8T6主控芯片构建,实现温室环境参数的实时监测与智能控制。该系统通过集成多种传感器和执行设备,结合华为云物联网平台与QT上位机,形成完整的闭环管理架构。所有硬件模块协同工作,确保数据采集、处理、传输和控制的高效执行,满足农业温室的自动化需求。
环境参数采集部分由DHT11传感器负责空气温湿度测量、YL-69传感器检测土壤湿度、BH1750传感器监测光照强度。这些传感器直接连接至STM32微控制器,通过ADC或数字接口周期性读取数据,确保实时性。采集到的原始数据在STM32内部进行初步处理,如滤波和校准,以提高精度和可靠性。
数据处理与控制逻辑由STM32F103C8T6核心实现。主控芯片根据预设算法分析传感器数据,执行自动阈值联动:当土壤湿度低于30%时启动水泵继电器,光照强度低于200 Lux时开启补光灯继电器。同时,系统支持手动/自动模式切换,用户可通过本地4×4矩阵键盘或远程QT上位机选择模式,在自动模式下触发联动控制,在手动模式下由用户远程操控设备。异常检测逻辑集成其中,如温度超过40℃时触发报警事件。
通信模块基于ESP8266 Wi-Fi模组,通过串口AT指令与STM32交互。数据通过MQTT协议上传至华为云物联网服务器,实现环境参数的远程存储与同步。STM32定期发送JSON格式的数据包,包括温湿度、土壤湿度和光照值,确保云平台实时更新。下行通信支持接收来自QT上位机的控制指令,如设备开关命令。
QT上位机作为远程监控界面,使用Qt Charts库动态绘制实时环境数据及历史曲线图,直观展示趋势变化。通过QMQTT库订阅华为云消息,上位机实时获取并显示数据。用户可在界面手动控制灌溉水泵、补光灯和通风设备,或设置报警阈值。异常发生时,如参数超限,QT界面弹窗报警并记录事件日志,便于追溯分析。
执行设备驱动由继电器模块完成。5V继电器控制DC 5V水泵,2路继电器模块分别管理AC 220V补光灯和DC 12V通风电机。STM32输出GPIO信号驱动继电器开关,确保安全隔离。本地交互通过0.96寸OLED显示屏提供参数预览,显示当前模式和环境值,方便现场操作。
电源管理采用LM2596降压模块,将输入12V转换为稳定的5V/3A输出,为STM32、传感器、继电器及通信模块供电,保证系统稳定运行。整体设计注重实用性与可靠性,所有功能严格基于给定硬件和需求实现,无额外扩展。
系统功能总结
功能模块 | 具体实现 |
---|---|
环境参数采集 | 通过DHT11采集空气温湿度,YL-69检测土壤湿度,BH1750监测光照强度,实时更新数据 |
数据远程传输 | ESP8266 Wi-Fi模组通过MQTT协议将数据上传至华为云物联网平台存储 |
上位机监控界面 | QT上位机动态显示实时数据,使用Qt Charts绘制历史曲线图 |
双模式设备控制 | 支持手动(QT界面远程控制)和自动模式,控制灌溉水泵、补光灯、通风设备 |
阈值联动控制 | 自动触发:土壤湿度<30%启动水泵,光照<200 Lux开启补光灯 |
异常报警系统 | 环境超限(如温度>40℃)时QT界面弹窗报警,并记录事件日志 |
本地交互模块 | 4×4矩阵键盘切换控制模式,0.96寸OLED显示屏实时预览本地环境参数 |
执行设备驱动 | 继电器模块驱动水泵(5V DC)、补光灯(220V AC)和通风电机(12V DC) |
电源管理 | LM2596降压模块提供5V/3A稳定电源,支持多设备供电 |
设计的各个功能模块描述
STM32F103C8T6主控芯片模块负责整体系统的数据处理与控制逻辑执行,包括读取传感器数据、处理自动阈值联动规则(如土壤湿度低于30%时启动水泵或光照低于200 Lux时开启补光灯),并根据手动或自动模式决策执行设备的启停,同时管理本地交互和通信模块的数据流转。
环境传感器模块集成DHT11传感器采集空气温湿度数据,YL-69土壤湿度传感器检测土壤水分值,以及BH1750光照传感器监测光照强度,所有数据通过模拟或数字接口实时传输至主控芯片,确保温室环境参数的准确获取。
执行设备驱动模块利用继电器模块控制外部设备,包括5V继电器驱动DC 5V灌溉水泵、2路继电器分别控制AC 220V补光灯和DC 12V通风电机,主控芯片根据传感器数据或QT上位机指令输出高低电平信号,实现设备的远程或本地开关操作。
通信模块基于ESP8266-01S Wi-Fi模组,通过串口AT指令与主控芯片交互,使用MQTT协议连接华为云物联网平台,实现环境数据的实时上传、云存储以及从云平台接收QT上位机的控制命令,保障远程数据传输的可靠性。
QT上位机界面模块运行在PC端,通过QMQTT库订阅华为云平台消息,动态显示实时空气温湿度、土壤湿度和光照强度数据,利用Qt Charts组件绘制历史曲线图,支持用户手动远程控制水泵、补光灯和通风设备,并在检测到异常(如温度超过40℃)时触发弹窗报警和事件日志记录。
电源管理模块采用LM2596降压模块,将外部输入的12V电源转换为稳定的5V/3A输出,为STM32主控板、传感器、继电器及通信模块提供所需电力,确保系统各部分的稳定运行。
本地交互辅助模块包含4×4矩阵键盘用于现场手动切换系统工作模式(自动或手动),以及0.96寸OLED显示屏实时预览关键环境参数(如温湿度、光照值),提供基本的本地操作和状态监控功能。
上位机代码设计
#include <QApplication>
#include <QMainWindow>
#include <QtCharts>
#include <QChartView>
#include <QLineSeries>
#include <QDateTimeAxis>
#include <QValueAxis>
#include <QMQTTClient>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QGroupBox>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QTimer>
using namespace QtCharts;
class GreenhouseMonitor : public QMainWindow {
Q_OBJECT
public:
GreenhouseMonitor(QWidget *parent = nullptr) : QMainWindow(parent) {
// 初始化UI
setupUI();
// 初始化MQTT客户端
setupMQTT();
// 初始化定时器
setupTimers();
}
private slots:
void onMqttConnected() {
qDebug() << "Connected to Huawei Cloud IoT";
mqttClient->subscribe("sensors/data", 0); // 订阅传感器数据主题
}
void onMqttMessage(const QMQTTMessage &msg) {
QString payload = QString::fromUtf8(msg.payload());
qDebug() << "Received:" << payload;
processSensorData(payload);
}
void onWaterPumpClicked() { sendControlCommand("pump", waterPumpBtn->isChecked()); }
void onGrowLightClicked() { sendControlCommand("light", growLightBtn->isChecked()); }
void onFanClicked() { sendControlCommand("fan", fanBtn->isChecked()); }
void updateRealtimeData() {
// 实时数据刷新到UI
tempLabel->setText(QString("温度: %1 °C").arg(currentTemp, 0, 'f', 1));
humidityLabel->setText(QString("湿度: %1%").arg(currentHumidity, 0, 'f', 1));
soilLabel->setText(QString("土壤湿度: %1%").arg(currentSoilMoisture, 0, 'f', 1));
lightLabel->setText(QString("光照: %1 Lux").arg(currentLight));
}
void checkAlarms() {
if (currentTemp > 40.0) {
showAlarm("温度警报", QString("温度过高: %1°C > 40°C").arg(currentTemp));
}
if (currentSoilMoisture < 30.0) {
showAlarm("土壤警报", QString("土壤过干: %1% < 30%").arg(currentSoilMoisture));
}
if (currentLight < 200) {
showAlarm("光照警报", QString("光照不足: %1 Lux < 200 Lux").arg(currentLight));
}
}
private:
void setupUI() {
// 主窗口设置
setWindowTitle("智慧农业温室监控系统");
setGeometry(100, 100, 1200, 800);
// 中央部件和布局
QWidget *centralWidget = new QWidget(this);
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
// 实时数据显示区域
QGroupBox *realtimeGroup = new QGroupBox("实时环境数据");
QHBoxLayout *realtimeLayout = new QHBoxLayout(realtimeGroup);
tempLabel = new QLabel("温度: -- °C");
humidityLabel = new QLabel("湿度: --%");
soilLabel = new QLabel("土壤湿度: --%");
lightLabel = new QLabel("光照: -- Lux");
realtimeLayout->addWidget(tempLabel);
realtimeLayout->addWidget(humidityLabel);
realtimeLayout->addWidget(soilLabel);
realtimeLayout->addWidget(lightLabel);
// 设备控制区域
QGroupBox *controlGroup = new QGroupBox("设备控制");
QHBoxLayout *controlLayout = new QHBoxLayout(controlGroup);
waterPumpBtn = new QPushButton("灌溉水泵");
growLightBtn = new QPushButton("补光灯");
fanBtn = new QPushButton("通风设备");
waterPumpBtn->setCheckable(true);
growLightBtn->setCheckable(true);
fanBtn->setCheckable(true);
controlLayout->addWidget(waterPumpBtn);
controlLayout->addWidget(growLightBtn);
controlLayout->addWidget(fanBtn);
// 历史图表区域
QGroupBox *chartGroup = new QGroupBox("历史数据趋势");
QVBoxLayout *chartLayout = new QVBoxLayout(chartGroup);
QChart *chart = new QChart();
chartView = new QChartView(chart);
chart->setTitle("温室环境参数变化");
chart->legend()->setVisible(true);
// 初始化数据序列
tempSeries = new QLineSeries();
tempSeries->setName("温度(°C)");
humiditySeries = new QLineSeries();
humiditySeries->setName("湿度(%)");
soilSeries = new QLineSeries();
soilSeries->setName("土壤湿度(%)");
lightSeries = new QLineSeries();
lightSeries->setName("光照(Lux)");
chart->addSeries(tempSeries);
chart->addSeries(humiditySeries);
chart->addSeries(soilSeries);
chart->addSeries(lightSeries);
// 时间轴设置
QDateTimeAxis *axisX = new QDateTimeAxis();
axisX->setFormat("hh:mm");
axisX->setTitleText("时间");
chart->addAxis(axisX, Qt::AlignBottom);
// 数值轴设置
QValueAxis *axisY = new QValueAxis();
axisY->setTitleText("数值");
axisY->setRange(0, 100);
chart->addAxis(axisY, Qt::AlignLeft);
// 关联序列到坐标轴
tempSeries->attachAxis(axisX);
tempSeries->attachAxis(axisY);
humiditySeries->attachAxis(axisX);
humiditySeries->attachAxis(axisY);
soilSeries->attachAxis(axisX);
soilSeries->attachAxis(axisY);
lightSeries->attachAxis(axisX);
lightSeries->attachAxis(axisY);
chartLayout->addWidget(chartView);
// 组装主界面
mainLayout->addWidget(realtimeGroup);
mainLayout->addWidget(controlGroup);
mainLayout->addWidget(chartGroup);
setCentralWidget(centralWidget);
// 连接按钮信号
connect(waterPumpBtn, &QPushButton::clicked, this, &GreenhouseMonitor::onWaterPumpClicked);
connect(growLightBtn, &QPushButton::clicked, this, &GreenhouseMonitor::onGrowLightClicked);
connect(fanBtn, &QPushButton::clicked, this, &GreenhouseMonitor::onFanClicked);
}
void setupMQTT() {
mqttClient = new QMQTTClient(this);
mqttClient->setHost("iotda.cn-north-4.myhuaweicloud.com"); // 华为云地址
mqttClient->setPort(1883);
mqttClient->setUsername("设备ID");
mqttClient->setPassword("设备密钥");
mqttClient->setClientId("QT_CLIENT_" + QString::number(rand()));
connect(mqttClient, &QMQTTClient::connected, this, &GreenhouseMonitor::onMqttConnected);
connect(mqttClient, &QMQTTClient::messageReceived, this, &GreenhouseMonitor::onMqttMessage);
mqttClient->connect();
}
void setupTimers() {
QTimer *dataTimer = new QTimer(this);
connect(dataTimer, &QTimer::timeout, this, &GreenhouseMonitor::updateRealtimeData);
dataTimer->start(1000); // 每秒更新UI
QTimer *alarmTimer = new QTimer(this);
connect(alarmTimer, &QTimer::timeout, this, &GreenhouseMonitor::checkAlarms);
alarmTimer->start(5000); // 每5秒检查警报
}
void processSensorData(const QString &data) {
// 示例数据格式: "T=25.6,H=65.2,S=45.1,L=350"
QStringList parts = data.split(",");
for (const QString &part : parts) {
QStringList keyVal = part.split("=");
if (keyVal.size() == 2) {
QString key = keyVal[0].trimmed();
float value = keyVal[1].toFloat();
if (key == "T") {
currentTemp = value;
updateChart(tempSeries, value);
} else if (key == "H") {
currentHumidity = value;
updateChart(humiditySeries, value);
} else if (key == "S") {
currentSoilMoisture = value;
updateChart(soilSeries, value);
} else if (key == "L") {
currentLight = value;
updateChart(lightSeries, value);
}
}
}
logEvent("数据更新: " + data);
}
void updateChart(QLineSeries *series, float value) {
QDateTime now = QDateTime::currentDateTime();
series->append(now.toMSecsSinceEpoch(), value);
// 限制数据点数量(保留最近100个点)
if (series->count() > 100) {
series->removePoints(0, series->count() - 100);
}
// 自动调整Y轴范围
QValueAxis *axisY = qobject_cast<QValueAxis*>(chartView->chart()->axes(Qt::Vertical)[0]);
double min = axisY->min();
double max = axisY->max();
if (value < min) min = value - 5;
if (value > max) max = value + 5;
axisY->setRange(min, max);
}
void sendControlCommand(const QString &device, bool state) {
QString topic = "devices/control/" + device;
QString payload = state ? "ON" : "OFF";
mqttClient->publish(topic, payload.toUtf8());
logEvent(QString("控制命令: %1 -> %2").arg(device).arg(payload));
}
void showAlarm(const QString &title, const QString &message) {
QMessageBox::warning(this, title, message);
logEvent("警报触发: " + title + " - " + message);
}
void logEvent(const QString &event) {
QFile logFile("event_log.txt");
if (logFile.open(QIODevice::Append)) {
QTextStream stream(&logFile);
stream << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")
<< " - " << event << "\n";
logFile.close();
}
}
private:
// UI组件
QLabel *tempLabel;
QLabel *humidityLabel;
QLabel *soilLabel;
QLabel *lightLabel;
QPushButton *waterPumpBtn;
QPushButton *growLightBtn;
QPushButton *fanBtn;
QChartView *chartView;
// 数据序列
QLineSeries *tempSeries;
QLineSeries *humiditySeries;
QLineSeries *soilSeries;
QLineSeries *lightSeries;
// MQTT客户端
QMQTTClient *mqttClient;
// 当前环境数据
float currentTemp = 0;
float currentHumidity = 0;
float currentSoilMoisture = 0;
int currentLight = 0;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
GreenhouseMonitor monitor;
monitor.show();
return app.exec();
}
#include "main.moc"
代码说明
-
UI布局:
- 实时数据区:显示温度、湿度、土壤湿度和光照强度
- 控制区:灌溉水泵、补光灯、通风设备的开关按钮
- 图表区:使用Qt Charts展示四种参数的历史曲线
-
MQTT通信:
- 连接华为云IoT平台(需替换实际设备凭证)
- 订阅
sensors/data
主题接收传感器数据 - 通过
devices/control/{device}
主题发送控制命令
-
核心功能:
- 实时解析传感器数据(格式示例:
"T=25.6,H=65.2,S=45.1,L=350"
) - 动态更新折线图(自动调整Y轴范围)
- 定时检查环境阈值并触发弹窗警报
- 事件日志记录到
event_log.txt
- 实时解析传感器数据(格式示例:
-
控制逻辑:
- 手动模式:通过按钮控制设备
- 自动模式:根据接收到的数据自动执行阈值控制(代码中已实现警报检查)
-
扩展性:
- 可添加数据库支持存储历史数据
- 可增加多温室切换功能
- 可扩展为多设备协同控制
模块代码设计
STM32模块代码设计(寄存器方式)
#include "stm32f10x.h"
// 引脚定义
#define DHT11_PIN GPIO_Pin_13 // PC13
#define PUMP_PIN GPIO_Pin_0 // PC0
#define LIGHT_PIN GPIO_Pin_1 // PC1
#define FAN_PIN GPIO_Pin_2 // PC2
// 传感器结构体
typedef struct {
float temperature;
float humidity;
uint16_t soil_moisture;
uint16_t light_intensity;
} SensorData;
// 全局变量
SensorData env_data;
uint8_t auto_mode = 1; // 默认自动模式
// 函数声明
void RCC_Configuration(void);
void GPIO_Configuration(void);
void ADC_Configuration(void);
void I2C_Configuration(void);
void USART_Configuration(void);
void DHT11_ReadData(void);
uint16_t SoilMoisture_Read(void);
uint16_t BH1750_ReadLight(void);
void Relay_Control(uint8_t device, uint8_t state);
void ESP8266_SendData(void);
void SysTick_Handler(void);
void Delay_us(uint32_t us);
void Delay_ms(uint32_t ms);
int main(void) {
// 系统初始化
RCC_Configuration();
GPIO_Configuration();
ADC_Configuration();
I2C_Configuration();
USART_Configuration();
// 初始化SysTick定时器(1ms中断)
SysTick_Config(SystemCoreClock / 1000);
// 继电器初始状态
Relay_Control(0, 0); // 关闭水泵
Relay_Control(1, 0); // 关闭补光灯
Relay_Control(2, 0); // 关闭通风
while(1) {
// 1. 采集环境数据
DHT11_ReadData();
env_data.soil_moisture = SoilMoisture_Read();
env_data.light_intensity = BH1750_ReadLight();
// 2. 自动控制逻辑
if(auto_mode) {
// 土壤湿度<30%启动水泵
if(env_data.soil_moisture < 300) { // 假设ADC值0-1000对应0-100%
Relay_Control(0, 1);
} else {
Relay_Control(0, 0);
}
// 光照<200 Lux启动补光灯
if(env_data.light_intensity < 200) {
Relay_Control(1, 1);
} else {
Relay_Control(1, 0);
}
// 温度>40℃启动通风
if(env_data.temperature > 40.0) {
Relay_Control(2, 1);
} else {
Relay_Control(2, 0);
}
}
// 3. 上传数据到华为云
ESP8266_SendData();
// 4. 添加延时防止频繁采集
Delay_ms(5000);
}
}
// -------------------- DHT11温湿度传感器驱动 --------------------
void DHT11_ReadData(void) {
uint8_t data[5] = {0};
uint8_t i, j;
// 主机发送开始信号
GPIO_ResetBits(GPIOC, DHT11_PIN);
Delay_ms(18);
GPIO_SetBits(GPIOC, DHT11_PIN);
Delay_us(30);
// 设置引脚为输入
GPIOC->CRH &= ~(0x0F << 20); // PC13输入模式
GPIOC->CRH |= (0x04 << 20); // 浮空输入
// 等待DHT11响应
while(GPIO_ReadInputDataBit(GPIOC, DHT11_PIN));
while(!GPIO_ReadInputDataBit(GPIOC, DHT11_PIN));
while(GPIO_ReadInputDataBit(GPIOC, DHT11_PIN));
// 读取40位数据
for(i=0; i<5; i++) {
for(j=0; j<8; j++) {
while(!GPIO_ReadInputDataBit(GPIOC, DHT11_PIN)); // 等待低电平结束
Delay_us(35);
if(GPIO_ReadInputDataBit(GPIOC, DHT11_PIN)) {
data[i] |= (1 << (7-j));
while(GPIO_ReadInputDataBit(GPIOC, DHT11_PIN)); // 等待高电平结束
}
}
}
// 设置引脚为输出
GPIOC->CRH &= ~(0x0F << 20);
GPIOC->CRH |= (0x03 << 20); // 推挽输出
// 校验数据
if(data[4] == (data[0] + data[1] + data[2] + data[3])) {
env_data.humidity = data[0];
env_data.temperature = data[2];
}
}
// -------------------- YL-69土壤湿度传感器驱动 --------------------
uint16_t SoilMoisture_Read(void) {
ADC1->CR2 |= ADC_CR2_ADON; // 开启ADC
ADC1->CR2 |= ADC_CR2_SWSTART; // 开始转换
while(!(ADC1->SR & ADC_SR_EOC)); // 等待转换完成
return ADC1->DR; // 返回ADC值
}
// -------------------- BH1750光照传感器驱动 --------------------
void BH1750_WriteCmd(uint8_t cmd) {
I2C1->CR1 |= I2C_CR1_START; // 发送START
while(!(I2C1->SR1 & I2C_SR1_SB)); // 等待START发送完成
I2C1->DR = 0x46; // BH1750写地址(0x23<<1)
while(!(I2C1->SR1 & I2C_SR1_ADDR)); // 等待地址发送完成
(void)I2C1->SR2; // 清除ADDR标志
while(!(I2C1->SR1 & I2C_SR1_TXE)); // 等待数据寄存器空
I2C1->DR = cmd; // 发送命令
while(!(I2C1->SR1 & I2C_SR1_BTF)); // 等待传输完成
I2C1->CR1 |= I2C_CR1_STOP; // 发送STOP
}
uint16_t BH1750_ReadLight(void) {
uint8_t data[2] = {0};
// 发送启动测量命令
BH1750_WriteCmd(0x10); // 连续H分辨率模式
Delay_ms(180); // 等待测量完成
// 读取数据
I2C1->CR1 |= I2C_CR1_START;
while(!(I2C1->SR1 & I2C_SR1_SB));
I2C1->DR = 0x47; // BH1750读地址
while(!(I2C1->SR1 & I2C_SR1_ADDR));
(void)I2C1->SR2;
// 读取高字节
while(!(I2C1->SR1 & I2C_SR1_RXNE));
data[0] = I2C1->DR;
// 读取低字节
while(!(I2C1->SR1 & I2C_SR1_RXNE));
data[1] = I2C1->DR;
I2C1->CR1 |= I2C_CR1_STOP;
return (data[0] << 8) | data[1]; // 返回光照值
}
// -------------------- 继电器控制函数 --------------------
void Relay_Control(uint8_t device, uint8_t state) {
switch(device) {
case 0: // 水泵
state ? GPIO_SetBits(GPIOC, PUMP_PIN) : GPIO_ResetBits(GPIOC, PUMP_PIN);
break;
case 1: // 补光灯
state ? GPIO_SetBits(GPIOC, LIGHT_PIN) : GPIO_ResetBits(GPIOC, LIGHT_PIN);
break;
case 2: // 通风
state ? GPIO_SetBits(GPIOC, FAN_PIN) : GPIO_ResetBits(GPIOC, FAN_PIN);
break;
}
}
// -------------------- ESP8266通信函数 --------------------
void ESP8266_SendData(void) {
char buffer[128];
// 构造MQTT消息 (示例格式)
sprintf(buffer, "AT+MQTTPUB=0,\"sensors/data\",\"%.1f,%.1f,%d,%d\",0,0\r\n",
env_data.temperature,
env_data.humidity,
env_data.soil_moisture,
env_data.light_intensity);
// 通过USART1发送数据
for(char *p = buffer; *p; p++) {
USART1->DR = *p;
while(!(USART1->SR & USART_SR_TXE));
}
}
// -------------------- 系统时钟配置 --------------------
void RCC_Configuration(void) {
// 使能外设时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN |
RCC_APB2ENR_AFIOEN | RCC_APB2ENR_ADC1EN |
RCC_APB2ENR_USART1EN;
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
// 配置ADC时钟
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6;
}
// -------------------- GPIO配置 --------------------
void GPIO_Configuration(void) {
// DHT11 (PC13 推挽输出)
GPIOC->CRH &= ~(0x0F << 20);
GPIOC->CRH |= (0x03 << 20);
// 继电器控制 (PC0, PC1, PC2 推挽输出)
GPIOC->CRL &= ~(0xFF << 0);
GPIOC->CRL |= (0x33 << 0);
// YL-69 (PA0 模拟输入)
GPIOA->CRL &= ~(0x0F << 0);
// BH1750 (PB6-SCL, PB7-SDA 复用开漏)
GPIOB->CRL &= ~(0xFF << 24);
GPIOB->CRL |= (0x77 << 24);
GPIOB->ODR |= (1 << 6) | (1 << 7); // 上拉
// ESP8266 (PA9-TX, PA10-RX 复用推挽)
GPIOA->CRH &= ~(0xFF << 4);
GPIOA->CRH |= (0x4B << 4);
}
// -------------------- ADC配置 --------------------
void ADC_Configuration(void) {
// 配置ADC1通道0 (PA0)
ADC1->SQR3 = 0; // 通道0作为第一个转换
ADC1->SMPR2 = 0x07; // 239.5周期采样时间
ADC1->CR2 = ADC_CR2_ADON; // 开启ADC
Delay_ms(1); // 等待稳定
}
// -------------------- I2C配置 --------------------
void I2C_Configuration(void) {
// 标准模式(100kHz)
I2C1->CR2 = 36; // APB1时钟36MHz
I2C1->CCR = 180; // CCR = 36M / (2*100k) = 180
I2C1->TRISE = 37; // TRISE = 36M*0.001 +1 = 37
I2C1->CR1 = I2C_CR1_PE; // 使能I2C
}
// -------------------- USART配置 --------------------
void USART_Configuration(void) {
// 波特率115200 (36MHz)
USART1->BRR = 0x0139; // 36M/115200=312.5->0x139
USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
}
// -------------------- 延时函数 --------------------
void Delay_us(uint32_t us) {
uint32_t start = SysTick->VAL;
uint32_t ticks = us * (SystemCoreClock / 1000000);
while((start - SysTick->VAL) < ticks);
}
void Delay_ms(uint32_t ms) {
while(ms--) Delay_us(1000);
}
// SysTick中断处理函数
void SysTick_Handler(void) {
// 可用于精确计时
}
关键代码说明
-
传感器驱动
- DHT11:使用单总线协议,通过PC13引脚实现温湿度采集
- YL-69:通过ADC1通道0(PA0)读取土壤湿度模拟值
- BH1750:通过I2C1接口(PB6/PB7)读取光照强度
-
控制逻辑
- 自动模式根据阈值控制设备:
- 土壤湿度 < 30% → 启动水泵
- 光照 < 200 Lux → 启动补光灯
- 温度 > 40℃ → 启动通风
- 自动模式根据阈值控制设备:
-
通信接口
- ESP8266通过USART1(PA9/PA10)发送MQTT数据到华为云
- 数据格式:
"温度,湿度,土壤湿度,光照强度"
-
安全机制
- 数据校验(DHT11校验和验证)
- 传感器采集间隔(5秒)
- 继电器初始化为关闭状态
-
硬件接口
- 继电器控制:PC0(水泵)、PC1(补光灯)、PC2(通风)
- ADC采样:PA0(土壤湿度)
- I2C总线:PB6(SCL)/PB7(SDA)(BH1750+OLED)
项目核心代码
以下是基于STM32F103C8T6的智慧农业系统main.c
完整代码(寄存器开发):
#include "stm32f10x.h"
#include "dht11.h"
#include "bh1750.h"
#include "esp8266.h"
#include "oled.h"
#include "keypad.h"
// 硬件定义
#define PUMP_GPIO GPIOA
#define PUMP_PIN GPIO_Pin_0 // 水泵继电器控制
#define LIGHT_GPIO GPIOA
#define LIGHT_PIN GPIO_Pin_1 // 补光灯继电器控制
#define FAN_GPIO GPIOA
#define FAN_PIN GPIO_Pin_2 // 通风设备继电器控制
// 全局变量
typedef struct {
float temperature;
float humidity;
uint16_t soil_moisture;
uint16_t light_intensity;
} SensorData;
volatile SensorData env_data = {0};
volatile uint8_t sys_mode = 0; // 0:自动模式 1:手动模式
volatile uint8_t pump_state = 0; // 水泵状态
volatile uint8_t light_state = 0; // 补光灯状态
volatile uint8_t fan_state = 0; // 通风状态
// 初始化函数声明
void RCC_Configuration(void);
void GPIO_Configuration(void);
void ADC_Configuration(void);
void TIM3_Init(void);
void NVIC_Configuration(void);
void ControlDevices(void);
int main(void) {
// 系统初始化
RCC_Configuration();
GPIO_Configuration();
ADC_Configuration();
TIM3_Init();
NVIC_Configuration();
OLED_Init();
Keypad_Init();
ESP8266_Init();
DHT11_Init();
BH1750_Init();
// 显示启动界面
OLED_ShowString(0, 0, "AgriSystem Start");
Delay_ms(1000);
OLED_Clear();
// 连接华为云
ESP8266_ConnectCloud();
// 主循环
while(1) {
// 1. 按键扫描(模式切换)
uint8_t key = Keypad_Scan();
if(key == 0x01) { // 假设按键1切换模式
sys_mode = !sys_mode;
OLED_ShowString(0, 2, sys_mode ? "Mode:Manual " : "Mode:Auto ");
}
// 2. 传感器数据采集(在TIM3中断中周期性执行)
// 3. 设备控制逻辑
ControlDevices();
// 4. 异常检测(温度>40℃报警)
if(env_data.temperature > 40.0) {
// 通过MQTT发送报警信息
char alert_msg[50];
sprintf(alert_msg, "ALERT:HighTemp=%.1fC", env_data.temperature);
ESP8266_MQTTPublish("alert_topic", alert_msg);
}
// 5. OLED显示刷新
static uint32_t oled_tick = 0;
if(SystemTick - oled_tick > 500) {
OLED_ShowString(0, 0, "T:");
OLED_ShowFloat(16, 0, env_data.temperature);
OLED_ShowString(0, 2, sys_mode ? "Mode:Manual " : "Mode:Auto ");
OLED_ShowString(0, 4, "Pump:");
OLED_ShowString(48, 4, pump_state ? "ON " : "OFF");
oled_tick = SystemTick;
}
// 6. 处理云平台指令
if(ESP8266_RxFlag) {
MQTT_MessageProcess(ESP8266_RxBuffer);
ESP8266_RxFlag = 0;
}
}
}
// 时钟配置
void RCC_Configuration(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN |
RCC_APB2ENR_AFIOEN | RCC_APB2ENR_ADC1EN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
}
// GPIO配置
void GPIO_Configuration(void) {
// 继电器控制引脚
GPIOA->CRL &= 0xFFFFF000; // PA0,PA1,PA2推挽输出
GPIOA->CRL |= 0x00000333;
GPIOA->ODR &= ~(PUMP_PIN | LIGHT_PIN | FAN_PIN);
// 传感器引脚初始化在各驱动模块中完成
}
// ADC配置(土壤湿度)
void ADC_Configuration(void) {
ADC1->CR2 = ADC_CR2_ADON; // 开启ADC
ADC1->SMPR2 = 0x00000007; // 通道0采样时间239.5周期
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6; // ADC时钟12MHz
}
// 定时器3初始化(1s周期)
void TIM3_Init(void) {
TIM3->PSC = 7200 - 1; // 10kHz
TIM3->ARR = 10000 - 1; // 1s中断
TIM3->DIER = TIM_DIER_UIE; // 允许更新中断
TIM3->CR1 = TIM_CR1_CEN; // 启动定时器
}
// 中断配置
void NVIC_Configuration(void) {
NVIC_EnableIRQ(TIM3_IRQn);
NVIC_SetPriority(TIM3_IRQn, 0);
}
// 设备控制逻辑
void ControlDevices(void) {
if(sys_mode == 0) { // 自动模式
// 土壤湿度<30%启动水泵
if(env_data.soil_moisture < 30 && !pump_state) {
PUMP_GPIO->BSRR = PUMP_PIN; // 开启水泵
pump_state = 1;
} else if(env_data.soil_moisture >= 35 && pump_state) {
PUMP_GPIO->BRR = PUMP_PIN; // 关闭水泵
pump_state = 0;
}
// 光照<200Lux开启补光灯
if(env_data.light_intensity < 200 && !light_state) {
LIGHT_GPIO->BSRR = LIGHT_PIN;
light_state = 1;
} else if(env_data.light_intensity >= 250 && light_state) {
LIGHT_GPIO->BRR = LIGHT_PIN;
light_state = 0;
}
} else { // 手动模式(状态由云平台指令控制)
GPIOA->BSRR = pump_state ? PUMP_PIN : (PUMP_PIN << 16);
GPIOA->BSRR = light_state ? LIGHT_PIN : (LIGHT_PIN << 16);
GPIOA->BSRR = fan_state ? FAN_PIN : (FAN_PIN << 16);
}
}
// TIM3中断处理(传感器采集)
void TIM3_IRQHandler(void) {
if(TIM3->SR & TIM_SR_UIF) {
TIM3->SR = ~TIM_SR_UIF;
// 读取DHT11
DHT11_ReadData(&env_data.temperature, &env_data.humidity);
// 读取BH1750
env_data.light_intensity = BH1750_ReadLight();
// 读取土壤湿度(ADC通道0)
ADC1->CR2 |= ADC_CR2_ADON;
while(!(ADC1->SR & ADC_SR_EOC));
env_data.soil_moisture = ADC1->DR; // 原始ADC值0-4095
// 上传到华为云
char mqtt_data[128];
sprintf(mqtt_data,
"{\"temp\":%.1f,\"humi\":%.1f,\"soil\":%d,\"light\":%d}",
env_data.temperature,
env_data.humidity,
env_data.soil_moisture,
env_data.light_intensity);
ESP8266_MQTTPublish("sensor_data", mqtt_data);
}
}
// MQTT消息处理(来自云平台)
void MQTT_MessageProcess(char *msg) {
if(strstr(msg, "pump=1")) pump_state = 1;
else if(strstr(msg, "pump=0")) pump_state = 0;
else if(strstr(msg, "light=1")) light_state = 1;
else if(strstr(msg, "light=0")) light_state = 0;
else if(strstr(msg, "fan=1")) fan_state = 1;
else if(strstr(msg, "fan=0")) fan_state = 0;
}
// 简单延时函数
void Delay_ms(uint32_t ms) {
for(uint32_t i=0; i<ms*8000; i++);
}
代码说明:
-
系统初始化:
- 配置时钟、GPIO、ADC、定时器、中断和外设驱动
- 启动OLED显示和WiFi连接
-
主循环功能:
- 按键检测(模式切换)
- 设备控制逻辑(自动/手动模式)
- 温度异常报警(>40℃)
- OLED数据刷新
- MQTT消息处理
-
定时器中断(TIM3):
- 每1秒采集所有传感器数据
- 通过MQTT上传到华为云平台
-
控制逻辑:
- 自动模式:土壤湿度<30%启动水泵,光照<200Lux开补光灯
- 手动模式:接收云平台指令控制设备
-
硬件控制:
- 继电器控制使用GPIO直接寄存器操作
- 土壤湿度通过ADC采集原始值
总结
本项目成功构建了一套以STM32F103C8T6为核心的智慧农业温室环境监测与联动控制系统。系统通过集成DHT11温湿度传感器、YL-69土壤湿度传感器和BH1750光照传感器,精准采集温室环境关键参数,为精细化管理提供数据基础。
借助ESP8266 Wi-Fi模块的通信能力,系统通过MQTT协议将实时数据稳定上传至华为云物联网平台,实现了环境信息的远程存储与可视化。QT上位机不仅动态展示实时数据,还利用Qt Charts组件绘制历史曲线图,直观呈现环境变化趋势,并具备手动远程控制水泵、补光灯及通风设备的能力。
系统创新性地融合了手动与自动双模式控制策略。在自动模式下,基于预设阈值(土壤湿度<30%启动水泵、光照<200 Lux开启补光灯)的智能联动机制,显著提升了环境调控的及时性与能效。同时,QT界面的异常弹窗报警与事件记录功能(如温度>40℃),有效保障了温室运行的可靠性与安全性。
硬件架构设计合理,STM32主控高效协调传感器数据采集、继电器驱动(控制5V水泵、12V通风电机及220V补光灯)及本地交互(4×4键盘模式切换、OLED参数预览)。电源模块(LM2596降压)为各单元提供稳定供电,确保系统长时间稳定运行。
综上所述,本系统实现了温室环境参数的全面感知、云端互联、智能决策与精准执行,为现代化农业生产提供了高效、可靠且用户友好的自动化管理解决方案,有力推动了农业智能化升级。
- 点赞
- 收藏
- 关注作者
评论(0)