项目开发背景
随着全球人口持续增长和粮食安全需求的日益凸显,现代农业正面临着提高生产效率、降低资源消耗的紧迫挑战。智能农业大棚作为精准农业的关键应用,通过集成物联网技术,能够实现对作物生长环境的实时监测与自动化控制,从而优化生长条件,提升农作物产量和质量,同时减少人力依赖和运营成本。
传统农业大棚管理多依赖于人工经验和定期检查,这种方式效率较低,且难以应对环境参数的突发变化。土壤湿度、空气温湿度、光照强度等因素的不稳定性往往导致灌溉、通风和补光操作不及时,易造成水资源浪费、能源过度使用或作物生长受阻。此外,缺乏远程监控和数据分析能力,限制了大规模农业管理的可扩展性和响应速度。
本项目开发基于STM32F103C8T6微控制器的智能农业大棚监控系统,旨在解决这些痛点。系统通过土壤湿度传感器、DHT22温湿度传感器和GY-30光照传感器实时采集环境数据,并利用STM32主控制器进行数据处理和决策,自动控制继电器模块驱动水泵、风扇及补光灯设备,实现灌溉、通风和补光的智能化调节。同时,借助ESP8266-01S Wi-Fi模块,系统将环境数据上传至华为云平台,实现数据的存储、分析和可视化,为农户提供长期趋势洞察和预警功能。
此外,通过QT上位机设计,用户能够远程监控大棚环境参数,并支持手动控制设备,增强了系统的灵活性和用户体验。这一设计不仅推动了农业生产的数字化转型,还为可持续农业提供了技术支撑,有望在资源节约、产量提升和经济效益方面发挥重要作用。
设计实现的功能
(1) 使用土壤湿度传感器、DHT22温湿度传感器和GY-30光照传感器实时监测大棚内的土壤湿度、空气温湿度及光照强度。
(2) 基于监测的环境参数,通过继电器模块自动控制灌溉水泵、通风风扇及补光灯设备,实现智能调节。
(3) 通过ESP8266-01S Wi-Fi模块将农作物生长环境数据上传至华为云平台,进行存储和分析。
(4) 通过QT上位机软件远程监控大棚环境数据,并支持手动控制灌溉、通风及补光设备。
项目硬件模块组成
(1) STM32F103C8T6最小系统核心板作为主控制器。
(2) 土壤湿度传感器监测土壤含水率。
(3) DHT22温湿度传感器监测空气环境。
(4) GY-30光照传感器监测光照强度。
(5) 继电器模块控制水泵、风扇及补光灯设备。
(6) ESP8266-01S Wi-Fi模块实现华为云平台通信。
设计意义
该智能农业大棚监控系统基于STM32F103C8T6设计,实现了对大棚内关键环境参数的实时监测和自动控制,显著提升了农业生产的智能化水平。通过集成土壤湿度、空气温湿度和光照强度传感器,系统能够精确采集作物生长环境数据,为精准农业提供数据基础,从而优化资源利用,提高农作物产量和质量。
系统具备自动控制功能,可根据环境参数智能调节灌溉、通风和补光设备,减少人工干预,降低劳动成本,同时避免资源浪费,如节水节电,促进可持续农业发展。这种自动化响应确保了作物始终处于最佳生长环境中,增强了农业生产的稳定性和可靠性。
借助ESP8266-01S Wi-Fi模块,系统将环境数据上传至华为云平台进行存储和分析,实现了远程数据管理和历史趋势追踪。这为农户提供了决策支持,通过云平台的分析功能,可以识别环境 patterns,预测潜在问题,并优化种植策略,提升农业管理的科学性和效率。
此外,QT上位机支持远程监控和设备手动控制,使农户能够随时随地查看大棚状态并进行干预,增强了系统的灵活性和实用性。这套系统不仅适用于单个大棚,还可扩展至大规模农业园区,推动农业现代化进程,符合当今智慧农业的发展趋势。
设计思路
设计思路基于STM32F103C8T6最小系统核心板作为主控制器,负责协调整个系统的运行。该系统通过集成土壤湿度传感器、DHT22温湿度传感器和GY-30光照传感器,实时采集大棚内的环境参数,包括土壤含水率、空气温湿度和光照强度。主控制器定期读取这些传感器的数据,并进行初步处理,以确保数据的准确性和稳定性。
采集到的环境数据用于实现自动控制功能。主控制器根据预设的阈值条件,例如土壤湿度低于一定值时启动灌溉,空气温度过高时开启通风,或光照不足时触发补光。这些控制操作通过继电器模块驱动水泵、风扇和补光灯设备,确保农作物生长环境始终处于 optimal 状态,同时减少人工干预。
数据上传至华为云平台是通过ESP8266-01S Wi-Fi模块实现的。主控制器将处理后的环境数据打包,通过串口通信发送给ESP8266模块,后者利用MQTT或HTTP协议将数据上传到华为云进行存储和分析。这允许用户远程访问历史数据和趋势,支持决策优化,如调整控制阈值或分析作物生长条件。
此外,系统支持QT上位机进行远程监控。上位机通过网络与华为云平台或直接与ESP8266模块通信,实时显示大棚环境数据,并允许用户手动控制设备,如强制启动灌溉或通风。这提供了灵活的远程管理方式,增强了系统的实用性和可操作性。
框架图
+-------------------+ +-----------------------+
| 土壤湿度传感器 |------| |
+-------------------+ | |
+-------------------+ | STM32F103C8T6 | +-------------------+
| DHT22温湿度传感器 |------| 主控制器 |------| 继电器模块 |
+-------------------+ | | +-------------------+
+-------------------+ | | |
| GY-30光照传感器 |------| | V
+-------------------+ +-----------------------+ +-------------------+
| | 水泵、风扇、补光灯 |
| +-------------------+
|
| 通过UART/SPI/I2C
|
+-------------------+
| ESP8266-01S |
| Wi-Fi模块 |
+-------------------+
|
| Wi-Fi
|
+-------------------+
| 华为云平台 |
| (存储、分析) |
+-------------------+
|
| 互联网
|
+-------------------+
| QT上位机 |
| (远程监控) |
+-------------------+
系统总体设计
系统以STM32F103C8T6最小系统核心板作为主控制器,负责协调整个智能农业大棚监控系统的运行。该系统集成多种传感器模块,包括土壤湿度传感器用于监测土壤含水率,DHT22温湿度传感器用于采集空气环境中的温度和湿度数据,以及GY-30光照传感器用于检测光照强度。这些传感器实时采集大棚内的环境参数,并通过STM32的ADC和数字接口进行数据处理和转换。
基于采集到的环境参数,系统实现自动控制功能。STM32控制器通过逻辑判断,当土壤湿度低于设定阈值时自动启动灌溉水泵,当空气温湿度或光照强度超出预设范围时控制通风风扇或补光灯设备。继电器模块作为执行机构,接收STM32的输出信号,切换水泵、风扇和补光灯的电源状态,确保农作物生长环境维持在 optimal 条件。
系统通过ESP8266-01S Wi-Fi模块与华为云平台建立通信连接,实现数据上传功能。STM32将处理后的环境数据封装成协议格式,通过串口发送至ESP8266模块,由Wi-Fi模块将数据无线传输到华为云平台进行存储和进一步分析。这允许用户远程访问历史数据和趋势,支持农业决策。
此外,QT上位机软件提供远程监控界面,用户可以通过网络连接实时查看大棚环境数据,并支持手动控制灌溉、通风和补光设备。上位机与STM32系统通过Wi-Fi通信,实现双向数据交互,增强了系统的灵活性和可操作性。
系统功能总结
功能 | 实现方式 |
---|---|
监测大棚内土壤湿度、空气温湿度及光照强度 | 土壤湿度传感器、DHT22温湿度传感器、GY-30光照传感器 |
根据环境参数自动控制灌溉、通风及补光设备 | 继电器模块控制水泵、风扇及补光灯设备 |
农作物生长环境数据上传至华为云平台存储分析 | ESP8266-01S Wi-Fi模块实现通信 |
QT上位机远程监控大棚环境,支持设备手动控制 | QT上位机软件 |
设计的各个功能模块描述
STM32F103C8T6最小系统核心板作为主控制器,负责协调整个系统的运行。它通过ADC接口读取土壤湿度传感器的模拟信号,通过数字接口与DHT22和GY-30传感器通信,获取环境参数数据,并根据预设阈值自动控制继电器模块,实现灌溉、通风和补光设备的智能调节。同时,主控制器通过串口与ESP8266-01S Wi-Fi模块交互,处理数据上传和接收指令。
土壤湿度传感器用于监测大棚内土壤的含水率,通常以模拟电压输出形式连接到STM32的ADC引脚,主控制器定期采样并转换为数字值,用于判断土壤干湿状态,从而触发自动灌溉或停止。
DHT22温湿度传感器监测空气环境的温度和湿度,通过单总线协议与STM32通信,提供高精度的数字输出,主控制器读取这些数据用于环境评估和自动控制通风设备。
GY-30光照传感器基于BH1750芯片,通过I2C接口与STM32连接,测量光照强度,输出数字值,主控制器根据光照水平决定是否启用补光灯,以维持农作物所需的光照条件。
继电器模块由STM32通过GPIO引脚控制,用于开关水泵、风扇和补光灯等设备,实现自动化的灌溉、通风和补光操作,同时支持手动 override 通过上位机指令。
ESP8266-01S Wi-Fi模块通过串口与STM32通信,负责将采集的环境数据上传至华为云平台,并接收云平台或上位机的控制指令,实现远程数据交换和设备管理。
华为云平台作为数据存储和分析中心,接收来自ESP8266模块上传的土壤湿度、空气温湿度和光照强度数据,进行历史记录、趋势分析和报警处理,用户可通过云平台API或界面查看报告。
QT上位机软件运行于远程计算机,通过网络与华为云平台或直接与ESP8266模块通信,提供图形化界面用于实时监控大棚环境参数,支持用户手动控制继电器设备,如启动灌溉或调整通风。
上位机代码设计
以下是基于QT框架的C++上位机代码设计,用于远程监控智能农业大棚系统。代码通过HTTP协议与华为云平台通信,获取环境数据并发送控制命令。假设华为云平台提供RESTful API,使用JSON格式传输数据。实际使用时,需替换API URL和认证信息。
项目文件结构:
main.cpp
:应用程序入口。mainwindow.h
:主窗口类声明。mainwindow.cpp
:主窗口类实现。mainwindow.ui
:QT设计师文件(UI布局,需通过QT Designer创建,这里省略具体UI代码,仅描述控件)。
代码实现:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
#include <QJsonDocument>
#include <QJsonObject>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void onDataReceived(QNetworkReply *reply);
void onControlButtonClicked();
void fetchData();
void sendControlCommand(const QString &device, bool state);
private:
Ui::MainWindow *ui;
QNetworkAccessManager *manager;
QTimer *timer;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h" // 假设通过QT Designer生成UI文件
#include <QPushButton>
#include <QLabel>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, manager(new QNetworkAccessManager(this))
, timer(new QTimer(this))
{
ui->setupUi(this);
// 初始化UI元素(假设UI中已有以下控件):
// - QLabel *labelSoilHumidity, *labelAirTemp, *labelAirHumidity, *labelLight
// - QPushButton *btnPump, *btnFan, *btnLight
// 连接按钮信号槽
connect(ui->btnPump, &QPushButton::clicked, this, &MainWindow::onControlButtonClicked);
connect(ui->btnFan, &QPushButton::clicked, this, &MainWindow::onControlButtonClicked);
connect(ui->btnLight, &QPushButton::clicked, this, &MainWindow::onControlButtonClicked);
// 设置定时器,每5秒获取数据
connect(timer, &QTimer::timeout, this, &MainWindow::fetchData);
timer->start(5000);
// 初始获取数据
fetchData();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::fetchData()
{
// 从华为云平台获取数据(示例URL,需替换实际API端点)
QUrl url("https://api.huaweicloud.com/your-api-endpoint/data");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
// 添加认证头(示例,使用Bearer token)
request.setRawHeader("Authorization", "Bearer your-token-here");
QNetworkReply *reply = manager->get(request);
connect(reply, &QNetworkReply::finished, this, [this, reply]() { onDataReceived(reply); });
}
void MainWindow::onDataReceived(QNetworkReply *reply)
{
if (reply->error() == QNetworkReply::NoError) {
QByteArray response = reply->readAll();
QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
QJsonObject jsonObj = jsonDoc.object();
// 解析JSON数据(假设返回格式为:{"soil_humidity": value, "air_temp": value, "air_humidity": value, "light": value})
double soilHumidity = jsonObj["soil_humidity"].toDouble();
double airTemp = jsonObj["air_temp"].toDouble();
double airHumidity = jsonObj["air_humidity"].toDouble();
double light = jsonObj["light"].toDouble();
// 更新UI
ui->labelSoilHumidity->setText(QString::number(soilHumidity) + " %");
ui->labelAirTemp->setText(QString::number(airTemp) + " °C");
ui->labelAirHumidity->setText(QString::number(airHumidity) + " %");
ui->labelLight->setText(QString::number(light) + " lux");
} else {
QMessageBox::warning(this, "Error", "Failed to fetch data: " + reply->errorString());
}
reply->deleteLater();
}
void MainWindow::onControlButtonClicked()
{
QPushButton *button = qobject_cast<QPushButton*>(sender());
if (!button) return;
QString device;
if (button == ui->btnPump) {
device = "pump";
} else if (button == ui->btnFan) {
device = "fan";
} else if (button == ui->btnLight) {
device = "light";
} else {
return;
}
// 切换按钮状态并发送控制命令
bool currentState = (button->text() == "ON");
bool newState = !currentState;
sendControlCommand(device, newState);
button->setText(newState ? "ON" : "OFF");
}
void MainWindow::sendControlCommand(const QString &device, bool state)
{
// 发送控制命令到华为云平台(示例URL,需替换实际API端点)
QUrl url("https://api.huaweicloud.com/your-api-endpoint/control");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Authorization", "Bearer your-token-here");
QJsonObject json;
json["device"] = device;
json["state"] = state;
QJsonDocument jsonDoc(json);
QByteArray data = jsonDoc.toJson();
QNetworkReply *reply = manager->post(request, data);
connect(reply, &QNetworkReply::finished, [reply]() {
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Control command failed: " << reply->errorString();
}
reply->deleteLater();
});
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
使用说明:
- UI设计:使用QT Designer创建UI文件(
mainwindow.ui
),包含以下控件:- QLabel用于显示土壤湿度、空气温度、空气湿度、光照强度。
- QPushButton用于控制水泵、风扇、补光灯(初始文本为"OFF")。
- 华为云API:替换代码中的URL和认证令牌为实际华为云平台的API端点。
- 编译运行:使用QT Creator打开项目,编译并运行。
此代码实现了数据定时获取、显示和设备控制功能。实际部署时,需根据华为云API的具体规范调整JSON解析和网络请求。
模块代码设计
#include "stm32f10x.h"
// 系统时钟配置
void SystemInit(void) {
// 启用HSE
RCC->CR |= ((uint32_t)0x00010000); // HSEON
while (!(RCC->CR & 0x00020000)); // 等待HSERDY
// 配置PLL: HSE作为源,9倍频到72MHz
RCC->CFGR &= ~((uint32_t)0x00030000); // 清除PLLSRC
RCC->CFGR |= ((uint32_t)0x00010000); // PLLSRC = HSE
RCC->CFGR &= ~((uint32_t)0x003C0000); // 清除PLLMUL
RCC->CFGR |= ((uint32_t)0x001C0000); // PLLMUL = 9 (0x7 << 18)
// 启用PLL
RCC->CR |= 0x01000000; // PLLON
while (!(RCC->CR & 0x02000000)); // 等待PLLRDY
// 切换系统时钟到PLL
RCC->CFGR &= ~((uint32_t)0x00000003);
RCC->CFGR |= 0x00000002; // SW = PLL
while ((RCC->CFGR & 0x0000000C) != 0x08); // 等待SWS = PLL
}
// ADC初始化 for 土壤湿度传感器 (PA0)
void ADC1_Init(void) {
RCC->APB2ENR |= 0x00000200; // 启用ADC1时钟
GPIOA->CRL &= ~0x0000000F; // 清除PA0配置
GPIOA->CRL |= 0x00000000; // 模拟输入模式
ADC1->CR2 = 0x00000001; // ADON使能
ADC1->SQR1 = 0x00000000; // 1个转换
ADC1->SQR3 = 0x00000000; // 通道0
ADC1->SMPR2 = 0x00000007; // 通道0采样时间239.5周期
}
uint16_t ADC_Read(uint8_t channel) {
ADC1->SQR3 = channel;
ADC1->CR2 |= 0x00000001; // 开始转换
while (!(ADC1->SR & 0x00000002)); // 等待EOC
return ADC1->DR;
}
// DHT22温湿度传感器 (PA1)
void DHT22_Init(void) {
GPIOA->CRL &= ~0x000000F0; // 清除PA1配置
GPIOA->CRL |= 0x00000030; // 推挽输出,50MHz
}
void Delay_us(uint32_t us) {
us *= 8; // 粗略延时,基于72MHz时钟
while (us--);
}
uint8_t DHT22_Read(float *humidity, float *temperature) {
uint8_t data[5] = {0};
uint8_t i, j;
// 发送开始信号
GPIOA->BSRR = 0x00020000; // PA1低
Delay_us(1000);
GPIOA->BSRR = 0x00000002; // PA1高
Delay_us(30);
// 配置为输入带上拉
GPIOA->CRL &= ~0x000000F0;
GPIOA->CRL |= 0x00000040; // 输入带上拉/下拉
GPIOA->ODR |= 0x00000002; // 上拉使能
// 等待响应
Delay_us(40);
if (GPIOA->IDR & 0x00000002) return 0; // 无响应
while (!(GPIOA->IDR & 0x00000002)); // 等待低电平
while (GPIOA->IDR & 0x00000002); // 等待高电平
// 读取40位数据
for (i = 0; i < 5; i++) {
for (j = 0; j < 8; j++) {
while (!(GPIOA->IDR & 0x00000002)); // 等待低电平开始
Delay_us(30);
if (GPIOA->IDR & 0x00000002) {
data[i] |= (1 << (7 - j));
while (GPIOA->IDR & 0x00000002); // 等待高电平结束
}
}
}
// 校验和检查
if (data[4] != (data[0] + data[1] + data[2] + data[3])) return 0;
// 转换数据
*humidity = (data[0] * 256 + data[1]) / 10.0;
*temperature = (data[2] * 256 + data[3]) / 10.0;
return 1;
}
// GY-30光照传感器 (I2C1, PB6 SCL, PB7 SDA)
void I2C1_Init(void) {
RCC->APB1ENR |= 0x00200000; // 启用I2C1时钟
RCC->APB2ENR |= 0x00000008; // 启用GPIOB时钟
GPIOB->CRL &= ~0xFF000000; // 清除PB6和PB7配置
GPIOB->CRL |= 0x99000000; // AF开漏输出,50MHz
I2C1->CR1 = 0x00000000; // 禁用I2C
I2C1->CR2 = 0x00000008; // FREQ = 8MHz (假设APB1为36MHz)
I2C1->CCR = 0x000000B4; // CCR for 100kHz
I2C1->TRISE = 0x00000009; // 最大上升时间
I2C1->CR1 = 0x00000001; // 启用I2C
}
void I2C_Start(void) {
I2C1->CR1 |= 0x00000100; // START
while (!(I2C1->SR1 & 0x00000001)); // 等待SB
}
void I2C_Stop(void) {
I2C1->CR1 |= 0x00000200; // STOP
while (I2C1->SR2 & 0x00000001); // 等待MSL清除
}
void I2C_WriteByte(uint8_t data) {
I2C1->DR = data;
while (!(I2C1->SR1 & 0x00000080)); // 等待TXE
}
uint8_t I2C_ReadByte(void) {
while (!(I2C1->SR1 & 0x00000040)); // 等待RXNE
return I2C1->DR;
}
#define BH1750_ADDR 0x23
uint16_t BH1750_ReadLight(void) {
I2C_Start();
I2C_WriteByte(BH1750_ADDR << 1);
I2C_WriteByte(0x10); // 连续高分辨率模式
I2C_Stop();
// 延时等待测量
for (volatile uint32_t i = 0; i < 180000; i++); // 粗略延时180ms
I2C_Start();
I2C_WriteByte((BH1750_ADDR << 1) | 1);
uint8_t high = I2C_ReadByte();
uint8_t low = I2C_ReadByte();
I2C_Stop();
return (high << 8) | low;
}
// ESP8266 Wi-Fi模块 (USART2, PA2 TX, PA3 RX)
void USART2_Init(void) {
RCC->APB1ENR |= 0x00020000; // 启用USART2时钟
RCC->APB2ENR |= 0x00000004; // 启用GPIOA时钟
GPIOA->CRL &= ~0x0000FF00; // 清除PA2和PA3配置
GPIOA->CRL |= 0x00004B00; // PA2: AF推挽输出, PA3: 输入浮空
USART2->BRR = 0x00001D4C; // 72MHz, 9600 baud
USART2->CR1 = 0x0000000C; // 启用TX和RX
USART2->CR1 |= 0x00002000; // 启用USART
}
void USART2_SendChar(char c) {
while (!(USART2->SR & 0x00000080)); // 等待TXE
USART2->DR = c;
}
void USART2_SendString(const char *str) {
while (*str) {
USART2_SendChar(*str++);
}
}
char USART2_ReceiveChar(void) {
while (!(USART2->SR & 0x00000020)); // 等待RXNE
return USART2->DR;
}
// 继电器控制 (PC13, PC14, PC15)
void Relay_Init(void) {
RCC->APB2ENR |= 0x00000010; // 启用GPIOC时钟
GPIOC->CRH &= ~0xFFF00000; // 清除PC13-15配置
GPIOC->CRH |= 0x33300000; // 推挽输出,50MHz
}
void Relay_Control(uint8_t relay, uint8_t state) {
if (state) {
GPIOC->BSRR = (1 << (relay + 13));
} else {
GPIOC->BRR = (1 << (relay + 13));
}
}
// 主函数
int main(void) {
SystemInit();
ADC1_Init();
DHT22_Init();
I2C1_Init();
USART2_Init();
Relay_Init();
float humidity = 0, temperature = 0;
uint16_t soil_moisture = 0, light_intensity = 0;
while (1) {
soil_moisture = ADC_Read(0);
if (DHT22_Read(&humidity, &temperature)) {
// 数据有效
}
light_intensity = BH1750_ReadLight();
// 自动控制逻辑
if (soil_moisture < 500) Relay_Control(0, 1); else Relay_Control(0, 0); // 土壤湿度控制水泵
if (temperature > 30.0) Relay_Control(1, 1); else Relay_Control(1, 0); // 温度控制风扇
if (light_intensity < 10000) Relay_Control(2, 1); else Relay_Control(2, 0); // 光照控制补光灯
// 数据上传华为云(示例AT命令)
char buffer[100];
sprintf(buffer, "AT+CIPSEND=0,100\r\n");
USART2_SendString(buffer);
// 等待ESP8266响应
while (USART2_ReceiveChar() != '>'); // 等待提示符
sprintf(buffer, "Soil:%d,Temp:%.2f,Hum:%.2f,Light:%d\r\n", soil_moisture, temperature, humidity, light_intensity);
USART2_SendString(buffer);
// 简单延时
for (volatile uint32_t i = 0; i < 5000000; i++);
}
}
项目核心代码
#include "stm32f10x.h"
#include <stdio.h>
#include <string.h>
// 假设外部模块函数原型
extern void DHT22_Init(void);
extern void DHT22_Read(float *temperature, float *humidity);
extern void GY30_Init(void);
extern uint16_t GY30_ReadLight(void);
extern uint16_t ReadSoilMoisture(void);
extern void ESP8266_Init(void);
extern void ESP8266_SendData(char *data);
extern void Relay_Control(uint8_t device, uint8_t state);
extern void UART1_RX_Handler(void); // 处理UART接收数据
// 引脚定义
#define SOIL_MOISTURE_ADC_CHANNEL ADC_Channel_0
#define DHT22_PIN GPIO_Pin_1
#define DHT22_PORT GPIOA
#define PUMP_PIN GPIO_Pin_0
#define FAN_PIN GPIO_Pin_1
#define LIGHT_PIN GPIO_Pin_2
#define RELAY_PORT GPIOC
// 全局变量
volatile uint32_t tick = 0;
char uart_rx_buffer[100];
volatile uint8_t uart_rx_index = 0;
// 函数原型
void SystemClock_Config(void);
void GPIO_Init(void);
void ADC_Init(void);
void I2C_Init(void);
void UART_Init(void);
void SysTick_Init(void);
void Delay_ms(uint32_t ms);
void USART1_IRQHandler(void);
int main(void) {
SystemClock_Config();
GPIO_Init();
ADC_Init();
I2C_Init();
UART_Init();
SysTick_Init();
DHT22_Init();
GY30_Init();
ESP8266_Init();
float air_temp, air_humidity;
uint16_t soil_moisture, light_intensity;
while(1) {
DHT22_Read(&air_temp, &air_humidity);
soil_moisture = ReadSoilMoisture();
light_intensity = GY30_ReadLight();
if (soil_moisture < 500) {
Relay_Control(0, 1);
} else {
Relay_Control(0, 0);
}
if (air_temp > 30.0) {
Relay_Control(1, 1);
} else {
Relay_Control(1, 0);
}
if (light_intensity < 300) {
Relay_Control(2, 1);
} else {
Relay_Control(2, 0);
}
char data[100];
sprintf(data, "{\"temp\":%.2f,\"hum\":%.2f,\"soil\":%d,\"light\":%d}", air_temp, air_humidity, soil_moisture, light_intensity);
ESP8266_SendData(data);
Delay_ms(5000);
}
}
void SystemClock_Config(void) {
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY));
RCC->CFGR |= RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9;
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY));
FLASH->ACR |= FLASH_ACR_LATENCY_2;
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}
void GPIO_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN;
GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0);
GPIOA->CRL |= GPIO_CRL_CNF0_0;
GPIOC->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0 | GPIO_CRL_MODE1 | GPIO_CRL_CNF1 | GPIO_CRL_MODE2 | GPIO_CRL_CNF2);
GPIOC->CRL |= (GPIO_CRL_MODE0_0 | GPIO_CRL_MODE0_1) | (GPIO_CRL_MODE1_0 | GPIO_CRL_MODE1_1) | (GPIO_CRL_MODE2_0 | GPIO_CRL_MODE2_1);
GPIOC->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_CNF1 | GPIO_CRL_CNF2);
GPIOA->CRH &= ~(GPIO_CRH_MODE9 | GPIO_CRH_CNF9);
GPIOA->CRH |= GPIO_CRH_MODE9_0 | GPIO_CRH_MODE9_1;
GPIOA->CRH |= GPIO_CRH_CNF9_1;
GPIOA->CRH &= ~(GPIO_CRH_MODE10 | GPIO_CRH_CNF10);
GPIOA->CRH |= GPIO_CRH_CNF10_0;
}
void ADC_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
ADC1->SQR1 = 0;
ADC1->SQR3 = SOIL_MOISTURE_ADC_CHANNEL;
ADC1->SMPR2 = ADC_SMPR2_SMP0_0 | ADC_SMPR2_SMP0_1 | ADC_SMPR2_SMP0_2;
ADC1->CR2 = ADC_CR2_ADON;
ADC1->CR2 |= ADC_CR2_CAL;
while (ADC1->CR2 & ADC_CR2_CAL);
}
void I2C_Init(void) {
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
I2C1->CR2 = 36;
I2C1->CCR = 180;
I2C1->TRISE = 37;
I2C1->CR1 = I2C_CR1_PE;
}
void UART_Init(void) {
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
USART1->BRR = 72000000 / 115200;
USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_UE;
NVIC_EnableIRQ(USART1_IRQn);
}
void SysTick_Init(void) {
SysTick->LOAD = 72000 - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
}
void Delay_ms(uint32_t ms) {
tick = 0;
while (tick < ms);
}
void USART1_IRQHandler(void) {
if (USART1->SR & USART_SR_RXNE) {
uint8_t data = USART1->DR;
if (data == '\n' || uart_rx_index >= sizeof(uart_rx_buffer) - 1) {
uart_rx_buffer[uart_rx_index] = '\0';
UART1_RX_Handler();
uart_rx_index = 0;
} else {
uart_rx_buffer[uart_rx_index++] = data;
}
}
}
void SysTick_Handler(void) {
tick++;
}
总结
本设计基于STM32F103C8T6最小系统核心板,构建了一个智能农业大棚监控系统,实现了对大棚内环境参数的全面监测和自动控制。系统通过土壤湿度传感器、DHT22温湿度传感器和GY-30光照传感器,实时采集土壤含水率、空气温湿度及光照强度数据,确保农作物生长环境的精确监控。
系统能够根据采集的环境参数自动决策,通过继电器模块控制灌溉水泵、通风风扇和补光灯设备,实现智能化管理,从而提高农业生产的效率和资源利用率。这减少了人工干预,提升了大棚管理的自动化水平。
数据通过ESP8266-01S Wi-Fi模块上传至华为云平台,进行存储和分析,支持远程数据访问和历史趋势查询。同时,QT上位机提供了友好的远程监控界面,允许用户手动控制设备,增强了系统的灵活性和实用性。
整体而言,该系统集成了传感、控制、通信和云平台技术,展现了现代物联网在农业领域的应用潜力,为智能农业的发展提供了可靠的解决方案。