这个部分中笔者将使用ESP32的RMT功能控制WS2812/11灯带。
WS2811芯片实现了上述功能。WS2812led灯珠为内置了2811芯片的RGB灯珠。
一些灯带用一个WS2811芯片驱动3个普通5050RGB灯珠,而另一些全部使用了集成了芯片的WS2812灯珠。WS2812灯条都为5v供电,芯片驱动版本的灯带有12v供电版本。
如上所说,WS2812芯片依靠一个信号线控制上百个LED的颜色,这是如何实现的呢?
每个LED的信号有24位,由R,G,B各八位组成。每个数据位的高低由信号引脚的波形决定:
T0H,T0L,T1H,T1L的时间值由具体的芯片决定,具体请参考worldsemi网站的技术手册。
当发送多个led的数据时,每个芯片都会吞掉最前面的24位数据。两个数据帧之间需要间隔280微秒以上。
为了接入wifi,这个项目使用ESP32作为灯带控制器和MQTT网关。笔者使用的是arduino-ide的开发环境(关于如何在arduino-ide或类似环境中开发esp32)。
控制WS2812/11的arduino库有WS2812FX和NeoPixelBus,但是它们都不支持ESP32硬件。好在esp32有内置的RMT库专门用来输出数字波形,并且提供了控制ws2812的范例程序(arduinoIDE-文件-示例-esp32-RMT-RMTWriteNeoPixel)。
//设置led数量,声明rmt对象。
#define NR_OF_LEDS 50
#define NR_OF_ALL_BITS (24*NR_OF_LEDS)
//rmt数据
rmt_data_t led_data[NR_OF_ALL_BITS];
//rmt对象
rmt_obj_t* rmt_send = NULL;
//每一个led的颜色状态。
uint8_t allColor[NR_OF_LEDS][3];
//初始化rmt对象
//18:针脚,true:输出或输入,RMT_MEM_64:内存数量
if ((rmt_send = rmtInit(18, true, RMT_MEM_64)) == NULL){
Serial.println("init sender failed\n");
}
//设置rmt的时间单位,这里为100ns,返回实际设置的时间单位。
float realTick = rmtSetTick(rmt_send, 100);
Serial.printf("real tick set to: %fns\n", realTick);
int led, col, bit;
int i = 0;
for (led = 0; led < NR_OF_LEDS; led++) {
for (col = 0; col < 3; col++ ) {
for (bit = 0; bit < 8; bit++) {
//位为1时。
if (allColor[led][col] & (1 << (8 - bit))) {
//先输出高电平
led_data[i].level0 = 1;
//高电平输出时间为8*100ns=0.8微秒
led_data[i].duration0 = 8;
//再输出低电平
led_data[i].level1 = 0;
//低电平输出时间为4*100ns=0.4微秒
led_data[i].duration1 = 4;
} else {
//位为0时。
led_data[i].level0 = 1;
led_data[i].duration0 = 4;
led_data[i].level1 = 0;
led_data[i].duration1 = 8;
}
i++;
}
}
}
//输出的目标波形。
// "0":
// +-------+ +--
// | | |
// | | |
// | | |
// ---| |--------------|
// + + +
// | 0.4us | 0.8us |
//
// "1":
// +-------------+ +--
// | | |
// | | |
// | | |
// | | |
// ---+ +-------+
// | 0.8us | 0.4us |
//输出波形
rmtWrite(rmt_send, led_data, NR_OF_ALL_BITS);
注意:只要没有关闭电源,WS2812/2811芯片会保存颜色输出状态。因此只有需要改变灯带状态时,esp32才需要重新输出控制数据。
注意:esp32的一些引脚无法使用rmt功能,运行时会出现缓存读取错误。
如果ESP32板上没有5v-3.3V线性电源则请自行添加。
另外,一些WS2812/11灯带需要5V控制电平,不支持ESP32 3.3V的控制电平。请添加三极管升压电路或者用高低电平转换模块解决。
如果使用12v的灯带和电源还需添加降压模块给esp32供电。
建议当灯带长度超过5米时建议每5米分别供电,不然后面的灯带会有较大的压降。另外灯带最后可添加稳压电容。
第二部分:https://blog.csdn.net/CharlieZ8/article/details/88044235
第三部分:https://blog.csdn.net/CharlieZ8/article/details/88096061