硬件環境:
(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中添加測試代碼:
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include "oled.h"
#include "dhtxx.h"
/* defined the LED1 pin: PB5 */
#define LED_G_PIN GET_PIN(B, 0)
#define LED_R_PIN GET_PIN(B, 1)
#define LED_B_PIN GET_PIN(B, 5)
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