WS2812B灯带项目

WS2812B灯带项目

刷B站偶然间看到了用电脑控制WS2812B显示各种图案,对此非常感兴趣,于是通过查资料,AI等实现了本项目,项目化驱动学习。

项目概述

本项目基于ESP32的实现智能WS2812B RGB灯带控制,主要是通过该项目学习电路,单片机等相关知识

设计思路分析

  1. 硬件架构设计思路

安全第一的设计理念

· 采用电平转换器解决3.3V ESP32与5V WS2812B的通信兼容性问题
· 通过220Ω电阻保护数据信号线,防止电流冲击
· 严格的共地(GND)设计,确保信号稳定性
· 外部独立供电方案,避免USB供电不足和潜在风险

模块化连接策略

· 电源模块:5V5A外部电源 → 定制线 → 灯带供电
· 控制模块:ESP32 → 电平转换 → 灯带数据控制
· 信号调理:串联电阻优化信号质量
· 灵活扩展:面包板设计便于调试和扩展

  1. 软件架构设计思路

分层式程序设计

· 底层驱动层:FastLED库提供硬件抽象
· 核心逻辑层:模式管理和动画算法
· 用户交互层:串口命令解析和反馈
· 效果展示层:多种预设灯光模式

状态机设计模式

· 定义8种独立灯光模式,每种模式有专属的状态管理
· 统一的模式切换接口,支持热切换
· 参数持久化设计,保持用户设置

材料准备

  1. WS2812B灯带1条(30灯珠,品牌:btf lighting)

  2. ESP32(WROOM-32E,品牌:源地工作室)

  3. 三种杜邦线若干(共对共,母对母,共对母)

  4. 面包板

  5. 3.3v 5v电平逻辑转换器

  6. 5V5A DC电源(内正外负)

  7. 特殊定制线(一端DC插座,内正外负,一端分为两正负:裸线正负+杜邦公头正负)

  8. 快速接线端子

  9. 220R电阻x1

  10. 一根USB-A to USB-C 数据线

电路连接

电路连接遵循 共地(GND) 原则,并且注意单片机供电不得同时接入多个外部电源输入,否则极有可能烧毁电脑主板,并且在没有连接好的情况下,绝对不可以接电源,否则可能触电!

graph TD
    A[开始连接WS2812电路] --> B[材料准备]

    B --> C[电源部分连接]
    B --> D[面包板线路布置]
    B --> E[信号线路连接]

    C --> C1[5V5A DC电源]
    C1 --> C2[连接定制线<br>DC插座端]
    C2 --> C3[定制线裸线端<br>通过快速接线端子<br>连接灯带电源正负]

    D --> D1[定制线杜邦头<br>连接面包板正负轨道]
    D1 --> D2[正轨道引线到<br>逻辑转换器HV VCC]
    D1 --> D3[负轨道三根线分别连接:]
    D3 --> D4[ESP32GND]
    D3 --> D5[逻辑转换器LV GND]
    D3 --> D6[逻辑转换器HV GND]

    E --> E1[ESP32 GPIO4<br>连接逻辑转换器A1通道]
    E1 --> E2[逻辑转换器B1通道<br>串联220R电阻]
    E2 --> E3[连接到灯带数据端<br>3pin中间引脚]

    E --> E4[ESP32 USB连接电脑<br>供电和数据通讯]
    E4 --> E5[ESP32 3.3V输出<br>连接逻辑转换器LV VCC]

    C3 --> F[电路连接完成]
    E3 --> F
    E5 --> F

    F --> G[开始编程控制]

    %% 样式定义
    classDef power fill:#f9f,stroke:#333,stroke-width:2px;
    classDef logic fill:#ccf,stroke:#333,stroke-width:2px;
    classDef signal fill:#9f9,stroke:#333,stroke-width:2px;
    classDef complete fill:#ff9,stroke:#333,stroke-width:3px;

    class C1,C2,C3 power;
    class D2,D5,D6,E5 logic;
    class E1,E2,E3 signal;
    class F complete;

补充

如果你考虑不接电脑,那么可以 拔掉USB与电脑相接的线后,然后在从电源轨道引出一根公对母杜邦线和ESP32的5V的GPIO相连接.

程序烧录

烧录方法

我采用Arduino IDE进行本项目程序编写与烧录

  1. 去Arduino IDE官网下载最新的IDE

  2. 在File-preference中下滑找到语言选项,选择中文(据说此功能仅限2.x版本)

  3. 在文件-首选项中下滑在下面的项目链接,添加:

1
https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_index_cn.json

这个链接是乐鑫官方文档中提供的镜像版本,更多内容可以参考文档,切换该文档可以有效解决安装工具链和库的时候无法访问github无法安装的问题。

  1. 在工具-开发板-开发板管理器顶部输入esp32,找到由 Espressif Systems 提供的 ESP32 项目。建议安装最新版,如果你用的上面的链接,可能还会有-cn版本,建议安装此版本。

  2. 选择开发板:点击 工具 (Tools) > 开发板 (Board)。在弹出的列表中,找到 ESP32 Arduino 分类。这里有很多具体的型号。如果您不确定,一个通用且安全的选择是 ESP32 Dev Module。

  3. 选择端口:将您的 ESP32 通过 USB 线连接到电脑。点击 工具 (Tools) > 端口 (Port)。选择一个新出现的端口。在 Windows 上通常是 COMx(如 COM3),在 Mac 上是 /dev/cu.usbmodem...。

7.然后写入你的代码,然后点击验证,如果编译通过了,然后再点上传即可。(首次编译可能较慢)

  1. 然后重新上电或者摁复位键,ESP32就会开始工作,你的灯带就会亮起来~哦耶

代码分享:

针对30个灯珠并使用GPIO4,WS2812控制代码。这个代码包含多种灯光模式,可以通过串口命令切换。

硬件连接

WS2812 灯带 ESP32 开发板
VCC (5V) 5V 引脚
GND GND 引脚
DIN (数据线) GPIO 4

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
#include <FastLED.h>

// LED配置
#define LED_PIN 4 // 数据线连接到GPIO4
#define NUM_LEDS 30 // 30个灯珠
#define BRIGHTNESS 100 // 初始亮度 (0-255)
#define LED_TYPE WS2812
#define COLOR_ORDER GRB // WS2812的颜色顺序

// 定义LED数组
CRGB leds[NUM_LEDS];

// 模式定义
#define MODE_RAINBOW 0
#define MODE_THEATER 1
#define MODE_CONFETTI 2
#define MODE_SOLID 3
#define MODE_BREATH 4
#define MODE_RAIN 5
#define MODE_FIRE 6
#define MODE_COMET 7
#define NUM_MODES 8

// 全局变量
uint8_t currentMode = MODE_RAINBOW;
uint8_t gHue = 0; // 彩虹色调
uint8_t currentBrightness = BRIGHTNESS;
CRGB solidColor = CRGB::Blue; // 纯色模式的默认颜色

void setup() {
Serial.begin(115200);
delay(1000); // 等待串口初始化

Serial.println("=== ESP32 WS2812 控制器 ===");
Serial.println("连接信息:");
Serial.println("- GPIO: 4");
Serial.println("- 灯珠数量: 30");
Serial.println("- 当前模式: 彩虹");
Serial.println();
Serial.println("串口命令:");
Serial.println("0-7: 切换模式 (0=彩虹, 1=跑马灯, 2=五彩纸屑, 3=纯色, 4=呼吸, 5=下雨, 6=火焰, 7=彗星)");
Serial.println("b100: 设置亮度为100");
Serial.println("r/g/b: 纯色模式切换颜色");
Serial.println("----------------------------");

// 初始化FastLED
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(currentBrightness);

// 初始显示一个启动动画
startupAnimation();
}

void loop() {
// 检查串口命令
checkSerialCommands();

// 根据当前模式执行相应的动画
switch(currentMode) {
case MODE_RAINBOW:
rainbow();
break;
case MODE_THEATER:
theaterChase();
break;
case MODE_CONFETTI:
confetti();
break;
case MODE_SOLID:
solid();
break;
case MODE_BREATH:
breath();
break;
case MODE_RAIN:
rain();
break;
case MODE_FIRE:
fire();
break;
case MODE_COMET:
comet();
break;
}

FastLED.show();
// 每种模式有自己的延时控制,这里不需要额外延时
}

// === 模式函数 ===

// 彩虹模式
void rainbow() {
fill_rainbow(leds, NUM_LEDS, gHue, 7);
EVERY_N_MILLISECONDS(20) {
gHue++;
}
}

// 跑马灯模式
void theaterChase() {
static uint8_t j = 0;

// 将所有LED设置为暗
fill_solid(leds, NUM_LEDS, CRGB::Black);

// 每隔3个LED设置一个亮起的LED
for(int i = 0; i < NUM_LEDS; i = i + 3) {
leds[(i + j) % NUM_LEDS] = CHSV(gHue, 255, 255);
}

EVERY_N_MILLISECONDS(100) {
j = (j + 1) % 3;
gHue++;
}
}

// 五彩纸屑模式
void confetti() {
// 淡出所有LED
fadeToBlackBy(leds, NUM_LEDS, 10);

// 随机位置添加彩色点
int pos = random16(NUM_LEDS);
leds[pos] += CHSV(gHue + random8(64), 200, 255);

EVERY_N_MILLISECONDS(30) {
gHue++;
}
}

// 纯色模式
void solid() {
fill_solid(leds, NUM_LEDS, solidColor);
}

// 呼吸灯模式
void breath() {
uint8_t breath = (exp(sin(millis() / 2000.0 * PI)) - 0.36787944) * 108.0;
fill_solid(leds, NUM_LEDS, CHSV(gHue, 255, breath));

EVERY_N_SECONDS(10) {
gHue += 32;
}
}

// 下雨模式
void rain() {
// 所有LED向下移动并淡出
for(int i = 0; i < NUM_LEDS - 1; i++) {
leds[i] = leds[i + 1];
leds[i].fadeToBlackBy(20);
}

// 随机在顶部添加新的雨滴
if(random8() < 50) {
leds[NUM_LEDS - 1] = CHSV(160, 200, 255); // 蓝色雨滴
} else {
leds[NUM_LEDS - 1] = CRGB::Black;
}

delay(50);
}

// 火焰效果
void fire() {
// 热源在底部
for(int i = 0; i < NUM_LEDS; i++) {
// 温度从底部到顶部递减
int temperature = map(i, 0, NUM_LEDS - 1, 255, 0);
temperature = qsub8(temperature, random8(0, 80));

// 将温度转换为火焰颜色 (红->黄->白)
if(temperature > 200) {
leds[i] = CRGB(255, 255, 255); // 白色核心
} else if(temperature > 150) {
leds[i] = CRGB(255, 255, 0); // 黄色
} else if(temperature > 100) {
leds[i] = CRGB(255, 100, 0); // 橙色
} else {
leds[i] = CRGB(255, 0, 0); // 红色
}

leds[i].nscale8_video(temperature);
}

// 随机闪烁
for(int i = 0; i < 3; i++) {
int flicker = random8(NUM_LEDS / 3);
leds[flicker] += CRGB(50, 25, 0);
}

delay(30);
}

// 彗星效果
void comet() {
static int cometPosition = 0;

// 淡出所有LED
fadeToBlackBy(leds, NUM_LEDS, 30);

// 绘制彗星头部 (最亮)
leds[cometPosition] = CHSV(gHue, 255, 255);

// 绘制彗星尾巴
for(int i = 1; i < 8; i++) {
int pos = cometPosition - i;
if(pos >= 0) {
leds[pos] = CHSV(gHue, 255, 255 - (i * 32));
}
}

EVERY_N_MILLISECONDS(50) {
cometPosition = (cometPosition + 1) % NUM_LEDS;
if(cometPosition == 0) {
gHue += 32; // 每次循环完成改变颜色
}
}
}

// === 辅助函数 ===

// 启动动画
void startupAnimation() {
// 从中间向两边展开
for(int i = 0; i <= NUM_LEDS / 2; i++) {
int left = (NUM_LEDS / 2) - i;
int right = (NUM_LEDS / 2) + i;

if(left >= 0) leds[left] = CRGB::Green;
if(right < NUM_LEDS) leds[right] = CRGB::Green;

FastLED.show();
delay(30);
}

// 彩虹扫描
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = CHSV(i * 8, 255, 255);
FastLED.show();
delay(20);
}

// 清空
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(500);
}

// 检查串口命令
void checkSerialCommands() {
if(Serial.available() > 0) {
String command = Serial.readString();
command.trim();

if(command.length() > 0) {
char cmd = command.charAt(0);

// 模式切换 (0-7)
if(cmd >= '0' && cmd <= '7') {
uint8_t newMode = cmd - '0';
if(newMode != currentMode) {
currentMode = newMode;
Serial.print("切换到模式: ");
Serial.println(newMode);
printModeName(newMode);
}
}
// 亮度设置 (b100)
else if(cmd == 'b' || cmd == 'B') {
int brightnessValue = command.substring(1).toInt();
if(brightnessValue >= 0 && brightnessValue <= 255) {
currentBrightness = brightnessValue;
FastLED.setBrightness(currentBrightness);
Serial.print("亮度设置为: ");
Serial.println(currentBrightness);
}
}
// 纯色模式颜色切换
else if(currentMode == MODE_SOLID) {
switch(cmd) {
case 'r': case 'R':
solidColor = CRGB::Red;
Serial.println("颜色: 红色");
break;
case 'g': case 'G':
solidColor = CRGB::Green;
Serial.println("颜色: 绿色");
break;
case 'b': case 'B':
solidColor = CRGB::Blue;
Serial.println("颜色: 蓝色");
break;
case 'w': case 'W':
solidColor = CRGB::White;
Serial.println("颜色: 白色");
break;
case 'y': case 'Y':
solidColor = CRGB::Yellow;
Serial.println("颜色: 黄色");
break;
case 'p': case 'P':
solidColor = CRGB::Purple;
Serial.println("颜色: 紫色");
break;
}
}
}
}
}

// 打印模式名称
void printModeName(uint8_t mode) {
switch(mode) {
case MODE_RAINBOW: Serial.println("彩虹循环"); break;
case MODE_THEATER: Serial.println("跑马灯"); break;
case MODE_CONFETTI: Serial.println("五彩纸屑"); break;
case MODE_SOLID: Serial.println("纯色"); break;
case MODE_BREATH: Serial.println("呼吸灯"); break;
case MODE_RAIN: Serial.println("下雨效果"); break;
case MODE_FIRE: Serial.println("火焰效果"); break;
case MODE_COMET: Serial.println("彗星效果"); break;
}
}

使用说明

  1. 上传代码

· 确保已正确安装 ESP32 开发板和 FastLED 库
· 选择正确的开发板(如 ESP32 Dev Module)和端口
· 点击上传

  1. 串口控制命令

打开串口监视器(波特率115200),发送以下命令:

模式切换:

· 0 - 彩虹循环
· 1 - 跑马灯
· 2 - 五彩纸屑
· 3 - 纯色模式
· 4 - 呼吸灯
· 5 - 下雨效果
· 6 - 火焰效果
· 7 - 彗星效果

亮度控制:

· b50 - 设置亮度为50
· b150 - 设置亮度为150
· b255 - 设置亮度为255(最亮)

纯色模式颜色切换:

· r - 红色
· g - 绿色
· b - 蓝色
· w - 白色
· y - 黄色
· p - 紫色

  1. 电源注意事项

30个WS2812灯珠全白最亮时功耗约 30 × 0.06A × 5V = 9W,建议使用外部5V电源供电,并将外部电源的GND与ESP32的GND连接。

这个代码提供了丰富的灯光效果和完整的控制功能,您可以通过串口实时切换模式和调整参数。

写在最后

本文篇用于记录本次WS2812B项目经过,如有不妥,请见谅。


WS2812B灯带项目
https://b.wihi.top/posts/addc03d1.html
作者
鸣心
发布于
2025年10月19日
许可协议