用一款以圣誕為主題的互動式雪球讓節(jié)日氛圍鮮活起來!項目使用矽遞科技(Seeed Studio)圓形顯示屏和(XIAO)ESP32S3開發(fā)板打造出極具視覺吸引力的雪景動畫,包含動態(tài)飄落的雪花、風(fēng)效以及觸摸交互功能。憑借雙緩沖技術(shù)實現(xiàn)的流暢動畫,該項目能提供專業(yè)且無閃爍的體驗。
Seeed Studio XIAO系列是小型開發(fā)板,共享類似的硬件結(jié)構(gòu),尺寸實際上是拇指大小。這里的代號“小”代表它的一半特征“小”,另一半將是“羊角面包”。
Seeed Studio XIAO ESP32S3 Sense集成了攝像頭傳感器、數(shù)字麥克風(fēng)和SD卡支持。結(jié)合嵌入式ML計算能力和攝影能力,這款開發(fā)板是使用智能語音和視覺AI的絕佳工具。
開發(fā)特點:
動態(tài)雪景動畫:模擬飄落的雪花顆粒,其速度和風(fēng)效均可調(diào)節(jié)。
觸摸交互:只需輕觸屏幕,即可循環(huán)切換三張漂亮的圣誕主題背景圖。
流暢渲染:采用雙緩沖技術(shù)實現(xiàn)無縫視覺效果,無閃爍現(xiàn)象。
可定制背景:輕松添加自己的 PNG 圖像,對雪球進(jìn)行個性化設(shè)置。
你將學(xué)到的內(nèi)容:
如何將矽遞科技圓形顯示屏與xiao ESP32S3 開發(fā)板配合使用。
利用 TFT_eSPI 庫實現(xiàn)雙緩沖以呈現(xiàn)流暢動畫。
使用 lv_xiao_round_screen 庫處理觸摸輸入。
模擬粒子效果以實現(xiàn)逼真的雪景動畫。
環(huán)境準(zhǔn)備
硬件:對于該項目,我們需要這些設(shè)備:適用于曉開發(fā)板的矽遞科技圓形顯示屏、XIAO ESP32S3 開發(fā)板,我選用xiao ESP32S3 開發(fā)板是因為內(nèi)存方面的考慮。PNGDEC(PNG 解碼庫)運行大約需要 40KB 的內(nèi)存。
軟件準(zhǔn)備:要使用圓形顯示屏,請前往 “曉開發(fā)板圓形顯示屏入門” 頁面安裝必要的庫。嘗試運行一些示例,看看一切是否運行正常。
庫:對于這個項目,我們將使用隨適用于曉開發(fā)板的矽遞科技圓形顯示屏附帶的庫。按照 “曉開發(fā)板圓形顯示屏入門” 教程中的規(guī)定安裝所有庫。之后,你還需要以下內(nèi)容:
PNGdec 庫。
更新 LVGL 庫(或者不安裝來自矽遞科技 GitHub 的那個版本)
圖像:我們的圖像是存儲在閃存數(shù)組中的 PNG 圖像,使用 PNGdec 庫進(jìn)行顯示。所有圖像都必須是 PNG 格式。以下是我使用過的圖像 —— 全部由人工智能生成。
我們需要準(zhǔn)備好背景圖像,以便 TFT_eSPI 庫能夠顯示它們,并且這些圖像能很好地適配曉開發(fā)板的圓形顯示屏。
準(zhǔn)備圖像
調(diào)整圖像大小,我們的XIAO開發(fā)板圓形顯示屏分辨率為 240×240。我們需要對圖像進(jìn)行尺寸調(diào)整。下面我將展示如何使用 GIMP(一款圖像處理軟件)來操作。
1.打開圖像
2.選擇 “圖像”>“縮放圖像”
3.將寬度和高度都設(shè)置為 240。由于 “保持比例” 選項(鏈條圖標(biāo)所示)已被選中,一旦你更改了寬度,高度也會相應(yīng)地改變。
4.點擊 “縮放” 按鈕。
5.保存圖像(我打算覆蓋原來的圖像)。
現(xiàn)在圖像已經(jīng)準(zhǔn)備好了,讓我們來創(chuàng)建閃存數(shù)組吧。
創(chuàng)建閃存數(shù)組
注意:這些操作說明包含在 TFT_eSPI 庫的 Flash_PNG 示例當(dāng)中。要創(chuàng)建閃存數(shù)組,進(jìn)入 “文件轉(zhuǎn) C 語言風(fēng)格數(shù)組轉(zhuǎn)換器”。
創(chuàng)建數(shù)組的步驟如下:
1、使用 “瀏覽” 功能上傳圖像。在上傳圖像之后……
2、我們需要設(shè)置一些選項
所有其他選項都會變灰(即不可用、無法進(jìn)行設(shè)置操作)。
3、讓我們將數(shù)據(jù)類型更改為字符型(char)。
4、點擊 “轉(zhuǎn)換” 按鈕。這將會把圖像轉(zhuǎn)換為數(shù)組。
5、現(xiàn)在你可以按下 “另存為文件” 按鈕來保存你的圖像,并將其添加到你的 Arduino(開源電子原型平臺)代碼中,或者按下 “復(fù)制到剪貼板” 按鈕。
如果你選擇 “復(fù)制到剪貼板”,那么你需要點擊 Arduino 編輯器右側(cè)的三個點(省略號圖標(biāo)),然后選擇 “新建標(biāo)簽頁”。
給它取個名字(一般來說是你的圖像名加上.h 擴(kuò)展名)。
最終你所有的圖像都會以.h 文件的形式存在。
代碼
以下是對代碼主要功能的一些解釋,代碼中也包含了一些注釋。
頭文件與庫
我們首先引入一些庫:
#include #include #include
#include "background1.h"#include "background2.h"#include "background3.h"
#define USE_TFT_ESPI_LIBRARY#include "lv_xiao_round_screen.h"
(左右移動查看全部內(nèi)容)
請記住,你需要安裝矽遞科技(Seeed Studio)相關(guān)的庫。
背景圖像以下是管理背景圖像的函數(shù):
struct Background { const uint8_t *data; size_t size;};
const Background backgrounds[] = { {(const uint8_t *)background1, sizeof(background1)}, {(const uint8_t *)background2, sizeof(background2)}, {(const uint8_t *)background3, sizeof(background3)},};
(左右移動查看全部內(nèi)容)
結(jié)構(gòu)體:每個背景圖像都作為一個 Background 結(jié)構(gòu)體進(jìn)行存儲,該結(jié)構(gòu)體包含:
data:指向 PNG 數(shù)據(jù)的指針。
size:PNG 文件的大小。
數(shù)組:backgrounds 數(shù)組存儲了所有的背景圖像。currentBackground 變量用于追蹤當(dāng)前顯示的背景圖像。
雪花粒子模擬
1. 粒子初始化
void initParticles() { for (int i = 0; i < numParticles; i++) { ? ?particles[i].x = random(0, sprite.width()); ? ?particles[i].y = random(0, sprite.height()); ? ?particles[i].speed = random(3, 8); ?}}
(左右移動查看全部內(nèi)容)
它使用隨機(jī)位置和速度來初始化 numParticles 個粒子。
2. 粒子更新
void updateParticles() { for (int i = 0; i < numParticles; i++) { ? ?particles[i].speed += random(-1, 2); // 速度變化 ? ?particles[i].speed = constrain(particles[i].speed, 3, 8); ? ?particles[i].y += particles[i].speed; // 向下移動 ? ?particles[i].x += random(-1, 2); ? ? ?// 風(fēng)效影響 ? ?// 循環(huán)邏輯 ? ?if (particles[i].y > sprite.height()) { particles[i].y = 0; particles[i].x = random(0, sprite.width()); particles[i].speed = random(3, 8); } if (particles[i].x < 0) particles[i].x = sprite.width(); ? ?if (particles[i].x > sprite.width()) particles[i].x = 0; }}
(左右移動查看全部內(nèi)容)
通過以下方式更新粒子位置:
下落效果:每個粒子向下移動。
風(fēng)效影響:添加輕微的水平偏移。
循環(huán)機(jī)制:當(dāng)粒子從底部離開時,重置到頂部。
3. 粒子渲染
void renderParticlesToSprite() { for (int i = 0; i < numParticles; i++) { ? ?sprite.fillCircle(particles[i].x, particles[i].y, 2, TFT_WHITE); ?}}
(左右移動查看全部內(nèi)容)
它將每個粒子渲染為一個小的白色圓圈。
PNG 解碼
int16_t rc = png.openFLASH((uint8_t *)backgrounds[currentBackground].data, backgrounds[currentBackground].size, pngDrawToSprite);if (rc!= PNG_SUCCESS) { Serial.println("Failed to open PNG file!"); return;}png.decode(NULL, 0);
(左右移動查看全部內(nèi)容)
使用 png.openFLASH() 函數(shù)加載并解碼當(dāng)前的背景 PNG 圖像。
觸摸交互
if (chsc6x_is_pressed()) { currentBackground = (currentBackground + 1) % numBackgrounds; // 循環(huán)切換背景 delay(300); // 去抖動}
(左右移動查看全部內(nèi)容)
使用 chsc6x_is_pressed() 檢測觸摸事件,并通過遞增 currentBackground 變量來切換背景圖像。
設(shè)置與循環(huán)
設(shè)置部分:
void setup() { Serial.begin(115200); tft.begin(); tft.fillScreen(TFT_BLACK); sprite.createSprite(240, 240); // 匹配顯示屏尺寸 pinMode(TOUCH_INT, INPUT_PULLUP); Wire.begin(); initParticles();}
(左右移動查看全部內(nèi)容)
初始化顯示屏、觸摸輸入以及雪花粒子。
主循環(huán):
void loop() { sprite.fillScreen(TFT_BLACK); // 渲染背景和雪花 int16_t rc = png.openFLASH((uint8_t *)backgrounds[currentBackground].data, backgrounds[currentBackground].size, pngDrawToSprite); if (rc == PNG_SUCCESS) { png.decode(NULL, 0); updateParticles(); renderParticlesToSprite(); sprite.pushSprite(0, 0); } // 處理觸摸輸入 if (chsc6x_is_pressed()) { currentBackground = (currentBackground + 1) % numBackgrounds; delay(300); } delay(10); // 約100幀每秒}
(左右移動查看全部內(nèi)容)
清除圖像緩存(sprite),渲染當(dāng)前幀(背景 + 粒子),并檢查用戶輸入。
雙緩沖
為了減少雪花閃爍并提高動畫的流暢度,我們使用雙緩沖技術(shù)。
這使得我們能夠在屏幕外的緩沖區(qū)進(jìn)行繪制,然后再將其顯示在屏幕上。
本項目中的雙緩沖
在這個項目中,TFT_eSPI 庫的 TFT_eSprite 類實現(xiàn)了雙緩沖。
1. 圖像緩存(sprite)創(chuàng)建
在 setup() 函數(shù)中創(chuàng)建圖像緩存(屏幕外緩沖區(qū)):
sprite.createSprite(240, 240); // 匹配顯示屏尺寸
(左右移動查看全部內(nèi)容)
2. 繪制緩沖區(qū)
所有繪制操作(背景渲染和雪花粒子動畫)都在圖像緩存(sprite)上進(jìn)行:
sprite.fillScreen(TFT_BLACK); // 清除圖像緩存renderParticlesToSprite(); // 繪制雪花粒子
(左右移動查看全部內(nèi)容)
3. 更新顯示
在圖像緩存中完整繪制完一幀后,通過一次操作將其推送到顯示屏上:
sprite.pushSprite(0, 0);
(左右移動查看全部內(nèi)容)
這會立即將緩沖區(qū)的內(nèi)容傳輸?shù)狡聊簧稀?/p>
4. 復(fù)用
在循環(huán)開始時清除圖像緩存,以便每一幀都能復(fù)用它:
sprite.fillScreen(TFT_BLACK);
(左右移動查看全部內(nèi)容)
使用雙緩沖的優(yōu)勢
流暢的雪花動畫:下落的雪花粒子能夠無縫更新,不會出現(xiàn)閃爍現(xiàn)象。
動態(tài)背景切換:觸摸觸發(fā)的背景切換能夠在無可見延遲或瑕疵的情況下完成。
高效渲染:在內(nèi)存(RAM)中進(jìn)行繪制比逐行直接更新顯示屏要快。
總結(jié)
我希望有人能制作一個 3D 球體,把適用于曉開發(fā)板的矽遞科技圓形顯示屏放在里面,然后將其掛在圣誕樹上。
我也希望修改代碼,使其能從 SD 卡加載圖像,而不是使用閃存數(shù)組來存儲圖像。
希望你們喜歡這個項目,為你們的圣誕節(jié)增添一點奇妙氛圍。
-
嵌入式
+關(guān)注
關(guān)注
5152文章
19670瀏覽量
317515 -
顯示屏
+關(guān)注
關(guān)注
28文章
4605瀏覽量
76392 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5680瀏覽量
104696 -
ESP32
+關(guān)注
關(guān)注
21文章
1017瀏覽量
19261
發(fā)布評論請先 登錄

深入解讀led互動地磚屏的原理與互動地磚屏和常規(guī)顯示屏的區(qū)別
ESP32硬定時器可以用來掃描HUB75D的LED32*16的顯示屏嗎?
InfoComm展:互動式觸摸屏走對了路
圓形LED顯示屏的詳細(xì)介紹
基于ESP32構(gòu)建一個具有3.5英寸大顯示屏的互聯(lián)網(wǎng)廣播設(shè)備

帶有ESP32和OLED顯示屏的Instagram追隨者計數(shù)器

帶GPS和OLED顯示屏的ESP32開發(fā)板

帶OLED顯示屏的LoRa節(jié)點和3個帶ESP32的繼電器

評論