?利用零知增強版的GPIO 模擬時序
在本教程中,我們將探討如何使用 零知增強版的 GPIO 接口來模擬 WS2812B LED 燈帶的信號傳輸時序,從而實現(xiàn)對單色或多彩 LED 燈帶的控制。這種技術允許我們避開專用驅動庫,直接與硬件進行交互,理解并掌握 WS2812B 的通信機制。
一、工具原料
電腦、Windows系統(tǒng)
零知增強版開發(fā)板
Micro-usb線
WS2812RGB燈
WS2812B 是一款內含控制器芯片的全彩 LED 燈珠,每個燈珠可以獨立顯示紅、綠、藍三色。它通過單一數(shù)據(jù)線接收命令,實現(xiàn)高精度顏色控制。
二、硬件連接
零知增強版 | WS2812B |
5V | VCC |
GND | GND |
51 | Din |
1、硬件連接示意圖
2、實際效果
三、傳輸時序和顏色控制
1、信號傳輸時序
WS2812B 的數(shù)據(jù)傳輸遵循特定的時間序列:
高電平持續(xù)時間決定比特值:T1H 和 T0H 分別代表比特 1 和比特 0 的高電平持續(xù)時間。
低電平持續(xù)時間:T1L 和 T0L。
注:T1H為 800ns,T1L為 450ns 表示 1 比特。
T0H為 400ns,T0L為 850ns 表示 0 比特。
2、顏色控制
控制全局亮度和遵循WS2812B發(fā)送的時序:
通過brightness參數(shù)調節(jié)RGB燈的全局亮度
WS2812B協(xié)議發(fā)送時序為G -> R -> B
四、代碼驅動
1、相關定義和初始化
?// WS2812B相關定義 #define WS2812B_PIN 51 // WS2812B數(shù)據(jù)引腳 #define NUM_LEDS 8 // 燈珠數(shù)量 #define MAX_BRIGHTNESS 0.5 // 全局亮度調節(jié)(范圍:0.0 - 1.0) // WS2812B控制協(xié)議時間(根據(jù)各自的時序進行修改該定義) #define T1H 800 #define T1L 450 #define T0H 400 #define T0L 850 // 初始化WS2812B引腳 void setupWS2812B() { pinMode(WS2812B_PIN, OUTPUT); digitalWrite(WS2812B_PIN, LOW); } // 更精確的納秒延時函數(shù)(這里只是示例,實際可能需要更復雜的實現(xiàn)) // 假設使用了支持納秒級延時的定時器庫 // 這里暫時使用簡單的微秒級延時近似 void delayNanoseconds(unsigned long ns) { delayMicroseconds(ns / 1000); }
2、控制顏色和發(fā)送相關數(shù)據(jù)
? // 發(fā)送一個比特 void WS2812B_SendBit(bool bitVal) { if (bitVal) { // 發(fā)送邏輯1 digitalWrite(WS2812B_PIN, HIGH); delayNanoseconds(T1H); digitalWrite(WS2812B_PIN, LOW); delayNanoseconds(T1L); } else { // 發(fā)送邏輯0 digitalWrite(WS2812B_PIN, HIGH); delayNanoseconds(T0H); digitalWrite(WS2812B_PIN, LOW); delayNanoseconds(T0L); } } // 發(fā)送一個字節(jié) void WS2812B_SendByte(uint8_t byte) { for (int i = 7; i >= 0; i--) { WS2812B_SendBit(byte & (1 R -> B WS2812B_SendByte(green); WS2812B_SendByte(red); WS2812B_SendByte(blue); }
3、實現(xiàn)流水燈、呼吸燈等功能
? // 效果:彩虹追逐 void rainbowChaseEffect(uint8_t wait) { for (int offset = 0; offset < 255; offset++) { for (int i = 0; i < NUM_LEDS; i++) { int hue = (i * 255 / NUM_LEDS + offset) % 255; uint8_t r = 0, g = 0, b = 0; if (hue < 85) { r = 255 - hue * 3; g = hue * 3; b = 0; } else if (hue < 170) { hue -= 85; r = 0; g = 255 - hue * 3; b = hue * 3; } else { hue -= 170; r = hue * 3; g = 0; b = 255 - hue * 3; } WS2812B_SendColor(r, g, b, MAX_BRIGHTNESS); } delay(wait); } } // 呼吸燈效果 void breathAndFlow(uint8_t red, uint8_t green, uint8_t blue, uint8_t steps, uint16_t period, uint8_t wait, uint8_t iterations) { int ledStep[NUM_LEDS]; // 為每個 LED 創(chuàng)建一個步驟計數(shù)器 for (int i = 0; i < NUM_LEDS; i++) { ledStep[i] = 0; // 初始化每個LED的步進 } uint8_t cycleCounter = 0; // 添加循環(huán)計數(shù)器 while (cycleCounter < iterations) { // 有限循環(huán),迭代指定次數(shù) for (int i = 0; i < NUM_LEDS; i++) { // 計算當前 LED 的亮度比例 float brightness = (sin(ledStep[i] * (M_PI / (steps))) + 1) / 2; WS2812B_SendColor(red, green, blue, brightness); // 使用計算出的亮度 // 更新 LED 的步驟計數(shù)器,模擬呼吸效果 ledStep[i] = (ledStep[i] + 1) % (steps * 2); // 確保計數(shù)器在達到兩倍步驟后重置 // 計算每個步驟的時間間隔 delayMicroseconds(period / steps); } // 在一輪呼吸之后關閉所有燈 clearAllLeds(); // 增加循環(huán)計數(shù)器 cycleCounter++; // 根據(jù)需要添加延遲,雖然這不是必須的 delay(wait); } } // 增加一個狀態(tài)變量來記錄是否有顏色覆蓋 bool isCovered = false; // 流水燈 void ShampEffect(uint8_t red, uint8_t green, uint8_t blue, uint8_t trailDecay, uint8_t wait) { // 特殊處理第一個燈 WS2812B_SendColor(red, green, blue, MAX_BRIGHTNESS); // 從第二個燈開始的索引為1 for (int i = 0; i < NUM_LEDS; i++) { for (int j = 0; j <= NUM_LEDS; j++) { if (i - j == 0) { if (!isCovered) { // 如果沒有被覆蓋,設置為綠色 WS2812B_SendColor(0, 0, 0, MAX_BRIGHTNESS); } else { WS2812B_SendColor(red, green, blue, MAX_BRIGHTNESS); } } else { WS2812B_SendColor(0, 0, 0, MAX_BRIGHTNESS * trailDecay / 255.0); } } if (i == NUM_LEDS - 1) { // 當?shù)竭_最后一個燈時,標記為已覆蓋 isCovered = true; } delay(wait); } }
4、控制燈的狀態(tài)
? // 設置特定位置燈珠顏色 void setLedColor(uint8_t pos, uint8_t red, uint8_t green, uint8_t blue, float brightness) { if (pos < NUM_LEDS) { // 只發(fā)送前面燈珠的關閉信號,直到要設置顏色的燈珠位置 for (int i = 0; i < pos; i++) { WS2812B_SendColor(0, 0, 0, 0); } // 設置目標燈珠顏色 WS2812B_SendColor(red, green, blue, brightness); // 發(fā)送后面燈珠的關閉信號,從目標燈珠的下一個位置開始 for (int i = pos + 1; i < NUM_LEDS; i++) { WS2812B_SendColor(0, 0, 0, 0); } } } // 設置所有燈珠顏色 void setAllLeds(uint8_t red, uint8_t green, uint8_t blue, float brightness) { clearAllLeds();// 先清除所有燈珠,確保沒有雜色 for (int i = 0; i < NUM_LEDS; i++) { WS2812B_SendColor(red, green, blue, brightness); } } // 清除所有燈珠 void clearAllLeds() { for (int i = 0; i < NUM_LEDS * 3; i++) { WS2812B_SendByte(0); } } ?
5、主循環(huán)
? // 初始化 void setup() { setupWS2812B(); clearAllLeds(); // 確保燈帶初始狀態(tài)關閉 } // 主循環(huán) void loop() { uint8_t Count = 0; //clearAllLeds(); // 設置第六個燈珠為藍色 //setLedColor(5, 0, 0, 255, MAX_BRIGHTNESS); //delay(500); while(Count < 10) { ShampEffect(0, 0, random(255), 256, 200); Count ++; } //rainbowChaseEffect(1000); breathAndFlow(0,255,0,5,50,100,100); }
五、成果展示
將上訴代碼驗證后上傳到零知板,可以看到以下流水燈、呼吸燈等測試結果。
https://live.csdn.net/v/437153?spm=1001.2014.3001.5501
?
使用 GPIO 模擬時序驅動 WS2812B LED 燈帶
審核編輯 黃宇
-
led
+關注
關注
242文章
23480瀏覽量
665879 -
燈帶
+關注
關注
0文章
19瀏覽量
9006 -
開源
+關注
關注
3文章
3472瀏覽量
42956
發(fā)布評論請先 登錄
相關推薦
CW32模塊使用 WS2812彩燈


零知開源——使用 GPIO 模擬時序驅動 WS2812B LED 燈帶
零知開源——網頁控制WS2812B

評論