硬件環境:
(1)開發板:ST官方的stm32wb55-st-nucleo開發板
(2)wifi模塊:esp8266
(3)溫濕度傳感器:DHT22
(4)單色oled屏:主控ssd1306,分辨率126x64
軟件環境:
(1)開發環境:Keil MDK v5.29
(2)RTOS:RT-Thread 4.0.3
實現目標:將溫度、濕度數據上報到華為雲物聯網平台。
一、准備工作
(1)安裝ENV工具,參見官方文檔《Env 用戶手冊》:
https://www.rt-thread.org/document/site/#
(2)安裝git下載最新的rt-thread源碼,可到github或碼雲gitee上下載:
git clone https://gitee.com/rtthread/rt-thread.git
(3)查看rt-thread源碼的bsp文件夾內已經適配了stm32wb55-st-nucleo開發板,進入“...\rt-thread\bsp\stm32\stm32wb55-st-nucleo”,打開env運行scons --dist將工程抽離成獨立工程(看個人習慣,喜歡一個項目一個工程文件夾就抽離一下)。
(4)先對工程文件進行編譯,看看有沒有錯誤,理論上官方默認狀態是無錯誤的。打開env再運行:
pkgs --upgrade
pkgs --update
scons --target=mdk5
然后用keil打開工程,編譯0錯誤,0警告。准備工作完成。
二、獲取需要的軟件包
rt-thread提供非常多的軟件包,主要任務就是怎么把軟件包利用起來。本次操作需要的軟件包:DHT22驅動、ESP8266驅動、MQTT軟件包、json軟件包,另外把oled屏驅動添加到工程。
1. 添加DHT22驅動
(1)DHT22與開發板連接,電源、地、數據就三根線,數據線我連接到開發板的GPIOB 9引腳上,需要查找一下GPIOB 9在rt-thread系統內對應的引腳號(打開drv_gpio.c文件,看到引腳列表pins[]可見對應編號為25),后面需要配置到menuconfig內。(注意:新版驅動去掉了pins[]列表,暫時不知道去哪里查找引腳對應的編號,可能需要在代碼內使用GET_PIN(B,9)獲取了)

(2)添加DHTxx驅動軟件包,工程目錄內打開env,執行menuconfig,開啟軟件包和例程,版本選擇最新,引腳號配置為25:


2. 添加oled顯示屏驅動
(1)在工程目錄內建立user_add_files文件夾,將后期用戶代碼都放在這個文件夾內。並在user_add_files文件夾內新建SConscript文件,內容如下(目的是scons時自動添加文件夾內的所有文件到工程):
-
import os
-
from building import *
-
objs = []
-
cwd = GetCurrentDir()
-
list = os.listdir(cwd)
-
-
for item in list:
-
if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
-
objs = objs + SConscript( os.path.join(item, 'SConscript'))
-
Return( 'objs')
(2)在user_add_files文件夾內新建oled_ssd1306_drv文件夾並新建對應的SConscript文件, oled驅動文件放到oled_ssd1306_drv文件夾:

SConscript文件內容:
-
from building import *
-
cwd = GetCurrentDir()
-
src = Glob( '*.c')
-
CPPPATH = [cwd]
-
group = DefineGroup( 'oled_ssd1306_drv', src, depend = [''], CPPPATH = CPPPATH)
-
Return('group')
(3)使用scons --target=mdk5重新構建工程,發現oled驅動已添加到工程:

(4)在main.c中添加測試代碼:
-
-
-
-
-
-
/* defined the LED1 pin: PB5 */
-
-
-
-
int main(void)
-
{
-
/* set LED0 pin mode to output */
-
rt_pin_write(LED_R_PIN, PIN_LOW);
-
rt_pin_write(LED_G_PIN, PIN_LOW);
-
rt_pin_write(LED_B_PIN, PIN_LOW);
-
rt_pin_mode(LED_R_PIN, PIN_MODE_OUTPUT);
-
rt_pin_mode(LED_G_PIN, PIN_MODE_OUTPUT);
-
rt_pin_mode(LED_B_PIN, PIN_MODE_OUTPUT);
-
dht_device_t sensor = dht_create(PKG_USING_DHTXX_SAMPLE_PIN);
-
oled_dev.display_on();
-
char disp_str[50];
-
for(;;)
-
{
-
rt_thread_mdelay( 3000);
-
if(dht_read(sensor))
-
{
-
rt_int32_t temp = dht_get_temperature(sensor);
-
rt_int32_t humi = dht_get_humidity(sensor);
-
rt_kprintf( "Temp: %d, Humi: %d\n", temp, humi);
-
rt_sprintf(disp_str, "Humi: %d.%d %%",humi/10,humi%10);
-
oled_dev.show_string( 0,4,(unsigned char *)disp_str,16,1);
-
rt_sprintf(disp_str, "Temp: %d.%d C",temp/10,temp%10);
-
oled_dev.show_string( 0,24,(unsigned char *)disp_str,16,1);
-
oled_dev.refresh();
-
}
-
else
-
{
-
rt_kprintf( "Read dht sensor failed.\n");
-
rt_pin_write(LED_R_PIN, PIN_HIGH);
-
}
-
}
-
return RT_EOK;
-
}
編譯燒錄運行:

3. 添加ESP8266 WIFI模塊驅動
(1)stm32wb55芯片有兩個串口(lpuart1和uart1,正好一個做控制台、一個連接wifi模塊,配置時注意區分,我將lpuart1作為控制台,uart1連接wifi),在menuconfig下面路徑找到esp8266,開啟並根據實際情況配置wifi密碼和串口號:



(2)保存 --> pkgs --update --> scons --target=mdk5
(3)keil打開工程 --> 編譯 --> 燒錄 --> 運行,打開串口工具,查看信息,已經可以發現wifi正常連接上了。

4. 添加MQTT軟件包,當時有4個MQTT軟件包可選,哪個好用不了解,暫時選擇my mqtt。


利用軟件包自帶的sample進行測試,直接編譯燒錄,控制台輸入mqtt_start:

根據打印信息,可以看出已與服務器連接;之后發布一個消息試試,內容為hello!,由於例程已訂閱的默認主題和發布的默認主題相同,所以如果MQTT運行正常則發布的內容會被原樣接收到,測試如下,說明my mqtt軟件包初步運行正常。

5.因為需要使用json串傳輸數據,所以添加json軟件包。

三、在華為物聯網平台上創建產品
注冊華為雲賬號,在華為物聯網平台上創建產品、建立產品模型、創建設備,具體過程及傳輸的json字符串格式參見官方指導文件《MQTT設備快速接入》文檔:
(https://support.huaweicloud.com/qs-iothub/iot_05_0006.html)
我的產品截圖:

模型定義截圖(只添加溫度和濕度兩個屬性):

四、上傳溫度和濕度數據到華為雲
(1)根據my_mqtt軟件包自帶的sample例程的函數,稍作調整,用於上報數據,mqtt_start函數采用rtthread上電自動運行方式INIT_APP_EXPORT(mqtt_start)。
編寫數據上報函數(JSON串格式參見上面華為MQTT設備快速接入文檔):
-
/*
-
* 函數名稱:user_humiture_send_to_server
-
* 輸入參數:temp 溫度數據,單位0.1C
-
* humi 濕度數據,單位0.1%
-
* 返回數據:-1 發送失敗
-
* 0 發送成功
-
*/
-
int8_t user_humiture_send_to_server(int temp,int humi)
-
{
-
cJSON *root_prop;
-
cJSON *root_serv;
-
cJSON *array_serv;
-
cJSON *root;
-
char *cjson_str = NULL;
-
//檢查mqtt連接狀態
-
if(paho_mqtt_is_connected(&client) == 0) return -1;
-
//生成json字符串
-
root_prop = cJSON_CreateObject();
-
cJSON_AddNumberToObject(root_prop, "humidity", (humi/10) + 0.1 * (humi%10));
-
cJSON_AddNumberToObject(root_prop, "temperature", (temp/10) + 0.1 * (temp%10));
-
//
-
root_serv = cJSON_CreateObject();
-
cJSON_AddStringToObject(root_serv, "service_id", "humiture");
-
cJSON_AddItemToObject(root_serv, "properties", root_prop);
-
cJSON_AddStringToObject(root_serv, "event_time", "NULL"); //"20201207T002920Z"
-
//
-
array_serv = cJSON_CreateArray();
-
cJSON_AddItemToArray(array_serv,root_serv);
-
//
-
root = cJSON_CreateObject();
-
cJSON_AddItemToObject(root, "services", array_serv);
-
//發布數據
-
cjson_str = cJSON_PrintUnformatted(root);
-
mqtt_publish(cjson_str);
-
//釋放內存
-
cJSON_Delete(root);
-
cJSON_free(cjson_str);
-
return 0;
-
}
(2)在main函數內調用數據上報函數,具體見后面我的實驗工程代碼,編譯燒寫運行程序;登錄華為雲查看設備狀態為在線,可見雲端已收到數據:

(3)數據上報華為雲初步測試成功,我的測試工程代碼:
鏈接:https://pan.baidu.com/s/10I-BtE3UVGmxp7F2TpNxHA
提取碼:38sr
