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

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

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

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

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

M5Stack圣誕雪球開(kāi)源分享

評(píng)論