一、項目背景
當前文章介紹基于STM32單片機的智能溫室大棚監控系統,當前系統由溫濕度傳感器、二氧化碳傳感器、光敏電阻傳感器、土壤濕度傳感器笨時溫宏大棚中內作物生長環境因子主要包括溫度、濕度、光度、土壤濕度傳感、二氧化碳濃度等參數進行監控。
采集數據,判斷是否在系統設定上限、下限范圍,如果超出了上限下限蜂鳴器報警、通風系統、LED補光系統、水泵系統就會啟也可以通過手機APP和華為云華為云物聯網云平臺對溫室大棚中的數據進行修改和設定新的數據。
本設計整體主要采用STM32單片機為核心、溫濕度傳感器、二氧化碳傳感器、光敏電阻傳感器、土壤濕度傳感器、通風系統、LED補光系統、水泵系統組成。
(1) 溫濕度傳感器: 主要對溫室大棚中農作物環境進行溫濕度監控,把數據傳到控制系統,由控制系統傳到OLED顯示屏上顯示出來。
(2) 二氧化碳傳感器: 工作過程對溫室大棚中的農作物環境二氧化碳濃度進行監控采集數據,把數據傳到控制系統后,再把控制系統中的當前環境數據傳顯示屏上顯示出來。
(3) 光敏電阻傳感器: 工作過程主要通過對溫室大棚中的農作物環境光照強度進行監控采集數據,把數據傳到控制系統后,再從控制系統的數據傳到顯示屏上顯示。
(4) 土壤濕度傳感器: 工作過程對溫室大棚中的農作物生長環境的土壤濕度進行監控采集數據,把數據傳到控制系統中,再從控制系統中的數據傳到顯示屏上顯示出來。
(5) OLED顯示屏: 主要用來對二氧化碳、溫濕度、光照強度以及土壤濕度傳感器中的數據顯示出來。
(6) 蜂鳴器模塊: 主要對二氧化碳濃度、溫濕度、土壤濕度、光照強度等傳感器的采集數據是否高過或低于上限、下限值時蜂鳴器報警等功能,并提醒用戶。
(7) 繼電器模塊: 主要通過把溫濕度、土壤濕度傳感器中的溫濕度過高時或過低時,把溫濕度轉換成電信號,使通風、水泵啟動等功能。
(8) 通風系統: 當溫室大棚中環境溫度過高時,通風系統啟動對室內進行通風,使溫度降下到設定值內通風系統關閉停止工作。
(9) 水泵系統: 當土壤濕度傳感器檢測土壤濕度低于下限值時,水泵系統開啟進行澆水灌溉,當土壤濕度到達土壤濕度傳感器上下限內,水泵系統關閉停止工作。
(10) LED補光系統: 通過光敏電阻傳感器檢測溫室大棚中環境光照強度低于下限值時,LED補光系統開啟對農作物進行補光,當光敏電阻傳感器檢測達到上下限內LED補光系統關閉停止補光。
(11) 按鍵模塊: 主要用來調采集數據模塊的上、下限值,可以通過按鍵切換手動和自動和云端三種模式,手動按鍵控制通風系統、LED補光系統、水泵系統打開和關閉功能。
(12) WIFI模塊: 通過控制系統數據處理之后傳輸給外網,手機APP主要用來接收傳來的數據顯示出來
(13). 上機模塊: 監控各個傳感器的采集數據工作情況,執行硬件工作狀態,也可以通過手機和華為云物聯網云平臺切換手動以及自動控制模式,對各傳感器的設置上下限值。
二、硬件設計
【1】硬件設計
本系統硬件設計包括控制模塊、傳感器模塊和執行模塊三部分。
控制模塊: 該模塊使用STM32F103C8T6單片機作為主控制器,負責處理各個傳感器的數據和控制執行模塊。此外,控制模塊還需要與各個執行模塊和外部設備進行通信,以實現數據的處理和傳輸。
傳感器模塊: 傳感器模塊包括溫濕度傳感器、二氧化碳傳感器、光敏電阻傳感器和土壤濕度傳感器,主要負責感應和采集生長環境的溫濕度、二氧化碳濃度、光照強度和土壤濕度等參數,并將數據傳輸給控制模塊處理。
執行模塊: 執行模塊包括通風系統、LED補光系統、水泵系統等,用于根據傳感器采集到的數據直接或間接地調節生長環境因子,并保證生長環境達到穩定的狀態。
【2】軟件設計
軟件設計主要分為以下四個模塊:傳感器數據采集模塊、數據處理模塊、控制模塊和遠程控制模塊。
傳感器數據采集模塊: 該模塊負責對傳感器數據進行采集,包括溫濕度傳感器、二氧化碳傳感器、光敏電阻傳感器和土壤濕度傳感器。采集到的數據通過串口接口發送給控制模塊。
數據處理模塊: 該模塊負責對采集到的傳感器數據進行處理,判斷當前環境因子是否超出設定范圍,如果超出,則觸發報警和控制執行模塊的操作。同時,該模塊還要將處理后的數據發送給控制模塊進行控制操作。
控制模塊: 該模塊負責控制執行模塊,根據數據處理模塊的指令,啟動通風系統、LED補光系統、水泵系統等設備,以保證生長環境穩定和水平。
遠程控制模塊: 該模塊實現通過手機APP和華為云IOT平臺遠程管理系統,對溫室大棚中的數據進行修改和設定新的數據。用戶可以通過手機APP或者華為云IOT平臺,實時查看和修改溫室大棚的環境因子,實現遠程控制和管理。
三、華為云IOT平臺開發
在華為云IOT平臺上,需要進行設備接入、數據模型定義、規則引擎配置和應用開發等四個核心模塊的開發。其中,設備接入模塊包括設備注冊、獲取設備證書、建立連接等步驟,以保障設備與云平臺之間的安全通信;數據模型定義模塊需要根據實際需求定義相應的數據模型,包括上傳數據格式、設備屬性和服務等。規則引擎配置模塊需要完成實時消息推送、遠程控制和告警等功能。應用開發模塊則是將完整的智能井蓋系統進行打包,為用戶提供統一的操作接口。
華為云官網: https://www.huaweicloud.com/
打開官網,搜索物聯網,就能快速找到 設備接入IoTDA
。
3.1 物聯網平臺介紹
華為云物聯網平臺(IoT 設備接入云服務)提供海量設備的接入和管理能力,將物理設備聯接到云,支撐設備數據采集上云和云端下發命令給設備進行遠程控制,配合華為云其他產品,幫助我們快速構筑物聯網解決方案。
使用物聯網平臺構建一個完整的物聯網解決方案主要包括3部分:物聯網平臺、業務應用和設備。
物聯網平臺作為連接業務應用和設備的中間層,屏蔽了各種復雜的設備接口,實現設備的快速接入;同時提供強大的開放能力,支撐行業用戶構建各種物聯網解決方案。
設備可以通過固網、2G/3G/4G/5G、NB-IoT、Wifi等多種網絡接入物聯網平臺,并使用LWM2M/CoAP、MQTT、HTTPS協議將業務數據上報到平臺,平臺也可以將控制命令下發給設備。
業務應用通過調用物聯網平臺提供的API,實現設備數據采集、命令下發、設備管理等業務場景。
3.2 開通物聯網服務
地址: https://www.huaweicloud.com/product/iothub.html
開通標準版免費單元。
開通之后,點擊總覽
,查看接入信息。 我們當前設備準備采用MQTT協議接入華為云平臺,這里可以看到MQTT協議的地址和端口號等信息。
總結:
端口號: MQTT (1883)| MQTTS (8883)
接入地址: a3433ab133.iot-mqtts.cn-north-4.myhuaweicloud.com
根據域名地址得到IP地址信息:
Microsoft Windows [版本 10.0.19044.2846]
(c) Microsoft Corporation。保留所有權利。
?
C:Users11266>ping a3433ab133.iot-mqtts.cn-north-4.myhuaweicloud.com
?
正在 Ping a3433ab133.iot-mqtts.cn-north-4.myhuaweicloud.com [121.36.42.100] 具有 32 字節的數據:
來自 121.36.42.100 的回復: 字節=32 時間=37ms TTL=31
來自 121.36.42.100 的回復: 字節=32 時間=37ms TTL=31
來自 121.36.42.100 的回復: 字節=32 時間=36ms TTL=31
來自 121.36.42.100 的回復: 字節=32 時間=37ms TTL=31
?
121.36.42.100 的 Ping 統計信息:
數據包: 已發送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計時間(以毫秒為單位):
最短 = 36ms,最長 = 37ms,平均 = 36ms
?
C:Users11266>
MQTT協議接入端口號有兩個,1883是非加密端口,8883是證書加密端口,單片機無法加載證書,所以使用1883端口比較合適。 接下來的ESP8266就采用1883端口連接華為云物聯網平臺。
3.3 創建產品
(1)創建產品
點擊右上角創建產品。
(2)填寫產品信息
根據自己產品名字填寫,設備類型選擇自定義類型。
(3)添加自定義模型
產品創建完成之后,點擊進入產品詳情頁面,翻到最下面可以看到模型定義。
模型簡單來說: 就是存放設備上傳到云平臺的數據。比如:環境溫度、環境濕度、環境煙霧濃度、火焰檢測狀態圖等等,這些我們都可以單獨創建一個模型保存。
3.4 添加設備
產品是屬于上層的抽象模型,接下來在產品模型下添加實際的設備。添加的設備最終需要與真實的設備關聯在一起,完成數據交互。
(1)注冊設備
點擊右上角注冊設備。
(2)根據自己的設備填寫
在彈出的對話框里填寫自己設備的信息。根據自己設備詳細情況填寫。
(3)保存設備信息
創建完畢之后,點擊保存并關閉,得到創建的設備密匙信息。該信息在后續生成MQTT三元組的時候需要使用。
3.5 MQTT協議主題訂閱與發布
(1)MQTT協議介紹
當前的設備是采用MQTT協議與華為云平臺進行通信。
MQTT是一個物聯網傳輸協議,它被設計用于輕量級的發布/訂閱式消息傳輸,旨在為低帶寬和不穩定的網絡環境中的物聯網設備提供可靠的網絡服務。MQTT是專門針對物聯網開發的輕量級傳輸協議。MQTT協議針對低帶寬網絡,低計算能力的設備,做了特殊的優化,使得其能適應各種物聯網應用場景。目前MQTT擁有各種平臺和設備上的客戶端,已經形成了初步的生態系統。
MQTT是一種消息隊列協議,使用發布/訂閱消息模式,提供一對多的消息發布,解除應用程序耦合,相對于其他協議,開發更簡單;MQTT協議是工作在TCP/IP協議上;由TCP/IP協議提供穩定的網絡連接;所以,只要具備TCP協議棧的網絡設備都可以使用MQTT協議。 本次設備采用的ESP8266就具備TCP協議棧,能夠建立TCP連接,所以,配合STM32代碼里封裝的MQTT協議,就可以與華為云平臺完成通信。
華為云的MQTT協議接入幫助文檔在這里: https://support.huaweicloud.com/devg-iothub/iot_02_2200.html
業務流程:
(2)華為云平臺MQTT協議使用限制
描述 | 限制 |
---|---|
支持的MQTT協議版本 | 3.1.1 |
與標準MQTT協議的區別 | 支持Qos 0和Qos 1支持Topic自定義不支持QoS2不支持will、retain msg |
MQTTS支持的安全等級 | 采用TCP通道基礎 + TLS協議(最高TLSv1.3版本) |
單帳號每秒最大MQTT連接請求數 | 無限制 |
單個設備每分鐘支持的最大MQTT連接數 | 1 |
單個MQTT連接每秒的吞吐量,即帶寬,包含直連設備和網關 | 3KB/s |
MQTT單個發布消息最大長度,超過此大小的發布請求將被直接拒絕 | 1MB |
MQTT連接心跳時間建議值 | 心跳時間限定為30至1200秒,推薦設置為120秒 |
產品是否支持自定義Topic | 支持 |
消息發布與訂閱 | 設備只能對自己的Topic進行消息發布與訂閱 |
每個訂閱請求的最大訂閱數 | 無限制 |
(3)主題訂閱格式
幫助文檔地址:https://support.huaweicloud.com/devg-iothub/iot_02_2200.html
對于設備而言,一般會訂閱平臺下發消息給設備 這個主題。
設備想接收平臺下發的消息,就需要訂閱平臺下發消息給設備 的主題,訂閱后,平臺下發消息給設備,設備就會收到消息。
(4)主題發布格式
對于設備來說,主題發布表示向云平臺上傳數據,將最新的傳感器數據,設備狀態上傳到云平臺。
這個操作稱為:屬性上報。
幫助文檔地址:https://support.huaweicloud.com/usermanual-iothub/iot_06_v5_3010.html
3.6 MQTT三元組
MQTT協議登錄需要填用戶ID,設備ID,設備密碼等信息,就像我們平時登錄QQ,微信一樣要輸入賬號密碼才能登錄。MQTT協議登錄的這3個參數,一般稱為MQTT三元組。
接下來介紹,華為云平臺的MQTT三元組參數如何得到。
(1)MQTT服務器地址
要登錄MQTT服務器,首先記得先知道服務器的地址是多少,端口是多少。
幫助文檔地址:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-portal/home
MQTT協議的端口支持1883和8883,它們的區別是:8883 是加密端口更加安全。但是單片機上使用比較困難,所以當前的設備是采用1883端口進連接的。
根據上面的域名和端口號,得到下面的IP地址和端口號信息: 如果設備支持填寫域名可以直接填域名,不支持就直接填寫IP地址。 (IP地址就是域名解析得到的)
華為云的MQTT服務器地址:121.36.42.100
華為云的MQTT端口號:1883
(2)生成MQTT三元組
華為云提供了一個在線工具,用來生成MQTT鑒權三元組: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
打開這個工具,填入設備的信息(也就是剛才創建完設備之后保存的信息),點擊生成,就可以得到MQTT的登錄信息了。
下面是打開的頁面:
3.7 參考案例
華為云平臺部署開發也可以參考這里:
https://bbs.huaweicloud.com/blogs/381072
【基于華為云IOT平臺實現多節點溫度采集(STM32+NBIOT)】
四、設計代碼
【1】DHT11溫濕度數據讀取
以下是基于HAL庫的STM32F103ZET6讀取DHT11溫濕度傳感器的代碼:
#include "dht11.h"
?
#define DHT11_GPIO_PORT GPIOA
#define DHT11_GPIO_PIN GPIO_PIN_0
?
/* DHT11引腳初始化 */
void DHT11_Init()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
?
/* 打開GPIO時鐘 */
__HAL_RCC_GPIOA_CLK_ENABLE();
?
/* 配置GPIO為推挽輸出模式 */
GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
}
?
/* 從DHT11讀取一次溫濕度數據 */
DHT11_Result_t DHT11_Read_Data()
{
uint8_t data[5] = {0};
uint8_t check = 0;
uint8_t i = 0;
?
/* 向DHT11發送起始信號 */
HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_RESET);
HAL_Delay(20);
HAL_GPIO_WritePin(DHT11_GPIO_PORT, DHT11_GPIO_PIN, GPIO_PIN_SET);
HAL_Delay(30);
?
/* 切換到輸入模式等待DHT11的響應 */
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DHT11_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
?
/* 等待DHT11響應 */
while (HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == GPIO_PIN_SET);
?
/* 等待DHT11發送完畢 */
while (HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == GPIO_PIN_RESET);
?
/* 讀取DHT11發送的數據 */
for (i = 0; i < 5; i++) {
? ? ? ? uint8_t j = 0;
? ? ? ? for (j = 0; j < 8; j++) {
? ? ? ? ? ? /* 等待低電平結束 */
? ? ? ? ? ? while (HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == GPIO_PIN_RESET);
??
? ? ? ? ? ? /* 等待高電平結束,并記錄時間 */
? ? ? ? ? ? uint32_t t = 0;
? ? ? ? ? ? while (HAL_GPIO_ReadPin(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == GPIO_PIN_SET) {
? ? ? ? ? ? ? ? t++;
? ? ? ? ? ? ? ? if (t > 100) break;
}
?
/* 根據時間計算數據位的值 */
data[i] <<= 1;
? ? ? ? ? ? if (t >= 50) {
data[i] |= 0x01;
}
}
}
?
/* 切換回輸出模式 */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
HAL_GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStruct);
?
/* 驗證數據的正確性 */
check = data[0] + data[1] + data[2] + data[3];
if (check != data[4]) {
return DHT11_ERROR_CHECKSUM;
}
?
/* 讀取溫濕度數據結果 */
DHT11_Result_t result;
result.humidity = data[0];
result.temperature = data[2];
return result;
}
該代碼基于HAL庫的STM32F103ZET6讀取DHT11溫濕度傳感器的代碼示例:
/* 獲取溫濕度數據 */
void get_temperature_humidity()
{
DHT11_Result_t res = DHT11_Read_Data();
if (res != DHT11_ERROR_CHECKSUM)
{
float humidity = res.humidity;
float temperature = res.temperature;
printf("溫度:%.1f°C 濕度:%.1f%%RHrn", temperature, humidity);
}
else
{
printf("讀取失敗,請檢查連接和傳感器是否正常!rn");
}
}
?
int main()
{
HAL_Init();
?
// 初始化串口輸出
uart_init();
?
printf("DHT11溫濕度傳感器讀取測試開始rn");
?
// 初始化DHT11引腳
DHT11_Init();
?
while (1)
{
// 讀取溫濕度傳感器數據
get_temperature_humidity();
HAL_Delay(2000);
}
}
需要注意的是,在主函數中,我們先初始化了串口輸出和DHT11引腳,然后通過循環一直讀取溫濕度數據并打印輸出。其中,get_temperature_humidity()函數負責調用DHT11_Read_Data()函數讀取溫濕度數據,并將結果打印出來。如果讀取失敗,get_temperature_humidity()函數也會將錯誤信息打印出來。
【2】讀取BH1750光敏傳感器的值
以下是基于HAL庫的STM32F103ZET6讀取BH1750光照強度傳感器的代碼:
#include "bh1750.h"
?
/* BH1750地址 */
#define BH1750_ADDR 0x23
?
/* BH1750命令 */
#define BH1750_CMD_POWER_ON 0x01
#define BH1750_CMD_POWER_DOWN 0x00
#define BH1750_CMD_RESET 0x07
#define BH1750_CMD_ONE_TIME_H 0x20
#define BH1750_CMD_ONE_TIME_L 0x23
?
/* BH1750初始化配置 */
void BH1750_Init()
{
I2C_HandleTypeDef hi2c1 = {0};
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 200000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&hi2c1);
?
uint8_t init_data = BH1750_CMD_POWER_ON;
HAL_I2C_Master_Transmit(&hi2c1, BH1750_ADDR, &init_data, 1, HAL_MAX_DELAY);
}
?
/* 從BH1750讀取光照強度數據 */
float BH1750_Read_Lux()
{
I2C_HandleTypeDef hi2c1 = {0};
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 200000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
HAL_I2C_Init(&hi2c1);
?
/* 發送手動讀取命令 */
uint8_t cmd_data = BH1750_CMD_ONE_TIME_H;
HAL_I2C_Master_Transmit(&hi2c1, BH1750_ADDR, &cmd_data, 1, HAL_MAX_DELAY);
?
/* 等待讀取完成 */
HAL_Delay(180);
?
/* 讀取數據 */
uint8_t buf[2];
HAL_I2C_Master_Receive(&hi2c1, BH1750_ADDR, buf, 2, HAL_MAX_DELAY);
?
/* 計算光照強度 */
uint16_t val = (buf[0] << 8) | buf[1];
? ? float lux = val / 1.2;
? ? return lux;
?}
該代碼首先在BH1750_Init()函數中初始化了I2C相關的參數,并使用HAL_I2C_Master_Transmit()函數向BH1750發送了開啟電源的命令。在BH1750_Read_Lux()函數中,我們首先發送手動讀取命令,等待數據準備完成后,使用 HAL_I2C_Master_Receive() 函數讀取BH1750返回的2字節數據。隨后通過計算獲得光照強度值。
使用時,只需要在主函數中調用BH1750_Init()函數初始化I2C參數和發送開啟電源命令,然后在需要讀取光照強度數據時調用BH1750_Read_Lux()函數即可,如下所示:
int main(void)
{
HAL_Init();
?
/* 初始化BH1750 */
BH1750_Init();
?
/* 讀取BH1750光照強度 */
float lux = BH1750_Read_Lux();
printf("光照強度:%.1f Luxrn", lux);
?
while (1)
{
/* 主程序循環,可以進行其他操作或等待 */
}
}
五、總結
當前設計實現了一款基于STM32單片機的智能溫室大棚監控系統,該系統通過多種傳感器實現環境因子的實時監測和數據上傳,在應用上具有重要的作用和應用價值。整體介紹了系統硬件和軟件設計的各個環節,提供了一定的參考價值和設計思路。同時,該系統還可以在未來加入更多的傳感器和控制設備,提升溫室大棚監控系統的智能化和自動化程度。
審核編輯:湯梓紅
-
傳感器
+關注
關注
2548文章
50668瀏覽量
751981 -
物聯網
+關注
關注
2903文章
44269瀏覽量
371233 -
STM32
+關注
關注
2266文章
10871瀏覽量
354796 -
IOT
+關注
關注
186文章
4177瀏覽量
196220 -
華為云
+關注
關注
3文章
2423瀏覽量
17311
發布評論請先 登錄
相關推薦
評論