一、項目背景
隨著糧食質(zhì)量要求的提高和儲存方式的改變,對于糧倉環(huán)境的監(jiān)測和控制也愈發(fā)重要。在過去的傳統(tǒng)管理中,通風(fēng)、防潮等操作需要定期人工進(jìn)行,精度和效率都較低。而利用嵌入式技術(shù)和智能控制算法進(jìn)行監(jiān)測和控制,不僅能夠?qū)崟r掌握環(huán)境變化,還可以快速做出響應(yīng)。
本項目選擇STM32F103RCT6作為主控芯片,采用DHT11溫濕度傳感器和MQ9可燃?xì)怏w檢測模塊進(jìn)行數(shù)據(jù)采集,在本地利用顯示屏實時顯示出來。WiFi模塊則用于與手機(jī)端實現(xiàn)數(shù)據(jù)通信和遠(yuǎn)程控制,方便用戶隨時了解糧倉環(huán)境狀況并進(jìn)行相應(yīng)的操作。同時,通過連接繼電器控制通風(fēng)風(fēng)扇和蜂鳴器報警,實現(xiàn)了智能化的溫濕度檢測和可燃?xì)怏w濃度檢測。
二、硬件選型
【1】主控芯片:STM32F103RCT6,這款芯片具有較高性能、低功耗等特點。
【2】溫濕度傳感器:DHT11,DHT11是一種數(shù)字溫濕度傳感器,價格便宜。
【3】可燃?xì)怏w檢測模塊:MQ9模塊,MQ9模塊對多種可燃?xì)怏w具有敏感性,可以精確檢測可燃?xì)怏w濃度。
【4】通風(fēng)風(fēng)扇:選擇直流電機(jī)作為通風(fēng)風(fēng)扇,使用繼電器進(jìn)行控制。
【5】WiFi模塊:ESP8266,ESP8266是一種低成本的高性能WiFi模塊,支持TCP/UDP協(xié)議。
【6】顯示屏:采用7針引腳的OLED顯示屏,SPI接口,分辨率128x64,用于顯示當(dāng)前溫度、濕度、可燃?xì)怏w濃度。
三、設(shè)計思路
【1】硬件層
通過STM32F103RCT6控制DHT11和MQ9等模塊進(jìn)行數(shù)據(jù)采集。在采集到溫濕度和可燃?xì)怏w濃度數(shù)據(jù)之后,對其進(jìn)行處理,并判斷是否超過了設(shè)定的閾值范圍。如果超過了閾值,就控制繼電器打開風(fēng)扇,并通過蜂鳴器聲音報警。
ESP8266 WiFi模塊用于與手機(jī)端進(jìn)行通信。ESP8266被配置成AP+TCP服務(wù)器模式,通過向服務(wù)器發(fā)送指令,實現(xiàn)遠(yuǎn)程控制風(fēng)扇及設(shè)置相應(yīng)閾值等操作,并能實時接收糧倉環(huán)境狀況信息。
【2】軟件層
STM32的控制程序使用C語言編寫,采用keil軟件進(jìn)行整體項目開發(fā),對外設(shè)進(jìn)行控制并實現(xiàn)數(shù)據(jù)采集和智能控制。主要分為采集數(shù)據(jù)、處理數(shù)據(jù)、數(shù)據(jù)顯示、控制繼電器和蜂鳴器等功能模塊。
手機(jī)APP采用Qt框架開發(fā),實現(xiàn)對應(yīng)數(shù)據(jù)界面顯示和邏輯操作,能夠?qū)崟r顯示和控制糧倉內(nèi)部的溫濕度和可燃?xì)怏w濃度,并能夠?qū)︼L(fēng)扇進(jìn)行控制。同時,APP界面提供了設(shè)置選項,允許用戶設(shè)置報警閾值參數(shù)。
四、代碼設(shè)計
【1】DHT11采集溫濕度
DHT11是一種數(shù)字溫濕度傳感器,能夠通過單總線接口輸出當(dāng)前環(huán)境下的溫度和相對濕度。它由測量模塊及處理電路組成,具有體積小、成本低、響應(yīng)時間快等特點,被廣泛應(yīng)用于各種環(huán)境監(jiān)測和自動控制系統(tǒng)中。
下面代碼是通過STM32F103RCT6采集DHT11溫濕度數(shù)據(jù)通過串口打印輸出(使用HAL庫):
#include "main.h"
#include "dht11.h"
?
UART_HandleTypeDef huart1;
?
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
?
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
?
char temp[20];
char humi[20];
while (1)
{
DHT11_Read_Data(temp, humi); // 讀取DHT11數(shù)據(jù)
printf("Temperature: %s C, Humidity: %s %%
", temp, humi); // 打印溫濕度數(shù)據(jù)
HAL_Delay(2000); // 延時2秒
}
}
?
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
?
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
?
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
?
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
?
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
?
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
?
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
?
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
?
void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if (uartHandle- >Instance == USART1)
{
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
?
/**USART1 GPIO Configuration
PA9 ------ > USART1_TX
PA10 ------ > USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
}
?
void HAL_UART_MspDeInit(UART_HandleTypeDef *uartHandle)
{
if (uartHandle- >Instance == USART1)
{
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
?
/**USART1 GPIO Configuration
PA9 ------ > USART1_TX
PA10 ------ > USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);
}
}