基于STM32的智慧农业温室环境监测与联动控制系统

举报
DS小龙哥 发表于 2025/06/22 18:42:04 2025/06/22
【摘要】 项目开发背景传统农业温室环境调控主要依赖人工经验,存在监测滞后、控制不精准、人力成本高等问题。尤其在规模化管理中,种植者难以及时掌握每个温室的实时参数变化,导致作物生长环境波动,影响产量和品质。同时,水资源、光照资源和电能的粗放式管理也造成了浪费。物联网技术的快速发展为解决上述问题提供了契机。将传感器、微控制器、无线通信和云端数据处理相结合,构建智能化监控系统,成为提升现代农业温室管理效率...

项目开发背景

传统农业温室环境调控主要依赖人工经验,存在监测滞后、控制不精准、人力成本高等问题。尤其在规模化管理中,种植者难以及时掌握每个温室的实时参数变化,导致作物生长环境波动,影响产量和品质。同时,水资源、光照资源和电能的粗放式管理也造成了浪费。

物联网技术的快速发展为解决上述问题提供了契机。将传感器、微控制器、无线通信和云端数据处理相结合,构建智能化监控系统,成为提升现代农业温室管理效率与精准度的必然趋势。通过实时采集关键环境数据并实现远程监控与自动控制,可显著优化作物生长条件。

本项目基于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 -- ----------------------^

框架说明

  1. 感知层:DHT11、YL-69、BH1750传感器实时采集环境参数
  2. 控制层
    • STM32处理传感器数据并执行自动控制逻辑(阈值联动)
    • 继电器模块驱动执行设备(水泵/补光灯/通风)
    • 矩阵键盘和OLED提供本地交互
  3. 通信层:ESP8266通过MQTT协议连接华为云,实现双向数据传输
  4. 云端:华为云物联网平台进行数据存储和消息路由
  5. 应用层:QT上位机实现数据可视化、设备控制和异常报警
  6. 电源: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"

代码说明

  1. UI布局

    • 实时数据区:显示温度、湿度、土壤湿度和光照强度
    • 控制区:灌溉水泵、补光灯、通风设备的开关按钮
    • 图表区:使用Qt Charts展示四种参数的历史曲线
  2. MQTT通信

    • 连接华为云IoT平台(需替换实际设备凭证)
    • 订阅sensors/data主题接收传感器数据
    • 通过devices/control/{device}主题发送控制命令
  3. 核心功能

    • 实时解析传感器数据(格式示例:"T=25.6,H=65.2,S=45.1,L=350"
    • 动态更新折线图(自动调整Y轴范围)
    • 定时检查环境阈值并触发弹窗警报
    • 事件日志记录到event_log.txt
  4. 控制逻辑

    • 手动模式:通过按钮控制设备
    • 自动模式:根据接收到的数据自动执行阈值控制(代码中已实现警报检查)
  5. 扩展性

    • 可添加数据库支持存储历史数据
    • 可增加多温室切换功能
    • 可扩展为多设备协同控制

模块代码设计

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) {
    // 可用于精确计时
}

关键代码说明

  1. 传感器驱动

    • DHT11:使用单总线协议,通过PC13引脚实现温湿度采集
    • YL-69:通过ADC1通道0(PA0)读取土壤湿度模拟值
    • BH1750:通过I2C1接口(PB6/PB7)读取光照强度
  2. 控制逻辑

    • 自动模式根据阈值控制设备:
      • 土壤湿度 < 30% → 启动水泵
      • 光照 < 200 Lux → 启动补光灯
      • 温度 > 40℃ → 启动通风
  3. 通信接口

    • ESP8266通过USART1(PA9/PA10)发送MQTT数据到华为云
    • 数据格式:"温度,湿度,土壤湿度,光照强度"
  4. 安全机制

    • 数据校验(DHT11校验和验证)
    • 传感器采集间隔(5秒)
    • 继电器初始化为关闭状态
  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++);
}

代码说明:

  1. 系统初始化

    • 配置时钟、GPIO、ADC、定时器、中断和外设驱动
    • 启动OLED显示和WiFi连接
  2. 主循环功能

    • 按键检测(模式切换)
    • 设备控制逻辑(自动/手动模式)
    • 温度异常报警(>40℃)
    • OLED数据刷新
    • MQTT消息处理
  3. 定时器中断(TIM3)

    • 每1秒采集所有传感器数据
    • 通过MQTT上传到华为云平台
  4. 控制逻辑

    • 自动模式:土壤湿度<30%启动水泵,光照<200Lux开补光灯
    • 手动模式:接收云平台指令控制设备
  5. 硬件控制

    • 继电器控制使用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降压)为各单元提供稳定供电,确保系统长时间稳定运行。

综上所述,本系统实现了温室环境参数的全面感知、云端互联、智能决策与精准执行,为现代化农业生产提供了高效、可靠且用户友好的自动化管理解决方案,有力推动了农业智能化升级。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。