• 方案介紹
    • 一、項目背景
    • 二、硬件選型
    • 三、設計思路
    • 四、代碼設計
  • 附件下載
  • 相關推薦
申請入駐 產(chǎn)業(yè)圖譜

基于STM32的智能糧倉系統(tǒng)設計

03/19 09:14
1826
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

更多詳細資料請聯(lián)系.docx

共1個文件

一、項目背景

隨著糧食質(zhì)量要求的提高和儲存方式的改變,對于糧倉環(huán)境的監(jiān)測和控制也愈發(fā)重要。在過去的傳統(tǒng)管理中,通風、防潮等操作需要定期人工進行,精度和效率都較低。而利用嵌入式技術和智能控制算法進行監(jiān)測和控制,不僅能夠?qū)崟r掌握環(huán)境變化,還可以快速做出響應。

本項目選擇STM32F103RCT6作為主控芯片,采用DHT11溫濕度傳感器和MQ9可燃氣體檢測模塊進行數(shù)據(jù)采集,在本地利用顯示屏實時顯示出來。WiFi模塊則用于與手機端實現(xiàn)數(shù)據(jù)通信遠程控制,方便用戶隨時了解糧倉環(huán)境狀況并進行相應的操作。同時,通過連接繼電器控制通風風扇和蜂鳴器報警,實現(xiàn)了智能化的溫濕度檢測和可燃氣體濃度檢測。

image-20230530221719977

image-20230530221802623

二、硬件選型

【1】主控芯片:STM32F103RCT6,這款芯片具有較高性能、低功耗等特點。

【2】溫濕度傳感器:DHT11,DHT11是一種數(shù)字溫濕度傳感器,價格便宜。

【3】可燃氣體檢測模塊:MQ9模塊,MQ9模塊對多種可燃氣體具有敏感性,可以精確檢測可燃氣體濃度。

【4】通風風扇:選擇直流電機作為通風風扇,使用繼電器進行控制。

【5】WiFi模塊:ESP8266,ESP8266是一種低成本的高性能WiFi模塊,支持TCP/UDP協(xié)議。

【6】顯示屏:采用7針引腳OLED顯示屏,SPI接口,分辨率128x64,用于顯示當前溫度、濕度、可燃氣體濃度。

三、設計思路

【1】硬件層

通過STM32F103RCT6控制DHT11和MQ9等模塊進行數(shù)據(jù)采集。在采集到溫濕度和可燃氣體濃度數(shù)據(jù)之后,對其進行處理,并判斷是否超過了設定的閾值范圍。如果超過了閾值,就控制繼電器打開風扇,并通過蜂鳴器聲音報警。

ESP8266 WiFi模塊用于與手機端進行通信。ESP8266被配置成AP+TCP服務器模式,通過向服務器發(fā)送指令,實現(xiàn)遠程控制風扇及設置相應閾值等操作,并能實時接收糧倉環(huán)境狀況信息。

【2】軟件層

STM32的控制程序使用C語言編寫,采用keil軟件進行整體項目開發(fā),對外設進行控制并實現(xiàn)數(shù)據(jù)采集和智能控制。主要分為采集數(shù)據(jù)、處理數(shù)據(jù)、數(shù)據(jù)顯示、控制繼電器和蜂鳴器等功能模塊。

手機APP采用Qt框架開發(fā),實現(xiàn)對應數(shù)據(jù)界面顯示和邏輯操作,能夠?qū)崟r顯示和控制糧倉內(nèi)部的溫濕度和可燃氣體濃度,并能夠?qū)︼L扇進行控制。同時,APP界面提供了設置選項,允許用戶設置報警閾值參數(shù)。

四、代碼設計

【1】DHT11采集溫濕度

DHT11是一種數(shù)字溫濕度傳感器,能夠通過單總線接口輸出當前環(huán)境下的溫度和相對濕度。它由測量模塊及處理電路組成,具有體積小、成本低、響應時間快等特點,被廣泛應用于各種環(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 %%rn", 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);
  }
}

s上面代碼里,使用了DHT11讀取函數(shù)DHT11_Read_Data(),該函數(shù)返回溫度值和濕度值,并將其轉換為字符串形式。通過串口與電腦連接后,可以使用串口調(diào)試軟件來查看STM32采集到的溫濕度數(shù)據(jù)。

【2】采集MQ9有毒氣氣體

MQ9是一種可燃氣體傳感器,可以檢測空氣中的多種可燃氣體,例如甲烷、丙烷、丁烷等。它的工作原理是通過加熱敏感元件,使其產(chǎn)生一個電阻變化,從而實現(xiàn)檢測目標氣體的濃度。MQ9具有高靈敏度、快速響應和穩(wěn)定性好等特點,廣泛應用于火災報警、室內(nèi)空氣質(zhì)量監(jiān)測、工業(yè)生產(chǎn)等領域。需要注意的是,MQ9只能檢測可燃氣體,不能檢測其他氣體,如二氧化碳、氧氣等。

下面代碼是通過STM32F103RCT6采集MQ9可燃氣體轉為濃度通過串口打印(使用HAL庫):

#include "main.h"

UART_HandleTypeDef huart1;
ADC_HandleTypeDef hadc1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_ADC1_Init(void);

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();

  uint16_t adc_value;
  float voltage;
  float concentration;
  char buffer[20];

  while (1)
  {
    HAL_ADC_Start(&hadc1); // 啟動ADC轉換
    if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) // 等待轉換完成
    {
      adc_value = HAL_ADC_GetValue(&hadc1); // 獲取原始ADC值
      voltage = (float)adc_value * 3.3f / 4096.0f; // 轉換為電壓值
      concentration = (float)(2.5f - voltage) / 0.2f; // 根據(jù)MQ9傳感器曲線計算濃度值
      sprintf(buffer, "Concentration: %.2f %%rn", concentration); // 將濃度值轉換為字符串
      printf("%s", buffer); // 通過串口打印濃度值
    }
    HAL_ADC_Stop(&hadc1); // 停止ADC轉換
    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_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig;

  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_55CYCLES5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != 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);
  }
}

上面代碼里,通過ADC采集MQ9可燃氣體濃度。由于MQ9傳感器的輸出信號與濃度值之間不是線性關系,需要根據(jù)其曲線進行計算,將電壓轉換為濃度值。

在這里,采用了簡單的公式:Concentration=(2.5?V)/0.2

其中V為MQ9傳感器輸出的電壓值,Concentration為可燃氣體濃度。在主函數(shù)里,先調(diào)用MX_ADC1_Init()函數(shù)中初始化ADC,將輸入通道設置為PA5(也就是ADC_CHANNEL_5)。

  • 更多詳細資料請聯(lián)系.docx
    下載
意法半導體

意法半導體

意法半導體(ST)集團于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導體有限公司。意法半導體是世界最大的半導體公司之一,公司銷售收入在半導體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(17%),計算機(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計數(shù)據(jù),意法半導體是全球第五大半導體廠商,在很多市場居世界領先水平。例如,意法半導體是世界第一大專用模擬芯片和電源轉換芯片制造商,世界第一大工業(yè)半導體和機頂盒芯片供應商,而且在分立器件、手機相機模塊和車用集成電路領域居世界前列.

意法半導體(ST)集團于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導體有限公司。意法半導體是世界最大的半導體公司之一,公司銷售收入在半導體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(17%),計算機(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計數(shù)據(jù),意法半導體是全球第五大半導體廠商,在很多市場居世界領先水平。例如,意法半導體是世界第一大專用模擬芯片和電源轉換芯片制造商,世界第一大工業(yè)半導體和機頂盒芯片供應商,而且在分立器件、手機相機模塊和車用集成電路領域居世界前列.收起

查看更多

相關推薦