一、前言
隨著人們對健康和可持續(xù)生活方式的關(guān)注不斷增加,蔬菜大棚成為了現(xiàn)代農(nóng)業(yè)中的重要組成部分。蔬菜大棚提供了一個受控的環(huán)境,使得農(nóng)民能夠在任何季節(jié)種植蔬菜,并根據(jù)需要進(jìn)行調(diào)節(jié)。為了實現(xiàn)最佳的蔬菜生長和產(chǎn)量,對溫度和濕度等環(huán)境條件的精確控制至關(guān)重要。
傳統(tǒng)的蔬菜大棚管理通常依賴于人工監(jiān)測和調(diào)節(jié)。這種方法存在一些問題,例如人工監(jiān)測容易出現(xiàn)誤差和延遲,而且對于大規(guī)模的蔬菜大棚來說,人工調(diào)節(jié)工作量巨大。所以開發(fā)一種基于智能控制系統(tǒng)的蔬菜大棚溫濕度管理方案變得非常重要。
基于STM32微控制器的蔬菜大棚溫濕度智能控制系統(tǒng)用于解決傳統(tǒng)管理方法的問題,并提供一種自動化的解決方案。該系統(tǒng)利用STM32微控制器的強(qiáng)大計算和控制能力,結(jié)合溫濕度傳感器和執(zhí)行器,實現(xiàn)對蔬菜大棚環(huán)境的精確監(jiān)測和控制。
通過該系統(tǒng),農(nóng)民可以實時監(jiān)測蔬菜大棚內(nèi)的溫度和濕度,并根據(jù)預(yù)設(shè)的目標(biāo)范圍自動調(diào)節(jié)。系統(tǒng)可以自動控制溫室內(nèi)的加熱器、通風(fēng)設(shè)備和加濕器等設(shè)備,以維持最適宜的生長環(huán)境條件。項目的目標(biāo)是提高蔬菜大棚的生產(chǎn)效率和質(zhì)量,降低能源消耗,并減少人力投入。通過智能控制系統(tǒng)的應(yīng)用,農(nóng)民能夠?qū)崿F(xiàn)更加可持續(xù)和高效的農(nóng)業(yè)生產(chǎn),為社會提供更多健康的蔬菜產(chǎn)品。
二、系統(tǒng)設(shè)計流程
2.1 硬件選型
硬件選型是設(shè)計蔬菜大棚溫濕度智能控制系統(tǒng)的重要環(huán)節(jié)。
【1】主控芯片:STM32F103ZET6 主控芯片使用STM32F103ZET6,它是一款高性能的ARM Cortex-M3內(nèi)核微控制器,具有豐富的外設(shè)資源和強(qiáng)大的處理能力。該芯片可滿足本項目對控制和數(shù)據(jù)處理的要求。
【2】溫濕度傳感器:DHT11 空氣溫濕度采集選用DHT11傳感器,它采用數(shù)字信號輸出,具有簡單、低成本和較好的精度,適合大棚環(huán)境的溫濕度監(jiān)測。
【3】土壤濕度傳感器:土壤濕度傳感器 土壤濕度采集選用土壤濕度傳感器,通過模擬-數(shù)字轉(zhuǎn)換器(ADC)接口采集土壤濕度數(shù)據(jù)。該傳感器能夠準(zhǔn)確測量土壤濕度,為農(nóng)作物提供合適的灌溉水量。
【4】通風(fēng)風(fēng)機(jī):5V小風(fēng)扇+繼電器 為了實現(xiàn)通風(fēng)控制,選擇5V小風(fēng)扇作為通風(fēng)裝置,并通過繼電器控制其開關(guān)狀態(tài)。根據(jù)溫度數(shù)據(jù)和設(shè)定閾值,通過STM32的GPIO口控制繼電器的高低電平實現(xiàn)通風(fēng)風(fēng)扇的啟??刂?。
【5】照明燈:LED白色燈模塊 為了提供適當(dāng)?shù)恼彰鳁l件,選擇LED白色燈模塊作為照明裝置。該模塊使用STM32的GPIO口控制其開關(guān)狀態(tài),實現(xiàn)燈光的開啟和關(guān)閉。
【6】灌溉系統(tǒng):抽水電機(jī)+繼電器 灌溉系統(tǒng)采用抽水電機(jī)作為水源,并通過繼電器控制其開啟和關(guān)閉。通過單片機(jī)控制繼電器的高低電平來控制抽水電機(jī)的工作狀態(tài),實現(xiàn)灌溉系統(tǒng)的自動化操作。
【7】顯示模塊:LCD顯示屏 為了方便用戶觀察當(dāng)前的溫濕度等數(shù)據(jù),選用LCD顯示屏進(jìn)行數(shù)據(jù)的顯示。通過STM32的數(shù)字接口與LCD顯示屏進(jìn)行通信,將采集到的數(shù)據(jù)實時顯示在屏幕上。
2.2 軟件設(shè)計思路
本項目的代碼設(shè)計思路可以分為以下幾個關(guān)鍵部分:
【1】初始化設(shè)置:首先,需要進(jìn)行主控芯片的初始化設(shè)置,包括引腳配置、時鐘設(shè)置等。同時,還需要對LCD顯示屏進(jìn)行初始化配置,以便后續(xù)顯示數(shù)據(jù)。
【2】傳感器數(shù)據(jù)采集:使用合適的庫函數(shù)或代碼,讀取DHT11傳感器和土壤濕度傳感器的數(shù)據(jù)。通過適當(dāng)?shù)慕涌谂c主控芯片進(jìn)行通信,獲取溫度、濕度和土壤濕度的數(shù)值。
【3】數(shù)據(jù)處理與判斷:根據(jù)采集到的溫濕度和土壤濕度數(shù)值,進(jìn)行相應(yīng)的數(shù)據(jù)處理和判斷。判斷當(dāng)前溫度是否超出設(shè)定范圍,以及土壤濕度是否低于設(shè)定閾值等。
【4】控制執(zhí)行器:根據(jù)數(shù)據(jù)處理和判斷的結(jié)果,控制相應(yīng)的執(zhí)行器,如通風(fēng)風(fēng)扇、照明燈和灌溉系統(tǒng)。通過設(shè)置相應(yīng)的引腳電平或觸發(fā)繼電器,實現(xiàn)執(zhí)行器的開啟或關(guān)閉。
【5】LCD顯示:將采集到的溫濕度和土壤濕度數(shù)值通過LCD顯示屏進(jìn)行顯示,以便用戶實時監(jiān)測。
【6】用戶交互:通過按鍵輸入或其他方式,實現(xiàn)用戶與系統(tǒng)的交互。設(shè)置土壤濕度閾值、調(diào)節(jié)溫度范圍等。
【7】循環(huán)運(yùn)行:將上述步驟組織成一個循環(huán)運(yùn)行的程序,確保系統(tǒng)能夠持續(xù)采集數(shù)據(jù)、處理判斷和控制執(zhí)行器的操作。
三、代碼實現(xiàn)
3.1 DHT11溫濕度讀取
讀取DHT11傳感器環(huán)境溫濕度并通過串口打印出來。
#include "stm32f10x.h"
#include "stdio.h"
// 定義DHT11數(shù)據(jù)引腳
#define DHT11_PIN GPIO_Pin_0
#define DHT11_PORT GPIOA
// DHT11初始化函數(shù)
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);
}
// 延時函數(shù),單位為微秒
void Delay_us(uint32_t nCount)
{
uint32_t i;
for(i=0; i<nCount; i++);
}
// 軟件延時函數(shù),單位為毫秒
void Delay_ms(uint32_t nCount)
{
uint32_t i;
for(i=0; i<nCount*1000; i++);
}
// 從DHT11讀取一位數(shù)據(jù)
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; // 超時標(biāo)識
else
retries = 0;
while(GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == Bit_SET)
{
if (retries++ > 100) return 0;
Delay_us(1);
}
return 1;
}
// 從DHT11讀取一個字節(jié)數(shù)據(jù)
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;
// 主機(jī)將總線拉低至少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);
// 設(shè)置為輸入模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
// 等待 DHT11 響應(yīng)
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字節(jié)數(shù)據(jù)
for(uint8_t i=0; i<5; i++)
data[i] = DHT11_ReadByte();
// 讀取校驗和
checksum = DHT11_ReadByte();
// 校驗數(shù)據(jù)
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);
}
// 發(fā)送字符到USART1
void USART1_SendChar(char ch)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, (uint8_t)ch);
}
// 發(fā)送字符串到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))
{
// 發(fā)送溫濕度數(shù)據(jù)到串口
char buffer[50];
sprintf(buffer, "Temperature: %d°C, Humidity: %d%%rn", temperature, humidity);
USART1_SendString(buffer);
}
Delay_ms(2000); // 2秒鐘讀取一次數(shù)據(jù)
}
}
將代碼下載到STM32F103ZET6開發(fā)板上,接上DHT11。當(dāng)成功運(yùn)行時,環(huán)境溫濕度數(shù)據(jù)會通過USART1串口打印出來。
3.2 讀取土壤濕度值
通過ADC1的通道1采集土壤傳感器的濕度值,打印到串口.
#include "stm32f10x.h"
#include "stdio.h"
// 函數(shù)聲明
void ADC_Configuration(void);
void UART_Configuration(void);
void USART1_SendChar(char ch);
int main(void)
{
// 初始化ADC和串口
ADC_Configuration();
UART_Configuration();
while (1)
{
// 啟動ADC轉(zhuǎn)換
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
// 等待轉(zhuǎn)換完成
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
// 讀取ADC值
uint16_t adcValue = ADC_GetConversionValue(ADC1);
// 將ADC值轉(zhuǎn)換為濕度百分比
float humidity = (float)adcValue / 4095 * 100;
// 將濕度值打印到串口
char buffer[20];
sprintf(buffer, "Humidity: %.2f%%rn", humidity);
for (int i = 0; buffer[i] != '?'; i++)
{
USART1_SendChar(buffer[i]);
}
// 延時一段時間
for (int i = 0; i < 1000000; i++);
}
}
// ADC配置
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能ADC1和GPIOA時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置GPIOA.1為模擬輸入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// ADC配置
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
// 配置ADC1的通道1為采樣通道
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
// 使能ADC1
ADC_Cmd(ADC1, ENABLE);
// ADC校準(zhǔn)
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1));
}
// 串口配置
void UART_Configuration(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;
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;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// USART配置
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);
}
// 發(fā)送字符到USART1
void USART1_SendChar(char ch)
{
USART_SendData(USART1, (uint8_t)ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
以上代碼使用STM32的標(biāo)準(zhǔn)庫函數(shù)進(jìn)行配置和操作。在ADC_Configuration
函數(shù)中進(jìn)行ADC的初始化配置,包括GPIO引腳配置、ADC時鐘使能、通道配置等。
在UART_Configuration
函數(shù)中進(jìn)行串口USART1的初始化配置,包括GPIO引腳配置、波特率設(shè)置等。
在主函數(shù)中,進(jìn)入一個無限循環(huán)。在循環(huán)中,啟動ADC轉(zhuǎn)換,并等待轉(zhuǎn)換完成。
通過ADC_GetConversionValue
函數(shù)讀取ADC轉(zhuǎn)換結(jié)果,將其轉(zhuǎn)換為濕度百分比。
使用sprintf
函數(shù)將濕度值格式化為字符串,并使用USART1_SendChar
函數(shù)將字符串逐個字符發(fā)送到USART1串口。
通過延時函數(shù)進(jìn)行一段時間的延時,以控制打印速率。
3.3 大棚補(bǔ)光燈控制
以下是使用STM32F103ZET6讀取BH1750光照傳感器輸出的光照強(qiáng)度,并根據(jù)閾值控制LED補(bǔ)光燈燈開關(guān)實現(xiàn)代碼:
#include "stm32f10x.h"
#include "i2c.h"
#include "delay.h"
#define BH1750_ADDRESS 0x23
void BH1750_Init()
{
// 初始化I2C總線
I2C_Init();
}
void BH1750_Start()
{
// 啟動BH1750測量
uint8_t cmd = 0x01; // 單次高分辨率模式
I2C_Start();
I2C_SendByte(BH1750_ADDRESS);
I2C_WaitAck();
I2C_SendByte(cmd);
I2C_WaitAck();
I2C_Stop();
}
uint16_t BH1750_Read()
{
// 讀取BH1750測量結(jié)果
uint16_t lux;
I2C_Start();
I2C_SendByte(BH1750_ADDRESS + 1); // 發(fā)送讀命令
I2C_WaitAck();
lux = I2C_ReceiveByte() << 8; // 讀取高字節(jié)
I2C_Ack();
lux |= I2C_ReceiveByte(); // 讀取低字節(jié)
I2C_NAck();
I2C_Stop();
return lux;
}
void LED_Control(uint8_t state)
{
// 控制LED照明燈開關(guān)
if (state)
GPIO_SetBits(GPIOA, GPIO_Pin_8); // 打開LED
else
GPIO_ResetBits(GPIOA, GPIO_Pin_8); // 關(guān)閉LED
}
int main(void)
{
// 初始化GPIO口
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 初始化BH1750傳感器
BH1750_Init();
while (1)
{
// 啟動測量
BH1750_Start();
// 延時等待測量完成
DelayMs(200);
// 讀取光照強(qiáng)度
uint16_t lux = BH1750_Read();
// 判斷閾值并控制LED
if (lux > 1000)
LED_Control(1); // 光照強(qiáng)度高于閾值,打開LED
else
LED_Control(0); // 光照強(qiáng)度低于閾值,關(guān)閉LED
}
}
代碼中初始化I2C總線和BH1750傳感器,通過BH1750_Init()
函數(shù)實現(xiàn)。在主循環(huán)中,啟動測量延時等待測量完成。使用BH1750_Read()
函數(shù)讀取測量結(jié)果,即光照強(qiáng)度。根據(jù)閾值判斷光照強(qiáng)度是否高于設(shè)定值,通過LED_Control()
函數(shù)控制LED的開關(guān)狀態(tài)。
四、總結(jié)
本項目基于STM32微控制器實現(xiàn)了一個蔬菜大棚溫濕度智能控制系統(tǒng)。系統(tǒng)的主控芯片采用了STM32F103ZET6,用于控制和協(xié)調(diào)各個硬件模塊的工作。系統(tǒng)包括空氣溫濕度采集模塊(DHT11)、土壤濕度采集模塊(ADC接口)、通風(fēng)風(fēng)機(jī)(5V小風(fēng)扇+繼電器控制)、照明燈(LED白色燈模塊)、灌溉系統(tǒng)(抽水電機(jī)+繼電器控制)以及LCD顯示屏。
系統(tǒng)的功能包括溫濕度的實時監(jiān)測、土壤濕度的檢測、通風(fēng)風(fēng)扇的自動控制、灌溉系統(tǒng)的自動控制和數(shù)據(jù)的顯示。通過按鍵設(shè)置土壤濕度閾值,實現(xiàn)自動澆水功能,當(dāng)土壤濕度低于閾值時,系統(tǒng)自動開啟灌溉系統(tǒng)進(jìn)行澆水。同時,根據(jù)設(shè)定的溫度閾值,系統(tǒng)自動控制通風(fēng)風(fēng)扇進(jìn)行降溫。
蔬菜大棚溫濕度智能控制系統(tǒng)利用STM32微控制器和各種傳感器實現(xiàn)了對環(huán)境參數(shù)的監(jiān)測和控制,提高了蔬菜大棚的自動化程度和生產(chǎn)效率。同時,通過自動控制灌溉和通風(fēng)系統(tǒng),能夠更好地滿足蔬菜生長的需求,提高農(nóng)作物的產(chǎn)量和質(zhì)量。