一、前言
随着人们对健康和可持续生活方式的关注不断增加,蔬菜大棚成为了现代农业中的重要组成部分。蔬菜大棚提供了一个受控的环境,使得农民能够在任何季节种植蔬菜,并根据需要进行调节。为了实现最佳的蔬菜生长和产量,对温度和湿度等环境条件的精确控制至关重要。
传统的蔬菜大棚管理通常依赖于人工监测和调节。这种方法存在一些问题,例如人工监测容易出现误差和延迟,而且对于大规模的蔬菜大棚来说,人工调节工作量巨大。所以开发一种基于智能控制系统的蔬菜大棚温湿度管理方案变得非常重要。
基于STM32微控制器的蔬菜大棚温湿度智能控制系统用于解决传统管理方法的问题,并提供一种自动化的解决方案。该系统利用STM32微控制器的强大计算和控制能力,结合温湿度传感器和执行器,实现对蔬菜大棚环境的精确监测和控制。
通过该系统,农民可以实时监测蔬菜大棚内的温度和湿度,并根据预设的目标范围自动调节。系统可以自动控制温室内的加热器、通风设备和加湿器等设备,以维持最适宜的生长环境条件。项目的目标是提高蔬菜大棚的生产效率和质量,降低能源消耗,并减少人力投入。通过智能控制系统的应用,农民能够实现更加可持续和高效的农业生产,为社会提供更多健康的蔬菜产品。
二、系统设计流程
2.1 硬件选型
硬件选型是设计蔬菜大棚温湿度智能控制系统的重要环节。
【1】主控芯片:STM32F103ZET6 主控芯片使用STM32F103ZET6,它是一款高性能的ARM Cortex-M3内核微控制器,具有丰富的外设资源和强大的处理能力。该芯片可满足本项目对控制和数据处理的要求。
【2】温湿度传感器:DHT11 空气温湿度采集选用DHT11传感器,它采用数字信号输出,具有简单、低成本和较好的精度,适合大棚环境的温湿度监测。
【3】土壤湿度传感器:土壤湿度传感器 土壤湿度采集选用土壤湿度传感器,通过模拟-数字转换器(ADC)接口采集土壤湿度数据。该传感器能够准确测量土壤湿度,为农作物提供合适的灌溉水量。
【4】通风风机:5V小风扇 继电器 为了实现通风控制,选择5V小风扇作为通风装置,并通过继电器控制其开关状态。根据温度数据和设定阈值,通过STM32的GPIO口控制继电器的高低电平实现通风风扇的启停控制。
【5】照明灯:LED白色灯模块 为了提供适当的照明条件,选择LED白色灯模块作为照明装置。该模块使用STM32的GPIO口控制其开关状态,实现灯光的开启和关闭。
【6】灌溉系统:抽水电机 继电器 灌溉系统采用抽水电机作为水源,并通过继电器控制其开启和关闭。通过单片机控制继电器的高低电平来控制抽水电机的工作状态,实现灌溉系统的自动化操作。
【7】显示模块:LCD显示屏 为了方便用户观察当前的温湿度等数据,选用LCD显示屏进行数据的显示。通过STM32的数字接口与LCD显示屏进行通信,将采集到的数据实时显示在屏幕上。
2.2 软件设计思路
本项目的代码设计思路可以分为以下几个关键部分:
【1】初始化设置:首先,需要进行主控芯片的初始化设置,包括引脚配置、时钟设置等。同时,还需要对LCD显示屏进行初始化配置,以便后续显示数据。
【2】传感器数据采集:使用合适的库函数或代码,读取DHT11传感器和土壤湿度传感器的数据。通过适当的接口与主控芯片进行通信,获取温度、湿度和土壤湿度的数值。
【3】数据处理与判断:根据采集到的温湿度和土壤湿度数值,进行相应的数据处理和判断。判断当前温度是否超出设定范围,以及土壤湿度是否低于设定阈值等。
【4】控制执行器:根据数据处理和判断的结果,控制相应的执行器,如通风风扇、照明灯和灌溉系统。通过设置相应的引脚电平或触发继电器,实现执行器的开启或关闭。
【5】LCD显示:将采集到的温湿度和土壤湿度数值通过LCD显示屏进行显示,以便用户实时监测。
【6】用户交互:通过按键输入或其他方式,实现用户与系统的交互。设置土壤湿度阈值、调节温度范围等。
【7】循环运行:将上述步骤组织成一个循环运行的程序,确保系统能够持续采集数据、处理判断和控制执行器的操作。
三、代码实现
3.1 DHT11温湿度读取
读取DHT11传感器环境温湿度并通过串口打印出来。
代码语言:javascript复制#include "stm32f10x.h"
#include "stdio.h"
// 定义DHT11数据引脚
#define DHT11_PIN GPIO_Pin_0
#define DHT11_PORT GPIOA
// DHT11初始化函数
void DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置DHT11引脚为推挽输出
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}
// 延时函数,单位为微秒
void Delay_us(uint32_t nCount)
{
uint32_t i;
for(i=0; i<nCount; i );
}
// 软件延时函数,单位为毫秒
void Delay_ms(uint32_t nCount)
{
uint32_t i;
for(i=0; i<nCount*1000; i );
}
// 从DHT11读取一位数据
uint8_t DHT11_ReadBit(void)
{
uint8_t retries = 0;
while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == Bit_RESET)
{
if (retries > 100) return 0;
Delay_us(1);
}
Delay_us(40); // 延时40us
if (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == Bit_SET)
retries = 100; // 超时标识
else
retries = 0;
while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == Bit_SET)
{
if (retries > 100) return 0;
Delay_us(1);
}
return 1;
}
// 从DHT11读取一个字节数据
uint8_t DHT11_ReadByte(void)
{
uint8_t i, temp = 0;
for(i=0; i<8; i )
{
temp <<= 1;
temp |= DHT11_ReadBit();
}
return temp;
}
// 读取DHT11的温湿度值
uint8_t DHT11_ReadData(uint8_t* temperature, uint8_t* humidity)
{
uint8_t data[5], checksum;
// 主机将总线拉低至少18ms
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
GPIO_ResetBits(DHT11_PORT, DHT11_PIN);
Delay_ms(20);
GPIO_SetBits(DHT11_PORT, DHT11_PIN);
Delay_us(30);
// 设置为输入模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
// 等待 DHT11 响应
if (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == Bit_RESET)
{
while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == Bit_RESET);
while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == Bit_SET);
// 读取5字节数据
for(uint8_t i=0; i<5; i )
data[i] = DHT11_ReadByte();
// 读取校验和
checksum = DHT11_ReadByte();
// 校验数据
if((data[0] data[1] data[2] data[3]) != checksum)
return 0;
*humidity = data[0];
*temperature = data[2];
return 1;
}
else
{
return 0;
}
}
// 初始化USART1
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 使能USART1和GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置USART1的引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // TX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // RX
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置USART1
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
// 使能USART1
USART_Cmd(USART1, ENABLE);
}
// 发送字符到USART1
void USART1_SendChar(char ch)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, (uint8_t)ch);
}
// 发送字符串到USART1
void USART1_SendString(const char* str)
{
while(*str)
{
USART1_SendChar(*str );
}
}
int main(void)
{
uint8_t temperature, humidity;
// 初始化DHT11和USART1
DHT11_Init();
USART1_Init();
while(1)
{
if (DHT11_ReadData(&temperature, &humidity))
{
// 发送温湿度数据到串口
char buffer[50];
sprintf(buffer, "Temperature: %d°C, Humidity: %d%%rn", temperature, humidity);
USART1_SendString(buffer);
}
Delay_ms(2000); // 2秒钟读取一次数据
}
}
将代码下载到STM32F103ZET6开发板上,接上DHT11。当成功运行时,环境温湿度数据会通过USART1串口打印出来。
3.2 读取土壤湿度值
通过ADC1的通道1采集土壤传感器的湿度值,打印到串口.
代码语言:javascript复制#include "stm32f10x.h"
#include "stdio.h"
// 函数声明
void ADC_Configuration(void);
void UART_Configuration(void);
void USART1_SendChar(char ch);
int main(void)
{
// 初始化ADC和串口
ADC_Configuration();
UART_Configuration();
while (1)
{
// 启动ADC转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
// 等待转换完成
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
// 读取ADC值
uint16_t adcValue = ADC_GetConversionValue(ADC1);
// 将ADC值转换为湿度百分比
float humidity = (float)adcValue / 4095 * 100;
// 将湿度值打印到串口
char buffer[20];
sprintf(buffer, "Humidity: %.2f%%rn", humidity);
for (int i = 0; buffer[i] != '