?利用零知增強版的GPIO 模擬時序
在本教程中,我們將探討如何使用 零知增強版的 GPIO 接口來模擬 WS2812B LED 燈帶的信號傳輸時序,從而實現對單色或多彩 LED 燈帶的控制。這種技術允許我們避開專用驅動庫,直接與硬件進行交互,理解并掌握 WS2812B 的通信機制。
一、工具原料
電腦、Windows系統
零知增強版開發板
Micro-usb線
WS2812RGB燈
WS2812B 是一款內含控制器芯片的全彩 LED 燈珠,每個燈珠可以獨立顯示紅、綠、藍三色。它通過單一數據線接收命令,實現高精度顏色控制。
二、硬件連接
零知增強版 | WS2812B |
5V | VCC |
GND | GND |
51 | Din |
1、硬件連接示意圖
2、實際效果
三、傳輸時序和顏色控制
1、信號傳輸時序
WS2812B 的數據傳輸遵循特定的時間序列:
高電平持續時間決定比特值:T1H 和 T0H 分別代表比特 1 和比特 0 的高電平持續時間。
低電平持續時間:T1L 和 T0L。
注:T1H為 800ns,T1L為 450ns 表示 1 比特。
T0H為 400ns,T0L為 850ns 表示 0 比特。
2、顏色控制
控制全局亮度和遵循WS2812B發送的時序:
通過brightness參數調節RGB燈的全局亮度
WS2812B協議發送時序為G -> R -> B
四、代碼驅動
1、相關定義和初始化
?// WS2812B相關定義 #define WS2812B_PIN 51 // WS2812B數據引腳 #define NUM_LEDS 8 // 燈珠數量 #define MAX_BRIGHTNESS 0.5 // 全局亮度調節(范圍:0.0 - 1.0) // WS2812B控制協議時間(根據各自的時序進行修改該定義) #define T1H 800 #define T1L 450 #define T0H 400 #define T0L 850 // 初始化WS2812B引腳 void setupWS2812B() { pinMode(WS2812B_PIN, OUTPUT); digitalWrite(WS2812B_PIN, LOW); } // 更精確的納秒延時函數(這里只是示例,實際可能需要更復雜的實現) // 假設使用了支持納秒級延時的定時器庫 // 這里暫時使用簡單的微秒級延時近似 void delayNanoseconds(unsigned long ns) { delayMicroseconds(ns / 1000); }
2、控制顏色和發送相關數據
? // 發送一個比特 void WS2812B_SendBit(bool bitVal) { if (bitVal) { // 發送邏輯1 digitalWrite(WS2812B_PIN, HIGH); delayNanoseconds(T1H); digitalWrite(WS2812B_PIN, LOW); delayNanoseconds(T1L); } else { // 發送邏輯0 digitalWrite(WS2812B_PIN, HIGH); delayNanoseconds(T0H); digitalWrite(WS2812B_PIN, LOW); delayNanoseconds(T0L); } } // 發送一個字節 void WS2812B_SendByte(uint8_t byte) { for (int i = 7; i >= 0; i--) { WS2812B_SendBit(byte & (1 < i)); } } // 發送RGB顏色數據(帶亮度調節) void WS2812B_SendColor(uint8_t red, uint8_t green, uint8_t blue, float brightness) { // 應用全局亮度調節 red = (uint8_t)(red * brightness * MAX_BRIGHTNESS); green = (uint8_t)(green * brightness * MAX_BRIGHTNESS); blue = (uint8_t)(blue * brightness * MAX_BRIGHTNESS); // WS2812B協議發送順序:G -?> R -> B WS2812B_SendByte(green); WS2812B_SendByte(red); WS2812B_SendByte(blue); }
3、實現流水燈、呼吸燈等功能
? // 效果:彩虹追逐 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 創建一個步驟計數器 for (int i = 0; i < NUM_LEDS; i++) { ledStep[i] = 0; // 初始化每個LED的步進 } uint8_t cycleCounter = 0; // 添加循環計數器 while (cycleCounter < iterations) { // 有限循環,迭代指定次數 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 的步驟計數器,模擬呼吸效果 ledStep[i] = (ledStep[i] + 1) % (steps * 2); // 確保計數器在達到兩倍步驟后重置 // 計算每個步驟的時間間隔 delayMicroseconds(period / steps); } // 在一輪呼吸之后關閉所有燈 clearAllLeds(); // 增加循環計數器 cycleCounter++; // 根據需要添加延遲,雖然這不是必須的 delay(wait); } } // 增加一個狀態變量來記錄是否有顏色覆蓋 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) { // 當到達最后一個燈時,標記為已覆蓋 isCovered = true; } delay(wait); } }
4、控制燈的狀態
? // 設置特定位置燈珠顏色 void setLedColor(uint8_t pos, uint8_t red, uint8_t green, uint8_t blue, float brightness) { if (pos < NUM_LEDS) { // 只發送前面燈珠的關閉信號,直到要設置顏色的燈珠位置 for (int i = 0; i < pos; i++) { WS2812B_SendColor(0, 0, 0, 0); } // 設置目標燈珠顏色 WS2812B_SendColor(red, green, blue, brightness); // 發送后面燈珠的關閉信號,從目標燈珠的下一個位置開始 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、主循環
? // 初始化 void setup() { setupWS2812B(); clearAllLeds(); // 確保燈帶初始狀態關閉 } // 主循環 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文章
23426瀏覽量
664385 -
燈帶
+關注
關注
0文章
19瀏覽量
8954 -
開源
+關注
關注
3文章
3442瀏覽量
42824
發布評論請先 登錄
相關推薦

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

【敏矽微ME32G070開發板免費體驗】點亮WS2812B燈板
基于瑞薩FPB-RA4E2智能床頭燈項目——1編譯環境搭建與點亮驅動ws2812全彩LED
在AvaotaA1全志T527開發板上驅動WS2812 RGB LCD
ESP32-S3控制WS2812燈帶顯示異常如何解決?
【Vision Board創客營連載體驗】利用 OpenMV 實現 AprilTag 跟蹤以及通過串口通訊控制 Arduino 驅動 LED 燈帶
STM32F030 MDA+PWM驅動ws2812b,起始的50US的低電平是怎么產生?
STM32F051C8 PA0不能以DMA的方式輸出PWM,沒有正確波形輸出是哪里出了問題?
麥爵士madrix麥覺仕幻彩燈條燈帶的基本認識以及測點編程調試方法解析

評論