National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 08

NeoPixel 全彩燈條

每顆燈的 RGB 顏色與動畫效果
Interaction 25 minute(s)

Learning Objectives

  • 說明 NeoPixel(WS2812)為什麼一支腳位就能控制整條燈的每一顆顏色
  • 用 neopixel.NeoPixel 設定單顆或全部燈的 RGB 顏色,並用 write() 送出
  • 用迴圈與 sleep 寫出跑馬燈這類動畫
  • 依亮度估算燈條的電流,判斷什麼時候需要外接電源

一支腳位控制一整條燈

第 03 課的 LED 一支腳位只能控制一顆燈,而且只有亮和暗。如果要做一整排會變色的燈,例如 30 顆的氣氛燈條, 照第 03 課的方法需要 90 支腳位(每顆燈的紅、綠、藍各一支),ESP32 根本沒有這麼多腳位。

NeoPixel 是 Adafruit 對一類「可定址 LED」的稱呼,最常見的晶片是 WS2812B。它的做法是: 每一顆燈裡面除了紅、綠、藍三個 LED,還有一顆小小的控制晶片;所有燈用一條資料線串在一起。

這一課要回答:

  1. 一條資料線怎麼分別告訴每一顆燈要亮什麼顏色?
  2. MicroPython 程式怎麼設定顏色、做出動畫?
  3. 燈條全亮時要多少電,什麼時候不能直接用開發板供電?

資料怎麼傳到每一顆燈

開發板從資料線送出一長串位元,每一顆燈需要 24 位元(綠、紅、藍各 8 位元)。 第一顆燈收下最前面的 24 位元留給自己,把後面的資料轉送給下一顆;第二顆再收下 24 位元,依此類推。 所以燈條上的燈有順序,程式用索引 0、1、2…指定第幾顆。

ESP32 GPIO5 ──▶ [燈 0] ──▶ [燈 1] ──▶ [燈 2] ──▶ … ──▶ [燈 7]
              收 24 位元   收 24 位元   收 24 位元

WS2812B 的資料速度是 800 Kbps,一顆燈的 24 位元大約 30 微秒就送完,所以就算有幾百顆燈,更新一次也很快。 晶片實際的順序是「綠、紅、藍」,不過 MicroPython 的 neopixel 模組會幫你換好,程式裡一律寫 (紅, 綠, 藍)。

RGB:三個 0~255 的數字

每一種顏色用三個整數表示:紅(R)、綠(G)、藍(B),每個從 0 到 255,剛好是一個位元組(8 位元)。 三個位元組可以組合出 256 × 256 × 256 = 16,777,216 種顏色。網頁上的色碼 #FF5000 也是同一件事,只是用十六進位寫:

寫法 紅 綠 藍 看起來
(255, 0, 0) 255 0 0 紅
(255, 80, 0) 255 80 0 橘(#FF5000)
(255, 255, 255) 255 255 255 白(三色全亮)
(0, 0, 30) 0 0 30 很暗的藍
(0, 0, 0) 0 0 0 熄滅

數字越大越亮。同樣的比例、較小的數字,就是同一種顏色比較暗的版本,例如 (30, 30, 30) 是暗一點的白。

逐步看:設定顏色,再 write() 送出

注意第 6~8 行設定顏色時,上方的燈條還沒有變;要等第 10 行 np.write() 執行完,燈條才一起換成新的顏色。 np[0] 這些索引設定的只是開發板記憶體裡的資料。

逐步看:跑馬燈

動畫就是「改顏色、write()、等一下」一直重複。每一輪先全部關掉,再只點亮第 i 顆,看起來就像一顆光點往前跑。

燈條要多少電

NeoPixel 好用,但很耗電。Adafruit 的說明文件提到,每一顆燈在三色全亮(白色、最亮)時最多大約 60 mA, 平常顯示各種顏色時,可以用每顆約 20 mA 粗略估計。

燈數 全亮白色最多 粗估(每顆 20 mA)
8 顆 480 mA 160 mA
30 顆 1.8 A 600 mA
60 顆 3.6 A 1.2 A

開發板的 USB 供電與板上穩壓器能提供的電流有限,幾顆燈的小燈環通常沒問題,長燈條要用外接的 5V 電源, 並且把電源的 GND 和 ESP32 的 GND 接在一起(訊號才有共同的參考電位)。 程式也能幫忙省電:把顏色數字調小,亮度降低,電流也跟著降低。

接線時的幾個好習慣(來自 Adafruit 的建議):

  • 在燈條的電源正負極之間並聯一顆大電容(500~1000 μF,耐壓 6.3V 以上)
  • 資料線串一顆 300~500Ω 的電阻,放在靠近第一顆燈的那一端
  • 接上已通電的電路時,先接 GND,再接電源,最後接資料線
  • 5V 供電的燈條,最好用 5V 的資料訊號;ESP32 輸出的是 3.3V,有時需要電位轉換(level shifter)模組

下一個範例的 estimate_ma 用「全亮 60 mA」依亮度比例估算,只是粗略的估計,實際電流要看燈的規格與量測。

逐步看:調亮度並估算電流

dim 函式把三個顏色乘上同一個比例。看每一輪的輸出:亮度變成十分之一,估計的電流也變成十分之一左右。

互動練習:改顏色、改動畫

起始程式是一個紅色的跑馬燈。依序完成任務:

  1. 先直接執行,看紅色光點從第 0 顆跑到第 7 顆。
  2. 把光點改成綠色 (0, 255, 0)。
  3. 跑馬燈結束後,讓 8 顆燈全部亮成暗一點的白色 (40, 40, 40)(提示:fill 之後別忘了 write)。
  4. 回答一個問題。

小測驗:資料與顏色

1.

每一顆 WS2812B 的顏色資料是 24 位元(紅、綠、藍各 8 位元),一顆燈可以表示幾種顏色?

2.

程式執行 np[3] = (0, 0, 255) 之後就結束了,沒有呼叫 np.write()。第 3 顆燈會怎樣?

3.

下面的程式會印出什麼?

def dim(color, level):
    r, g, b = color
    return (int(r * level), int(g * level), int(b * level))

print(dim((200, 100, 50), 0.3))
第 1 次作答

小測驗:動畫與供電

1.

下面的程式會印出什麼?(兩種顏色輪流,常用來做交錯閃爍的效果)

colors = [(255, 0, 0), (0, 255, 0)]
for i in range(5):
    print(colors[i % 2][1], end=" ")
2.

一條 30 顆的燈條要全部亮最亮的白色,以每顆最多 60 mA 估計,最多需要多少電流?

3.

跑馬燈的迴圈裡少了 np.fill((0, 0, 0)) 這一行,看起來會怎樣?

第 1 次作答

重點整理

  • NeoPixel(WS2812B)每一顆燈都有控制晶片,所有燈用一條資料線串接,每顆收下 24 位元、其餘轉送下一顆。
  • np = NeoPixel(Pin(5), 8) 建立燈條;np[i] = (r, g, b) 設定第 i 顆、np.fill(顏色) 設定全部,數值 0~255。
  • 設定只改記憶體,np.write() 才會送出,燈條才改變。
  • 動畫=改顏色、write()、sleep,一直重複;跑馬燈要記得先把其他燈關掉。
  • 每顆燈全亮白色最多約 60 mA;燈多時用外接 5V 電源、共地,並在電源加電容、資料線加電阻。

下一課讀溫溼度感測器,再把數值顯示在 OLED 小螢幕上。

這一課完成了!
Next lesson:溫溼度感測與 OLED 顯示
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。