基于STM32设计的智能温室二氧化碳施肥系统

举报
DS小龙哥 发表于 2025/12/25 15:20:10 2025/12/25
【摘要】 项目开发背景随着全球人口持续增长和农业资源日益紧张,高效、可持续的农业生产方式成为解决粮食安全问题的关键。温室农业作为一种可控环境农业技术,能够通过优化作物生长条件来提高产量和品质,尤其在现代城市化进程中,其重要性日益凸显。然而,传统温室管理多依赖人工经验,难以实现精准调控,导致资源浪费和效率低下,特别是在二氧化碳施肥方面,不当的控制可能引发环境问题或作物生长不均。二氧化碳是植物光合作用的...

项目开发背景

随着全球人口持续增长和农业资源日益紧张,高效、可持续的农业生产方式成为解决粮食安全问题的关键。温室农业作为一种可控环境农业技术,能够通过优化作物生长条件来提高产量和品质,尤其在现代城市化进程中,其重要性日益凸显。然而,传统温室管理多依赖人工经验,难以实现精准调控,导致资源浪费和效率低下,特别是在二氧化碳施肥方面,不当的控制可能引发环境问题或作物生长不均。

二氧化碳是植物光合作用的重要原料,在温室环境中,适当增加CO2浓度可以显著提升作物的光合效率,促进生长并增加产量。研究表明,在光照充足条件下,将CO2浓度维持在适宜范围(如800-1200 ppm)可使作物产量提高20%-30%。但传统CO2施肥方法往往基于粗略估算,缺乏实时监测和自动调节,容易造成浓度波动,影响作物健康,同时也增加了能源和成本消耗。

为克服这些局限性,智能温室控制系统应运而生,它结合传感器技术、微控制器和物联网,实现对环境参数的精准监测与自动控制。本项目基于STM32微控制器设计智能CO2施肥系统,旨在通过集成CO2、温湿度和光照传感器,实时采集数据,并利用继电器自动调节CO2发生装置,确保施肥过程精准高效。同时,系统通过Wi-Fi模块连接华为云平台,实现数据远程传输和分析,辅以QT上位机进行可视化显示,帮助用户优化作物生长环境。

该系统的开发不仅提升了温室管理的自动化水平,还通过数据驱动决策降低了人为误差,为现代智慧农业提供了可行的技术解决方案。它有望在资源节约、产量提升和环境保护方面发挥积极作用,推动农业向智能化、可持续化方向发展。

设计实现的功能

(1)实时监测温室CO2浓度(使用SGP30传感器)
(2)实时监测温室温度(使用DHT22传感器)
(3)实时监测温室湿度(使用DHT22传感器)
(4)实时监测温室光照强度(使用GY-30传感器)
(5)自动控制CO2发生装置进行精准施肥(使用继电器模块)
(6)通过Wi-Fi将环境参数传输到华为云(使用ESP8266模块)
(7)作物生长环境优化控制(通过STM32主控制器基于传感器数据实现)
(8)QT上位机显示环境参数和施肥效果分析(通过云数据传输实现)

项目硬件模块组成

(1)STM32F103C8T6最小系统核心板作为主控制器
(2)SGP30 CO2传感器监测二氧化碳浓度
(3)DHT22温湿度传感器监测环境参数
(4)GY-30光照传感器监测光照强度
(5)继电器模块控制CO2发生装置
(6)ESP8266-01S Wi-Fi模块实现华为云通信

设计意义

该系统通过实时监测温室内的二氧化碳浓度、温度和光照强度,并结合自动控制CO2发生装置,实现了对作物生长环境的精准调控。这种设计能够有效提升光合作用效率,促进作物健康生长,从而提高温室农业的生产力和经济效益。

通过集成多种传感器和控制器,系统优化了资源利用,减少了人工干预和能源浪费。自动化的环境控制不仅降低了运营成本,还确保了作物在不同生长阶段获得适宜的条件,增强了温室管理的稳定性和可靠性。

借助ESP8266 Wi-Fi模块与华为云的通信功能,系统支持远程数据监控和上位机显示,为用户提供实时的环境参数和施肥效果分析。这有助于农业管理者基于数据做出科学决策,及时调整控制策略,提升整体管理效率。

该设计体现了现代农业向智能化和精准化发展的趋势,具有广泛的应用价值。它能够推动温室种植技术的创新,促进农业可持续发展,为应对粮食安全和环境挑战提供实用解决方案。

设计思路

本系统以STM32F103C8T6最小系统核心板作为主控制器,负责协调整个智能温室二氧化碳施肥系统的运行。系统通过集成多种传感器实时采集温室环境参数,其中SGP30 CO2传感器用于监测二氧化碳浓度,DHT22温湿度传感器获取环境温度数据,GY-30光照传感器检测光照强度。这些传感器数据通过I2C或GPIO接口传输到STM32控制器,进行实时处理和校准,确保监测的准确性和稳定性。

在自动控制方面,STM32根据预设的CO2浓度阈值和作物生长需求,通过继电器模块精准控制CO2发生装置的开启与关闭。当监测到的CO2浓度低于设定值时,控制器会触发继电器启动施肥装置;反之则关闭,以实现二氧化碳的精准补充,避免浪费或过度施肥。这一过程完全自动化,无需人工干预,提高了温室管理的效率。

作物生长环境优化控制主要通过分析采集的温度和光照数据来实现。STM32会综合环境参数,例如在光照充足时适当提高CO2施肥目标,或在温度过高时调整控制策略,以模拟理想生长条件。这种优化基于简单的反馈机制,确保作物处于适宜的CO2、温度和光照平衡状态,促进健康生长。

系统通过ESP8266-01S Wi-Fi模块将处理后的环境数据和施肥状态上传至华为云平台,实现远程数据传输和存储。QT上位机应用程序从云平台获取这些数据,以图形化界面实时显示温室CO2浓度、温度、光照强度等参数,并提供历史趋势分析和施肥效果评估,帮助用户直观了解环境变化和控制系统性能。

框架图

+-------------------+      +-------------------+      +-------------------+
|                   |      |                   |      |                   |
|   SGP30 CO2传感器  |----->|                   |      |                   |
|                   |      |                   |      |                   |
+-------------------+      |                   |      |                   |
                           |   STM32F103C8T6   |----->|   继电器模块       |-----> CO2发生装置
+-------------------+      |   主控制器        |      |                   |
|                   |      |                   |      |                   |
|  DHT22温湿度传感器 |----->|                   |      |                   |
|                   |      |                   |      |                   |
+-------------------+      |                   |      +-------------------+
                           |                   |
+-------------------+      |                   |      +-------------------+
|                   |      |                   |      |                   |
|  GY-30光照传感器  |----->|                   |----->|  ESP8266 Wi-Fi    |-----> 华为云 ----> QT上位机
|                   |      |                   |      |                   |
+-------------------+      +-------------------+      +-------------------+

系统总体设计

本系统基于STM32F103C8T6最小系统核心板作为主控制器,实现智能温室二氧化碳施肥的自动化管理。系统通过集成多种传感器和执行器,实时采集温室环境数据并控制CO2施肥过程,同时借助无线通信和上位机界面进行数据展示与分析,确保作物生长环境的优化。

系统采用SGP30传感器监测二氧化碳浓度,DHT22传感器采集温度和湿度数据,GY-30传感器检测光照强度。STM32控制器定期轮询这些传感器,获取实时环境参数,并进行数据滤波和校准处理,以保证监测的准确性和稳定性。

控制逻辑基于预设的环境阈值,STM32根据采集的CO2浓度、温度和光照数据,自动判断是否需要启动施肥。当CO2浓度低于设定值时,控制器通过继电器模块驱动CO2发生装置开启,进行精准施肥;同时,系统综合考虑温度和光照等因素,动态调整控制策略,以优化作物生长条件。

通信部分通过ESP8266-01S Wi-Fi模块实现,系统将环境参数和施肥状态数据上传至华为云平台。这使得数据能够远程存储和访问,为上位机提供实时数据源,并支持后续的数据分析和历史记录查询。

QT开发的上位机应用程序从华为云获取数据,以图形化界面实时显示温室环境参数,如CO2浓度、温度、湿度和光照强度,同时提供施肥效果分析功能,帮助用户直观评估系统性能并做出决策优化。

系统功能总结

功能模块 功能描述
环境参数监测 实时监测温室内的CO2浓度、温度和光照强度,使用SGP30、DHT22和GY-30传感器采集数据
CO2施肥控制 自动控制CO2发生装置进行精准施肥,基于环境数据通过继电器模块实现开关控制
环境优化控制 综合CO2浓度、温度、光照等参数,动态调整环境条件以优化作物生长
数据通信与显示 通过ESP8266 Wi-Fi模块上传数据至华为云,QT上位机实时显示环境参数和施肥效果分析

设计的各个功能模块描述

STM32F103C8T6最小系统核心板作为主控制器,负责协调整个系统的运行,采集传感器数据并进行处理,根据预设逻辑自动控制CO2施肥操作,确保温室环境的稳定和优化。它通过集成各模块实现实时监测和控制功能,是整个系统的核心处理单元。

SGP30 CO2传感器用于实时监测温室内的二氧化碳浓度,提供高精度的CO2数据,帮助系统判断是否需要启动施肥。DHT22温湿度传感器检测环境的温度和湿度参数,为环境优化提供全面的气候数据支持。GY-30光照传感器监测光照强度,辅助分析作物生长条件,确保光照因素得到充分考虑。

继电器模块与CO2发生装置连接,根据主控制器的指令自动控制施肥设备的开启和关闭,实现精准的CO2施肥。当CO2浓度低于设定阈值时,系统会通过继电器触发CO2发生装置,以维持适宜的浓度水平,从而优化作物生长环境。

ESP8266-01S Wi-Fi模块实现与华为云的通信功能,将采集的环境参数如CO2浓度、温度、湿度和光照强度上传至云平台,同时支持从云端接收指令或配置数据,增强系统的远程监控和互联能力。

QT上位机软件用于显示温室的环境参数和施肥效果分析,提供直观的图形界面展示实时数据、历史趋势和施肥操作记录,帮助用户进行环境评估和决策优化。

上位机代码设计

// main.cpp
#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QTextEdit>
#include <QTabWidget>
#include <QChartView>
#include <QLineSeries>
#include <QDateTimeAxis>
#include <QValueAxis>
#include <QTimer>
#include <QMessageBox>
#include <QGroupBox>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QProgressBar>
#include <QTableWidget>
#include <QHeaderView>
#include <QtMqtt/QMqttClient>
#include <QDateTime>
#include <QtCharts>

QT_CHARTS_USE_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
    {
        setupUI();
        setupMQTT();
        setupCharts();
        setupConnections();
    }

private slots:
    void onConnectButtonClicked()
    {
        if (mqttClient->state() == QMqttClient::Disconnected) {
            mqttClient->setHostname("你的华为云地址");
            mqttClient->setPort(1883);
            mqttClient->setUsername("设备ID");
            mqttClient->setPassword("设备密钥");
            mqttClient->connectToHost();
        } else {
            mqttClient->disconnectFromHost();
        }
    }

    void onStateChanged(QMqttClient::ClientState state)
    {
        if (state == QMqttClient::Connected) {
            statusLabel->setText("已连接到华为云");
            connectButton->setText("断开连接");
            // 订阅主题
            mqttClient->subscribe("sensor/data", 0);
            mqttClient->subscribe("control/status", 0);
        } else {
            statusLabel->setText("未连接");
            connectButton->setText("连接");
        }
    }

    void onMessageReceived(const QByteArray &message, const QMqttTopicName &topic)
    {
        QString msg = QString::fromUtf8(message);
        
        if (topic.name() == "sensor/data") {
            processSensorData(msg);
        } else if (topic.name() == "control/status") {
            controlStatusText->append(QDateTime::currentDateTime().toString() + " - " + msg);
        }
    }

    void onControlButtonClicked()
    {
        if (mqttClient->state() == QMqttClient::Connected) {
            QString command = QString("{\"target_co2\":%1,\"mode\":\"%2\"}")
                .arg(targetCO2SpinBox->value())
                .arg(autoModeCheckBox->isChecked() ? "auto" : "manual");
            mqttClient->publish("control/command", command.toUtf8(), 0, false);
        }
    }

    void updateCharts()
    {
        // 更新图表数据
        QDateTime now = QDateTime::currentDateTime();
        
        // CO2浓度图表
        co2Series->append(now.toMSecsSinceEpoch(), currentCO2);
        if (co2Series->count() > 100) {
            co2Series->remove(0);
        }
        
        // 温度图表
        tempSeries->append(now.toMSecsSinceEpoch(), currentTemp);
        if (tempSeries->count() > 100) {
            tempSeries->remove(0);
        }
        
        // 光照图表
        lightSeries->append(now.toMSecsSinceEpoch(), currentLight);
        if (lightSeries->count() > 100) {
            lightSeries->remove(0);
        }
        
        // 更新X轴范围
        QDateTime minTime = now.addSecs(-300); // 显示最近5分钟数据
        co2Chart->axisX()->setMin(minTime);
        co2Chart->axisX()->setMax(now);
    }

private:
    void setupUI()
    {
        setWindowTitle("智能温室CO2施肥监控系统");
        setMinimumSize(1200, 800);
        
        QWidget *centralWidget = new QWidget(this);
        setCentralWidget(centralWidget);
        
        QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
        
        // 状态栏
        QHBoxLayout *statusLayout = new QHBoxLayout();
        statusLabel = new QLabel("未连接");
        connectButton = new QPushButton("连接");
        statusLayout->addWidget(statusLabel);
        statusLayout->addStretch();
        statusLayout->addWidget(connectButton);
        
        // 标签页
        QTabWidget *tabWidget = new QTabWidget();
        
        // 实时监控标签页
        QWidget *monitorTab = createMonitorTab();
        tabWidget->addTab(monitorTab, "实时监控");
        
        // 数据分析标签页
        QWidget *analysisTab = createAnalysisTab();
        tabWidget->addTab(analysisTab, "数据分析");
        
        // 控制设置标签页
        QWidget *controlTab = createControlTab();
        tabWidget->addTab(controlTab, "控制设置");
        
        mainLayout->addLayout(statusLayout);
        mainLayout->addWidget(tabWidget);
    }

    QWidget* createMonitorTab()
    {
        QWidget *tab = new QWidget();
        QHBoxLayout *layout = new QHBoxLayout(tab);
        
        // 左侧:传感器数据显示
        QGroupBox *sensorGroup = new QGroupBox("传感器数据");
        QGridLayout *sensorLayout = new QGridLayout(sensorGroup);
        
        sensorLayout->addWidget(new QLabel("CO2浓度:"), 0, 0);
        co2Label = new QLabel("-- ppm");
        sensorLayout->addWidget(co2Label, 0, 1);
        
        sensorLayout->addWidget(new QLabel("温度:"), 1, 0);
        tempLabel = new QLabel("-- °C");
        sensorLayout->addWidget(tempLabel, 1, 1);
        
        sensorLayout->addWidget(new QLabel("湿度:"), 2, 0);
        humidityLabel = new QLabel("-- %");
        sensorLayout->addWidget(humidityLabel, 2, 1);
        
        sensorLayout->addWidget(new QLabel("光照强度:"), 3, 0);
        lightLabel = new QLabel("-- Lux");
        sensorLayout->addWidget(lightLabel, 3, 1);
        
        sensorLayout->addWidget(new QLabel("设备状态:"), 4, 0);
        deviceStatusLabel = new QLabel("离线");
        sensorLayout->addWidget(deviceStatusLabel, 4, 1);
        
        // 右侧:图表显示
        QTabWidget *chartTabWidget = new QTabWidget();
        
        QWidget *co2ChartWidget = new QWidget();
        QVBoxLayout *co2ChartLayout = new QVBoxLayout(co2ChartWidget);
        co2ChartView = new QChartView();
        co2ChartLayout->addWidget(co2ChartView);
        chartTabWidget->addTab(co2ChartWidget, "CO2浓度");
        
        QWidget *tempChartWidget = new QWidget();
        QVBoxLayout *tempChartLayout = new QVBoxLayout(tempChartWidget);
        tempChartView = new QChartView();
        tempChartLayout->addWidget(tempChartView);
        chartTabWidget->addTab(tempChartWidget, "温度");
        
        QWidget *lightChartWidget = new QWidget();
        QVBoxLayout *lightChartLayout = new QVBoxLayout(lightChartWidget);
        lightChartView = new QChartView();
        lightChartLayout->addWidget(lightChartView);
        chartTabWidget->addTab(lightChartWidget, "光照强度");
        
        layout->addWidget(sensorGroup, 1);
        layout->addWidget(chartTabWidget, 3);
        
        return tab;
    }

    QWidget* createAnalysisTab()
    {
        QWidget *tab = new QWidget();
        QVBoxLayout *layout = new QVBoxLayout(tab);
        
        // 数据表格
        dataTable = new QTableWidget();
        dataTable->setColumnCount(5);
        dataTable->setHorizontalHeaderLabels({"时间", "CO2浓度", "温度", "湿度", "光照强度"});
        dataTable->horizontalHeader()->setStretchLastSection(true);
        
        // 分析结果
        QGroupBox *analysisGroup = new QGroupBox("施肥效果分析");
        QVBoxLayout *analysisLayout = new QVBoxLayout(analysisGroup);
        analysisText = new QTextEdit();
        analysisText->setReadOnly(true);
        analysisLayout->addWidget(analysisText);
        
        layout->addWidget(dataTable, 2);
        layout->addWidget(analysisGroup, 1);
        
        return tab;
    }

    QWidget* createControlTab()
    {
        QWidget *tab = new QWidget();
        QVBoxLayout *layout = new QVBoxLayout(tab);
        
        // 控制设置
        QGroupBox *controlGroup = new QGroupBox("控制参数设置");
        QGridLayout *controlLayout = new QGridLayout(controlGroup);
        
        controlLayout->addWidget(new QLabel("目标CO2浓度:"), 0, 0);
        targetCO2SpinBox = new QSpinBox();
        targetCO2SpinBox->setRange(400, 2000);
        targetCO2SpinBox->setValue(800);
        targetCO2SpinBox->setSuffix(" ppm");
        controlLayout->addWidget(targetCO2SpinBox, 0, 1);
        
        controlLayout->addWidget(new QLabel("控制模式:"), 1, 0);
        autoModeCheckBox = new QCheckBox("自动模式");
        autoModeCheckBox->setChecked(true);
        controlLayout->addWidget(autoModeCheckBox, 1, 1);
        
        controlButton = new QPushButton("发送控制指令");
        controlLayout->addWidget(controlButton, 2, 0, 1, 2);
        
        // 控制状态日志
        QGroupBox *logGroup = new QGroupBox("控制状态日志");
        QVBoxLayout *logLayout = new QVBoxLayout(logGroup);
        controlStatusText = new QTextEdit();
        controlStatusText->setReadOnly(true);
        logLayout->addWidget(controlStatusText);
        
        layout->addWidget(controlGroup);
        layout->addWidget(logGroup);
        
        return tab;
    }

    void setupMQTT()
    {
        mqttClient = new QMqttClient(this);
        mqttClient->setClientId(QString("QT_CLIENT_%1").arg(QDateTime::currentSecsSinceEpoch()));
    }

    void setupCharts()
    {
        // CO2浓度图表
        co2Chart = new QChart();
        co2Series = new QLineSeries();
        co2Chart->addSeries(co2Series);
        co2Chart->setTitle("CO2浓度实时监测");
        
        QDateTimeAxis *axisX = new QDateTimeAxis();
        axisX->setFormat("hh:mm:ss");
        axisX->setTitleText("时间");
        co2Chart->addAxis(axisX, Qt::AlignBottom);
        co2Series->attachAxis(axisX);
        
        QValueAxis *axisY = new QValueAxis();
        axisY->setRange(400, 2000);
        axisY->setTitleText("CO2浓度 (ppm)");
        co2Chart->addAxis(axisY, Qt::AlignLeft);
        co2Series->attachAxis(axisY);
        
        co2ChartView->setChart(co2Chart);
        
        // 温度图表
        tempChart = new QChart();
        tempSeries = new QLineSeries();
        tempChart->addSeries(tempSeries);
        tempChart->setTitle("温度实时监测");
        
        // 光照强度图表
        lightChart = new QChart();
        lightSeries = new QLineSeries();
        lightChart->addSeries(lightSeries);
        lightChart->setTitle("光照强度实时监测");
    }

    void setupConnections()
    {
        connect(connectButton, &QPushButton::clicked, this, &MainWindow::onConnectButtonClicked);
        connect(mqttClient, &QMqttClient::stateChanged, this, &MainWindow::onStateChanged);
        connect(mqttClient, &QMqttClient::messageReceived, this, &MainWindow::onMessageReceived);
        connect(controlButton, &QPushButton::clicked, this, &MainWindow::onControlButtonClicked);
        
        // 定时更新图表
        QTimer *chartTimer = new QTimer(this);
        connect(chartTimer, &QTimer::timeout, this, &MainWindow::updateCharts);
        chartTimer->start(1000); // 每秒更新一次
    }

    void processSensorData(const QString &data)
    {
        // 解析JSON数据
        // 示例数据格式: {"co2":800,"temp":25.5,"humidity":60,"light":1200}
        QJsonDocument doc = QJsonDocument::fromJson(data.toUtf8());
        if (!doc.isNull()) {
            QJsonObject obj = doc.object();
            
            currentCO2 = obj["co2"].toInt();
            currentTemp = obj["temp"].toDouble();
            currentHumidity = obj["humidity"].toDouble();
            currentLight = obj["light"].toInt();
            
            // 更新UI
            co2Label->setText(QString("%1 ppm").arg(currentCO2));
            tempLabel->setText(QString("%1 °C").arg(currentTemp));
            humidityLabel->setText(QString("%1 %").arg(currentHumidity));
            lightLabel->setText(QString("%1 Lux").arg(currentLight));
            
            // 添加到数据表格
            int row = dataTable->rowCount();
            dataTable->insertRow(row);
            dataTable->setItem(row, 0, new QTableWidgetItem(QDateTime::currentDateTime().toString()));
            dataTable->setItem(row, 1, new QTableWidgetItem(QString::number(currentCO2)));
            dataTable->setItem(row, 2, new QTableWidgetItem(QString::number(currentTemp)));
            dataTable->setItem(row, 3, new QTableWidgetItem(QString::number(currentHumidity)));
            dataTable->setItem(row, 4, new QTableWidgetItem(QString::number(currentLight)));
            
            // 自动滚动到最后一行
            dataTable->scrollToBottom();
            
            // 更新分析结果
            updateAnalysis();
        }
    }

    void updateAnalysis()
    {
        QString analysis;
        
        // CO2浓度分析
        if (currentCO2 < 600) {
            analysis += "? CO2浓度过低,需要施肥\n";
        } else if (currentCO2 >= 600 && currentCO2 <= 1000) {
            analysis += "? CO2浓度适宜\n";
        } else {
            analysis += "?? CO2浓度过高\n";
        }
        
        // 温度分析
        if (currentTemp < 18) {
            analysis += "? 温度过低\n";
        } else if (currentTemp >= 18 && currentTemp <= 28) {
            analysis += "? 温度适宜\n";
        } else {
            analysis += "?? 温度过高\n";
        }
        
        // 光照分析
        if (currentLight < 500) {
            analysis += "? 光照不足\n";
        } else if (currentLight >= 500 && currentLight <= 2000) {
            analysis += "? 光照适宜\n";
        } else {
            analysis += "?? 光照过强\n";
        }
        
        analysisText->setPlainText(analysis);
    }

private:
    // MQTT客户端
    QMqttClient *mqttClient;
    
    // UI组件
    QLabel *statusLabel;
    QPushButton *connectButton;
    QPushButton *controlButton;
    
    // 监控标签页组件
    QLabel *co2Label;
    QLabel *tempLabel;
    QLabel *humidityLabel;
    QLabel *lightLabel;
    QLabel *deviceStatusLabel;
    
    // 图表组件
    QChartView *co2ChartView;
    QChartView *tempChartView;
    QChartView *lightChartView;
    QChart *co2Chart;
    QChart *tempChart;
    QChart *lightChart;
    QLineSeries *co2Series;
    QLineSeries *tempSeries;
    QLineSeries *lightSeries;
    
    // 分析标签页组件
    QTableWidget *dataTable;
    QTextEdit *analysisText;
    
    // 控制标签页组件
    QSpinBox *targetCO2SpinBox;
    QCheckBox *autoModeCheckBox;
    QTextEdit *controlStatusText;
    
    // 当前传感器数据
    int currentCO2 = 0;
    double currentTemp = 0;
    double currentHumidity = 0;
    int currentLight = 0;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    MainWindow window;
    window.show();
    
    return app.exec();
}

#include "main.moc"
# CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(SmartGreenhouseCO2)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 REQUIRED COMPONENTS Core Widgets Charts Mqtt Network)

qt_standard_project_setup()

qt_add_executable(SmartGreenhouseCO2
    main.cpp
)

qt_add_resources(SmartGreenhouseCO2 "resources"
    PREFIX "/"
)

target_link_libraries(SmartGreenhouseCO2 Qt6::Core Qt6::Widgets Qt6::Charts Qt6::Mqtt Qt6::Network)
# SmartGreenhouseCO2.pro
QT += core widgets charts mqtt network

CONFIG += c++17

TARGET = SmartGreenhouseCO2
TEMPLATE = app

SOURCES += \
    main.cpp

HEADERS +=

这个上位机程序包含以下主要功能:

  1. 实时监控

    • 显示CO2浓度、温度、湿度和光照强度
    • 实时曲线图表显示历史数据
    • 设备连接状态监控
  2. 数据分析

    • 数据表格记录历史数据
    • 施肥效果分析
    • 环境参数评估
  3. 控制设置

    • CO2目标浓度设置
    • 自动/手动模式切换
    • 控制指令发送
    • 控制状态日志
  4. 华为云通信

    • MQTT协议连接
    • 数据订阅和发布
    • 实时数据接收

使用前需要配置华为云的连接参数(地址、设备ID、密钥等)。程序采用模块化设计,便于维护和扩展。

模块代码设计

#include "stm32f10x.h"

// 引脚定义
#define DHT22_GPIO_PORT    GPIOA
#define DHT22_GPIO_PIN     GPIO_Pin_0
#define RELAY_GPIO_PORT    GPIOA  
#define RELAY_GPIO_PIN     GPIO_Pin_1

// 传感器地址定义
#define SGP30_ADDRESS      0x58
#define GY30_ADDRESS       0x23

// 函数声明
void System_Init(void);
void GPIO_Init(void);
void I2C_Init(void);
void USART_Init(void);
void TIM_Init(void);
void SGP30_Init(void);
uint16_t SGP30_ReadCO2(void);
float DHT22_ReadTemp(void);
float DHT22_ReadHumidity(void);
uint16_t GY30_ReadLight(void);
void Relay_Control(uint8_t state);
void ESP8266_SendData(float co2, float temp, float humidity, float light);

// 系统初始化
void System_Init(void)
{
    // 开启外设时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN;
    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN | RCC_APB1ENR_USART2EN | RCC_APB1ENR_TIM2EN;
    
    // 系统时钟配置
    SystemInit();
}

// GPIO初始化
void GPIO_Init(void)
{
    // DHT22引脚配置 - 输入
    GPIOA->CRL &= ~(0xF << (0*4));  // PA0清空
    GPIOA->CRL |= (0x4 << (0*4));   // PA0输入上拉
    
    // 继电器引脚配置 - 输出
    GPIOA->CRL &= ~(0xF << (1*4));  // PA1清空  
    GPIOA->CRL |= (0x1 << (1*4));   // PA1推挽输出50MHz
    GPIOA->BSRR = GPIO_BSRR_BR1;    // 默认关闭继电器
    
    // I2C引脚配置 - PB6(SCL), PB7(SDA)
    GPIOB->CRL &= ~(0xFF << (6*4)); // PB6,PB7清空
    GPIOB->CRL |= (0xB4 << (6*4));  // PB6,PB7复用开漏输出
    
    // USART2引脚配置 - PA2(TX), PA3(RX)
    GPIOA->CRL &= ~(0xFF << (2*4)); // PA2,PA3清空
    GPIOA->CRL |= (0xB4 << (2*4));  // PA2,PA3复用推挽输出
}

// I2C初始化
void I2C_Init(void)
{
    // 复位I2C1
    RCC->APB1RSTR |= RCC_APB1RSTR_I2C1RST;
    RCC->APB1RSTR &= ~RCC_APB1RSTR_I2C1RST;
    
    // I2C配置
    I2C1->CR1 &= ~I2C_CR1_PE;  // 禁用I2C
    
    // 标准模式配置(100kHz)
    I2C1->CR2 = 36;            // 36MHz
    I2C1->CCR = 180;           // CCR = 36M/(2*100k) = 180
    I2C1->TRISE = 37;          // TRISE = 36M/1000ns + 1 = 37
    
    I2C1->CR1 |= I2C_CR1_PE;   // 启用I2C
}

// USART初始化
void USART_Init(void)
{
    // USART2配置
    USART2->BRR = 0x1388;      // 115200波特率
    USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
}

// 定时器初始化
void TIM_Init(void)
{
    // TIM2用于微秒延时
    TIM2->PSC = 72 - 1;        // 1MHz计数频率
    TIM2->ARR = 0xFFFF;
    TIM2->CR1 = TIM_CR1_CEN;
}

// SGP30初始化
void SGP30_Init(void)
{
    uint8_t cmd[2] = {0x20, 0x03};  // 初始化命令
    
    // I2C启动
    I2C1->CR1 |= I2C_CR1_START;
    while(!(I2C1->SR1 & I2C_SR1_SB));
    
    // 发送设备地址
    I2C1->DR = SGP30_ADDRESS << 1;
    while(!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;
    
    // 发送初始化命令
    for(int i=0; i<2; i++)
    {
        I2C1->DR = cmd[i];
        while(!(I2C1->SR1 & I2C_SR1_TXE));
    }
    
    // I2C停止
    I2C1->CR1 |= I2C_CR1_STOP;
    while(I2C1->SR2 & I2C_SR2_MSL);
}

// SGP30读取CO2浓度
uint16_t SGP30_ReadCO2(void)
{
    uint8_t cmd[2] = {0x20, 0x08};  // 测量命令
    uint8_t data[6];
    uint16_t co2;
    
    // 发送测量命令
    I2C1->CR1 |= I2C_CR1_START;
    while(!(I2C1->SR1 & I2C_SR1_SB));
    
    I2C1->DR = SGP30_ADDRESS << 1;
    while(!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;
    
    for(int i=0; i<2; i++)
    {
        I2C1->DR = cmd[i];
        while(!(I2C1->SR1 & I2C_SR1_TXE));
    }
    
    I2C1->CR1 |= I2C_CR1_STOP;
    
    // 延时等待测量完成
    for(volatile int i=0; i<10000; i++);
    
    // 读取数据
    I2C1->CR1 |= I2C_CR1_START;
    while(!(I2C1->SR1 & I2C_SR1_SB));
    
    I2C1->DR = (SGP30_ADDRESS << 1) | 0x01;
    while(!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;
    
    // 读取6字节数据
    for(int i=0; i<6; i++)
    {
        if(i == 5)
            I2C1->CR1 &= ~I2C_CR1_ACK;
        
        while(!(I2C1->SR1 & I2C_SR1_RXNE));
        data[i] = I2C1->DR;
    }
    
    I2C1->CR1 |= I2C_CR1_STOP;
    
    // 计算CO2值
    co2 = (data[0] << 8) | data[1];
    return co2;
}

// DHT22读取温度
float DHT22_ReadTemp(void)
{
    uint8_t data[5] = {0};
    uint32_t time = 0;
    
    // 主机拉低18ms
    GPIOA->BRR = DHT22_GPIO_PIN;
    Delay_ms(18);
    GPIOA->BSRR = DHT22_GPIO_PIN;
    
    // 等待响应
    while(GPIOA->IDR & DHT22_GPIO_PIN);
    while(!(GPIOA->IDR & DHT22_GPIO_PIN));
    while(GPIOA->IDR & DHT22_GPIO_PIN);
    
    // 读取40位数据
    for(int i=0; i<40; i++)
    {
        while(!(GPIOA->IDR & DHT22_GPIO_PIN));
        
        TIM2->CNT = 0;
        while(GPIOA->IDR & DHT22_GPIO_PIN);
        
        time = TIM2->CNT;
        data[i/8] <<= 1;
        if(time > 40)  // 高电平持续时间大于40us为1
            data[i/8] |= 1;
    }
    
    // 计算温度
    float temp = ((data[2] & 0x7F) << 8 | data[3]) * 0.1;
    if(data[2] & 0x80) temp = -temp;
    
    return temp;
}

// DHT22读取湿度
float DHT22_ReadHumidity(void)
{
    uint8_t data[5] = {0};
    uint32_t time = 0;
    
    // 读取过程同上
    GPIOA->BRR = DHT22_GPIO_PIN;
    Delay_ms(18);
    GPIOA->BSRR = DHT22_GPIO_PIN;
    
    while(GPIOA->IDR & DHT22_GPIO_PIN);
    while(!(GPIOA->IDR & DHT22_GPIO_PIN));
    while(GPIOA->IDR & DHT22_GPIO_PIN);
    
    for(int i=0; i<40; i++)
    {
        while(!(GPIOA->IDR & DHT22_GPIO_PIN));
        
        TIM2->CNT = 0;
        while(GPIOA->IDR & DHT22_GPIO_PIN);
        
        time = TIM2->CNT;
        data[i/8] <<= 1;
        if(time > 40)
            data[i/8] |= 1;
    }
    
    // 计算湿度
    float humidity = (data[0] << 8 | data[1]) * 0.1;
    return humidity;
}

// GY30读取光照强度
uint16_t GY30_ReadLight(void)
{
    uint8_t cmd = 0x10;  // 高分辨率模式
    uint16_t lux;
    
    // 发送测量命令
    I2C1->CR1 |= I2C_CR1_START;
    while(!(I2C1->SR1 & I2C_SR1_SB));
    
    I2C1->DR = GY30_ADDRESS << 1;
    while(!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;
    
    I2C1->DR = cmd;
    while(!(I2C1->SR1 & I2C_SR1_TXE));
    
    I2C1->CR1 |= I2C_CR1_STOP;
    
    // 等待测量完成
    Delay_ms(180);
    
    // 读取数据
    I2C1->CR1 |= I2C_CR1_START;
    while(!(I2C1->SR1 & I2C_SR1_SB));
    
    I2C1->DR = (GY30_ADDRESS << 1) | 0x01;
    while(!(I2C1->SR1 & I2C_SR1_ADDR));
    (void)I2C1->SR2;
    
    // 读取2字节数据
    uint8_t data[2];
    for(int i=0; i<2; i++)
    {
        if(i == 1)
            I2C1->CR1 &= ~I2C_CR1_ACK;
        
        while(!(I2C1->SR1 & I2C_SR1_RXNE));
        data[i] = I2C1->DR;
    }
    
    I2C1->CR1 |= I2C_CR1_STOP;
    
    // 计算光照强度
    lux = (data[0] << 8) | data[1];
    return lux / 1.2;  // 转换为lux单位
}

// 继电器控制
void Relay_Control(uint8_t state)
{
    if(state)
        GPIOA->BSRR = RELAY_GPIO_PIN;  // 打开继电器
    else
        GPIOA->BRR = RELAY_GPIO_PIN;   // 关闭继电器
}

// ESP8266发送数据到华为云
void ESP8266_SendData(float co2, float temp, float humidity, float light)
{
    char buffer[128];
    
    // 构建JSON数据
    sprintf(buffer, "{\"co2\":%.1f,\"temp\":%.1f,\"humidity\":%.1f,\"light\":%.1f}",
            co2, temp, humidity, light);
    
    // 通过USART发送数据
    for(int i=0; buffer[i]!='\0'; i++)
    {
        USART2->DR = buffer[i];
        while(!(USART2->SR & USART_SR_TXE));
    }
}

// 延时函数
void Delay_ms(uint32_t ms)
{
    for(uint32_t i=0; i<ms*1000; i++);
}

// 主函数
int main(void)
{
    System_Init();
    GPIO_Init();
    I2C_Init();
    USART_Init();
    TIM_Init();
    
    SGP30_Init();
    
    while(1)
    {
        // 读取传感器数据
        uint16_t co2_raw = SGP30_ReadCO2();
        float co2_ppm = co2_raw;
        float temperature = DHT22_ReadTemp();
        float humidity = DHT22_ReadHumidity();
        uint16_t light_lux = GY30_ReadLight();
        
        // CO2施肥控制逻辑
        if(co2_ppm < 800)  // CO2浓度低于800ppm时开启施肥
        {
            Relay_Control(1);  // 打开CO2发生装置
        }
        else if(co2_ppm > 1200)  // CO2浓度高于1200ppm时关闭施肥
        {
            Relay_Control(0);  // 关闭CO2发生装置
        }
        
        // 发送数据到华为云
        ESP8266_SendData(co2_ppm, temperature, humidity, (float)light_lux);
        
        Delay_ms(5000);  // 5秒采样间隔
    }
}

项目核心代码

#include "stm32f10x.h"
#include "delay.h"
#include "sgp30.h"
#include "dht22.h"
#include "gy30.h"
#include "esp8266.h"
#include "relay.h"

// 全局变量定义
uint16_t co2_ppm = 0;
float temperature = 0;
float humidity = 0;
uint16_t light_intensity = 0;
uint8_t relay_state = 0;

// 华为云平台配置
#define DEVICE_ID "your_device_id"
#define DEVICE_SECRET "your_device_secret"

// CO2浓度阈值
#define CO2_TARGET_MIN 800
#define CO2_TARGET_MAX 1200

void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
void I2C_Configuration(void);
void TIM_Configuration(void);
void System_Init(void);
void Sensor_Data_Update(void);
void CO2_Control_Logic(void);
void Cloud_Data_Upload(void);

int main(void)
{
    System_Init();
    
    // 初始化传感器模块
    SGP30_Init();
    DHT22_Init();
    GY30_Init();
    ESP8266_Init();
    Relay_Init();
    
    // 连接华为云
    ESP8266_ConnectCloud(DEVICE_ID, DEVICE_SECRET);
    
    while(1)
    {
        // 传感器数据采集
        Sensor_Data_Update();
        
        // CO2施肥控制逻辑
        CO2_Control_Logic();
        
        // 数据上传到云平台
        Cloud_Data_Upload();
        
        // 延时2秒
        Delay_ms(2000);
    }
}

void System_Init(void)
{
    RCC_Configuration();
    GPIO_Configuration();
    USART_Configuration();
    I2C_Configuration();
    TIM_Configuration();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
}

void RCC_Configuration(void)
{
    // 开启外部高速晶振
    RCC->CR |= 0x00010000;
    while(!(RCC->CR & 0x00020000));
    
    // 配置PLL为9倍频
    RCC->CFGR |= 0x001C0000;
    RCC->CFGR |= 0x00010000;
    
    // 开启PLL
    RCC->CR |= 0x01000000;
    while(!(RCC->CR & 0x02000000));
    
    // 选择PLL作为系统时钟
    RCC->CFGR |= 0x00000002;
    while((RCC->CFGR & 0x0000000C) != 0x08);
    
    // 开启外设时钟
    RCC->APB2ENR |= 0x00000001;  // AFIO
    RCC->APB2ENR |= 0x00000004;  // GPIOA
    RCC->APB2ENR |= 0x00000008;  // GPIOB
    RCC->APB2ENR |= 0x00000010;  // GPIOC
    RCC->APB2ENR |= 0x00004000;  // USART1
    RCC->APB2ENR |= 0x00000020;  // ADC1
    RCC->APB1ENR |= 0x00020000;  // I2C1
    RCC->APB1ENR |= 0x00000002;  // TIM3
}

void GPIO_Configuration(void)
{
    // USART1 TX(PA9) RX(PA10)
    GPIOA->CRH &= 0xFFFFF00F;
    GPIOA->CRH |= 0x000004B0;
    
    // I2C1 SCL(PB6) SDA(PB7)
    GPIOB->CRL &= 0x00FFFFFF;
    GPIOB->CRL |= 0xBB000000;
    
    // DHT22数据线(PC0)
    GPIOC->CRL &= 0xFFFFFFF0;
    GPIOC->CRL |= 0x00000008;
    
    // 继电器控制(PC1)
    GPIOC->CRL &= 0xFFFFFF0F;
    GPIOC->CRL |= 0x00000020;
    
    // GY30光照传感器(PC2)
    GPIOC->CRL &= 0xFFFFF0FF;
    GPIOC->CRL |= 0x00000800;
}

void USART_Configuration(void)
{
    // USART1配置:115200,8,N,1
    USART1->BRR = 0x0271;
    USART1->CR1 = 0x200C;
    USART1->CR2 = 0x0000;
    USART1->CR3 = 0x0000;
}

void I2C_Configuration(void)
{
    // I2C1配置
    I2C1->CR1 = 0x0000;
    I2C1->CR2 = 0x0018;
    I2C1->CCR = 0x0050;
    I2C1->TRISE = 0x0013;
    I2C1->CR1 = 0x0001;
}

void TIM_Configuration(void)
{
    // TIM3用于延时和定时任务
    TIM3->PSC = 7199;
    TIM3->ARR = 9999;
    TIM3->CR1 = 0x0084;
    TIM3->DIER = 0x0001;
    
    NVIC->ISER[0] |= 0x00001000;
    TIM3->CR1 |= 0x0001;
}

void Sensor_Data_Update(void)
{
    // 读取CO2浓度
    co2_ppm = SGP30_ReadCO2();
    
    // 读取温湿度
    if(DHT22_ReadData(&temperature, &humidity) == SUCCESS)
    {
        // 温湿度读取成功
    }
    
    // 读取光照强度
    light_intensity = GY30_ReadLight();
}

void CO2_Control_Logic(void)
{
    // CO2施肥控制算法
    if(co2_ppm < CO2_TARGET_MIN)
    {
        // CO2浓度过低,开启施肥
        Relay_ON();
        relay_state = 1;
    }
    else if(co2_ppm > CO2_TARGET_MAX)
    {
        // CO2浓度过高,关闭施肥
        Relay_OFF();
        relay_state = 0;
    }
    
    // 考虑光照和温度条件的优化控制
    if(light_intensity < 5000 || temperature < 15 || temperature > 35)
    {
        // 光照不足或温度不适宜时停止施肥
        Relay_OFF();
        relay_state = 0;
    }
}

void Cloud_Data_Upload(void)
{
    char upload_data[256];
    
    // 构建JSON格式数据
    sprintf(upload_data, 
            "{\"co2\":%d,\"temp\":%.1f,\"humi\":%.1f,\"light\":%d,\"relay\":%d}",
            co2_ppm, temperature, humidity, light_intensity, relay_state);
    
    // 通过ESP8266上传到华为云
    ESP8266_SendData(upload_data);
}

// TIM3中断服务函数
void TIM3_IRQHandler(void)
{
    if(TIM3->SR & 0x0001)
    {
        TIM3->SR &= ~0x0001;
        // 定时任务处理
    }
}

// USART1中断服务函数
void USART1_IRQHandler(void)
{
    if(USART1->SR & 0x0020)
    {
        uint8_t data = USART1->DR;
        // ESP8266数据接收处理
        ESP8266_ReceiveHandler(data);
    }
}

总结

本系统基于STM32F103C8T6核心板设计,实现了智能温室二氧化碳施肥的全面监控与控制。通过集成多种传感器,系统能够实时采集CO2浓度、温度、湿度和光照强度等环境参数,并利用自动控制机制精准调节CO2发生装置,确保作物在最优条件下生长。

硬件组成包括SGP30 CO2传感器、DHT22温湿度传感器和GY-30光照传感器,用于精确监测环境数据,而继电器模块则负责执行CO2施肥操作。ESP8266-01S Wi-Fi模块实现了与华为云的稳定通信,支持远程数据传输和监控。

系统还配备了QT上位机界面,方便用户实时查看环境参数和施肥效果分析,从而进行数据驱动的决策优化。这种集成设计不仅提高了温室管理的自动化水平,还增强了系统的可靠性和实用性。

总体而言,该系统通过智能控制和远程通信技术,有效提升了温室种植的精准度和效率,为现代农业的可持续发展提供了有力的技术支持。其模块化结构和可扩展性,使其在智能农业应用中具有广泛的前景和价值。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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