基于STM32设计的智能温室二氧化碳施肥系统
项目开发背景
随着全球人口持续增长和农业资源日益紧张,高效、可持续的农业生产方式成为解决粮食安全问题的关键。温室农业作为一种可控环境农业技术,能够通过优化作物生长条件来提高产量和品质,尤其在现代城市化进程中,其重要性日益凸显。然而,传统温室管理多依赖人工经验,难以实现精准调控,导致资源浪费和效率低下,特别是在二氧化碳施肥方面,不当的控制可能引发环境问题或作物生长不均。
二氧化碳是植物光合作用的重要原料,在温室环境中,适当增加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 +=
这个上位机程序包含以下主要功能:
-
实时监控:
- 显示CO2浓度、温度、湿度和光照强度
- 实时曲线图表显示历史数据
- 设备连接状态监控
-
数据分析:
- 数据表格记录历史数据
- 施肥效果分析
- 环境参数评估
-
控制设置:
- CO2目标浓度设置
- 自动/手动模式切换
- 控制指令发送
- 控制状态日志
-
华为云通信:
- 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上位机界面,方便用户实时查看环境参数和施肥效果分析,从而进行数据驱动的决策优化。这种集成设计不仅提高了温室管理的自动化水平,还增强了系统的可靠性和实用性。
总体而言,该系统通过智能控制和远程通信技术,有效提升了温室种植的精准度和效率,为现代农业的可持续发展提供了有力的技术支持。其模块化结构和可扩展性,使其在智能农业应用中具有广泛的前景和价值。
- 点赞
- 收藏
- 关注作者
评论(0)