
用野火啟明6M5開發板制作了一個基于FreeRTOS和LVGL V8的智能家居儀表盤,顏值較高,也可以作為桌面擺件使用,具體特點如下:
采用SPI+DTC驅動1.8寸SPI屏幕,超高幀率刷屏
采用LVGL V8界面庫繪制界面,有豐富控件、動畫(FPS穩定50以上?。?/span>
采用ESP8266聯網,使用心知天氣API獲取當前天氣并顯示到屏幕
采用ESP8266聯網,通過MQTT協議連接到云服務器,上傳狀態數據
采用魯班貓2安裝EMQ作為MQTT服務器,接收啟明6M5上傳數據
采用Node-RED + Homeassistant接入家庭自動化,與智能家居設備完美聯動

硬件平臺介紹
野火啟明6M5開發板
使用野火啟明6M5開發板來進行開發,開發板采用R7FA6M5BH3CFC作為主控芯片,有2MB Flash,2MB??!拿來開發GUI時的可發揮空間很大,接口有SD卡、以太網、PMOD、USB等等,接口很豐富,功能模塊有ESP8266、電容按鍵和實體按鍵等,功能十分的豐富。

外接模塊
由于開發板板載的模塊已經十分豐富,這里只外接了一個SPI屏幕和溫濕度傳感器模塊
采用1.8寸的液晶顯示屏,驅動芯片為ST7735S,SPI接口。
溫濕度傳感器采用瑞薩的HS3003溫濕度傳感器,I2C接口。
外設使用情況
本次使用到了許多的外設,其中有如下外設
串口4 (SCI_UART4) 作為調試串口使用
串口9 (SCI_UART9) 連接到ESP8266-AT模塊
SDHI連接到SD卡,提供文件系統的支持
AGT定時器為LVGL提供計時器
RTC提供實時的時間 (需要安裝CR1220電池)
SPI+DTC來實現屏幕的驅動,SPI以最大速度50MHz運行
TOUCH提供電容按鍵
I2C (SCI_I2C6) 連接到HS3003溫濕度傳感器

軟件設計方案
① 采用FreeRTOS作為本作品使用的RTOS
② 采用LVGL V8界面庫來進行界面開發
③ 采用letter-shell終端組件方便開發調試
④ 采用easylogger日志組件方便調試
⑤ 采用cJSON組件配合來完成網絡數據包打包與解包
多線程
由于代碼較多,所以不作全面的介紹,只介紹幾個線程的任務內容和軟件包的使用,文末有開源鏈接,作品的代碼全部開源,線程列表如下圖,下面依次介紹。

調試線程(debug_thread)
該線程使用了letter-shell和easylogger軟件包,提供完整的終端操作支持,同時支持日志打印,例如打印esp8266線程的調試日志。

使用自定義的命令來打印當前運行的任務列表

ESP8266線程(esp8266_thread)
該線程使用AT指令,實現開機自動連接Wi-Fi、自動連接MQTT服務器、訂閱主題。當收到消息隊列的數據后,更新溫濕度數據、LED狀態,然后使用cJSON來打包為JSON數據包,發布到MQTT服務器的指定主題。當收到MQTT發來的數據后,使用cJSON來解析JSON數據包,更新當前天氣等。
(觸摸)按鍵、LED、RTC線程(misc_thread)
該線程使用了MultiButton軟件包,可以實現一個按鍵的單擊、雙擊、連擊、長按等事件的處理,這里使用觸摸按鍵來搭配這個軟件包實現觸摸按鍵控制板載的LED亮滅,并且發送狀態信息到消息隊列中,交由ESP8266線程上傳到服務器端。
該線程同時也使用了RTC時鐘,每秒觸發一次中斷,發送當前時間到消息隊列中,交由LCD線程來顯示當前時間。
SD卡線程
該線程使用了Fatfs來掛載文件系統,自動將SD卡掛載到1: 分區下,提供給LVGL FS接口,實現LVGL加載SD卡中的文本、圖片等文件。
屏幕驅動線程(lcd_thread)
屏幕驅動使用硬件SPI+DTC的方案,這里沒有使用SCI上的SPI接口,因為根據瑞薩6M5的文檔得知掛在SCI上的SPI最大時鐘頻率為25Mhz,而直接連接的SPI最大時鐘頻率為50Mhz,顯然使用直連SPI接口可以獲得更快的刷屏速度。


該線程會接收多個線程傳入的消息隊列:接收RTC時鐘中斷發來的消息隊列,在LVGL中注冊的timer callback函數中讀取后顯示到屏幕上,每秒刷新一次時間數據;接收溫濕度線程發來的消息隊列,讀取后更新當前屏幕上的溫濕度數值和進度條控件。
溫濕度傳感器線程(sensor_thread)
該線程每隔十秒使用硬件I2C來讀取HS3003的數據并解算出溫濕度數據,發送溫濕度數據到消息隊列中,交由ESP8266線程來上傳到服務器和LCD線程來顯示到屏幕。
LVGL移植、界面設計LVGL移植
在本作品中對LVGL的顯示接口和文件系統接口做了移植,下面對LVGL的顯示接口移植做介紹,LVGL的顯示接口只有三個函數需要修改,分別是緩沖區的初始化、屏幕的初始化和刷屏函數的接口,對于屏幕的初始化在lcd_thread中已經完成過,所以只需完成緩沖區的初始化和刷屏函數接口的適配。
為了實現更快的刷屏速度,使用官方提供的example2程序,并且給LVGL申請一個全屏緩沖區,搭配SPI+DTC的全屏緩沖區,需要更新屏幕上的數據時只需要搬運數據即可。
對于刷屏函數的移植只需實現數據的搬運,代碼如下:
extern uint8_t lcd_buff[160][128][2];static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p){? ?if(disp_flush_enabled) {? ? ? ?/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/? ? ? ?int32_t x;? ? ? ?int32_t y;? ? ? ?for(y = area->y1; y <= area->y2; y++) {? ? ? ? ? ?for(x = area->x1; x <= area->x2; x++) {? ? ? ? ? ? ? ?/*Put a pixel to the display. For example:*/? ? ? ? ? ? ? ?/*put_px(x, y, *color_p)*/? ? ? ? ? ? ? ?lcd_buff[y][x][0] = color_p->full >> 8;? ? ? ? ? ? ? ?lcd_buff[y][x][1] = color_p->full;? ? ? ? ? ? ? ?color_p++;? ? ? ? ? ?}? ? ? ?}? ?}? ?/*IMPORTANT!!!? ? *Inform the graphics library that you are ready with the flushing*/? ?lv_disp_flush_ready(disp_drv);}
在lcd_thread線程的while循環中只需使用SPI發送全屏緩沖到屏幕,代碼如下:
void lcd_push_buff(void) {? ?R_SPI_Write(spilcd_spi0.p_ctrl, lcd_buff, LCD_W * LCD_H * 2, SPI_BIT_WIDTH_8_BITS);}/* 下面是主函數調用 */void lcd_thread_entry(void* pvParameters) {? ?FSP_PARAMETER_NOT_USED(pvParameters);? ?lcd_setup();? ?while (1) {? ? ? ?lcd_push_buff();? ? ? ?lv_task_handler();? ?}}
界面設計與仿真
采用NXP的GUI Guider作為PC端的設計器和仿真器,GUI Guider可以在PC端完成一站式的LVGL界面設計與仿真,例如下圖所示:

在GUI Guider中對兩個頁面分別創建了一個定時器,并且實現了兩個回調函數,代碼如下,通過這個定時器回調函數來實現周期性的刷新屏幕顯示的內容,更新網絡連接狀態、當前溫濕度、當前時間、當前天氣等數據。
MQTT與服務器解析
使用ESP8266模塊連接到MQTT服務器,因為MQTT也是自建的EMQX服務器,自由度相對onenet平臺要大很多,這里的上傳數據、下載數據都是統一由MQTT服務器搭配node-red來完成,避免來回地將ESP8266切換為透傳模式來實現HTTP訪問,全由服務器來進行數據的處理與打包,拖拽化開發自定義的MQTT消息處理流程不香嗎?
例如上傳當前溫濕度、LED狀態、知心天氣API獲得當前的天氣數據的流程設置如下:

服務器端解析溫濕度數據時,上傳的數據包格式為 JSON 數據,形如
{“hum”:51.498504638671872,”tem”:30.258193969726564}
為了解析MQTT的數據包,需要編寫一段代碼來實現數據類型的限定,這里還加了保留到兩位小數,其中的 “get humidity” 等函數只需編寫如下一段JavaScript代碼,經過解析后得到濕度數據,傳入后面的 “is null ?” 節點后若不為空就更新數據給Homeassistant的設備。
var field = msg.payload.hum;var out;if (field == null) {? ?out = { payload: null };} else {? ?if (typeof field === 'number') {? ? ? ?if (Number(field) === Math.round(field)) {? ? ? ? ? ?/* 整數 */? ? ? ? ? ?out = { payload: field };? ? ? ?} else {? ? ? ? ? ?/* 小數 */? ? ? ? ? ?out = { payload: field.toFixed(2) };? ? ? ?}? ?} else if (typeof field === 'boolean') {? ? ? ?/* 布爾 */? ? ? ?out = { payload: field };? ?} else if (typeof field === 'string') {? ? ? ?/* 字符串 */? ? ? ?out = { payload: field };? ?}}return out;
經過HTTP訪問知心天氣的API后,耶對得到的JSON結果進行解析,消息形如:
{? ?"results": [? ? ? ?{? ? ? ? ? ?"location": {? ? ? ? ? ? ? ?"id": "WTW3SJ5ZBJUY",? ? ? ? ? ? ? ?"name": "Shanghai",? ? ? ? ? ? ? ?"country": "CN",? ? ? ? ? ? ? ?"path": "Shanghai,Shanghai,China",? ? ? ? ? ? ? ?"timezone": "Asia/Shanghai",? ? ? ? ? ? ? ?"timezone_offset": "+08:00"? ? ? ? ? ?},? ? ? ? ? ?"now": {? ? ? ? ? ? ? ?"text": "Cloudy",? ? ? ? ? ? ? ?"code": "4",? ? ? ? ? ? ? ?"temperature": "35"? ? ? ? ? ?},? ? ? ? ? ?"last_update": "2023-08-13T12:10:14+08:00"? ? ? ?}? ?]}
解析代碼也非常簡單,text為當前的天氣文本,code為當前的天氣代碼:
var text = msg.payload.results[0].now.text;var code = msg.payload.results[0].now.code;return { payload: code };
然后發送最終的天氣碼到主題 /test/esp8266/sub,這個主題是ESP8266已經訂閱的,ESP8266線程完成數據的獲取,然后發送天氣碼到消息隊列,LCD讀取消息隊列,得到天氣碼,然后讀取SD卡中的天氣圖標,顯示到屏幕上,完成天氣圖標的更新。
最終效果
聯網進度顯示界面
開機自動聯網、進度條提示,FPS最低50!這個瑞薩的MCU跑LVGL完全無壓力

實時溫濕度、時間數據顯示

接入Homeassistant記錄溫濕度數據
通過node-red接入到HA作為一個設備顯示當前的溫濕度數據和板載LED的狀態

溫度數據的歷史曲線(開了空調溫度是直線下降?。?/span>


天貓精靈獲取板載LED狀態
設置了單擊觸摸按鍵開關LED2亮滅的邏輯操作,然后會自動上傳這個LED2的開關狀態到MQTT服務器上,通過node-red來上傳到Homeassistent,搭配巴法云平臺接入到語音助手,我用的是天貓精靈,可以通過語音助手獲取到當前LED2的狀態,當然只是做一個演示,可以實現的自動化智能家居當然還有很多的玩法。
視頻展示
總結
本作品開發過程中體會到了瑞薩的開發軟件十分的易用,方便,也學習到了LVGL V8、MQTT服務器數據包的收發,node-red橋接MQTT消息包到HA的知識。
完成以上所有的功能后Flash使用了1MB出頭(主要是GUI的資源文件),這個單片機是有2MB的Flash,界面開發還有很大的發揮空間。
1.8寸的小屏比較小,可以換成更大的屏和增加觸摸,但是RA6M5沒有專門的屏幕驅動外設,如果要拓展成并口MCU屏或者RGB屏還是有點受限的。
使用到了如下第三方軟件包,除FatFs使用BSD外別的均為MIT開源協議
FatFs
FreeRTOS
更多資料您可識別下方二維碼或點擊文末閱讀原文訪問查看:

您可復制下方網址到瀏覽器中打開進入瑞薩中文論壇查看:
https://community-ja.renesas.com/zh/forums-groups/mcu-mpu/
1
END
1
推薦閱讀
【瑞薩RA MCU創意氛圍賽作品賞析】項目20——便攜式熱成像儀
【瑞薩RA MCU創意氛圍賽作品賞析】項目21——藍牙平衡小車
【瑞薩RA創意氛圍賽作品賞析】項目22——室內空氣質量監測盒子