WS2812串行可控彩色LED灯珠

简 介: 利用ESP32中的硬件SPI控制WS2812的显示。使用了高频三极管9018 作为输出接口反向器,确定合适的电阻参数,验证了驱动方案的硬件和软件的可行性。

关键词 WS2812ESP32SPI

WS2812
目 录
Contents
芯片简介
工作原理
ESP32-SPI
ESP32中的硬件SPI
使用晶体管反向MOSI
产生控制波形
测试WS2812
实验总结
附加测试
提高SPI的波特率

 

§01 WS2812


  能集成LED光源 WS2812 通过简单的外部接口、特有的级联方案便于利用MCU完成多个LED控制,极大简化了LED控制接口。相比于传统的 单片机LED IO口复用控制方案 ,使用WS2812则更加的简介。

▲ 图1.1  灯珠控制闪烁

▲ 图1.1 灯珠控制闪烁

一、芯片简介

1、特点与优势

  • 在5050封装内集成有控制电路和RGB芯片,形成完整像素点控制;
  • 内置扫执行好整形电路,传递到级联下一节点时,不会产生信号失真累积效应;
  • 内置复位电路与掉电复位电路;
  • 每个RGB灯都有256亮度级别,可以形成 2 24 = 16777216 2^{24} = 16777216 224=16777216中颜色,刷新频率不低于400Hz;
  • 通过信号线完成端口级联;
  • 传输距离在5米之内,无需增加额外电路;
  • 在刷新频率30帧/秒中,低速模式下可以控制不少于512颗灯,高速模式下则超过1024颗灯;
  • 数据传输速率为800kbps;
  • 颜色一致性强,价格低;

▲ 图1.1.1 灯带点亮后的效果

▲ 图1.1.1 灯带点亮后的效果

2、应用

  • 全色彩模块;全色彩柔光灯带;
  • LED装饰灯带;室内、室外LED不规则显示屏;

3、管脚封装

▲ 图1.1.2 WS2812封装与管脚功能定义

▲ 图1.1.2 WS2812封装与管脚功能定义

二、工作原理

1、工作电压

  根据 WS2812 数据手册,它的工作电压范围在KaTeX parse error: Can't use function '\~' in math mode at position 6: + 3.5\̲~̲ + 5.3V,输入信号电压在工作电压VDD±0.5V范围内。三路LED的参数:

【表2-1-1 RGB 参数】

Emitting colorWavelength(nm)Luminous intensity(mcd)Current(mA)Voltage(V)
Red620-630550-700161.8-2.2
Green515-5301100-1400162.8~3.1
Blue465-475200-400163.0-3.4

2、控制协议

  WS2812的级联控制协议非常简单。通过一根信号线就可以进行串行异步信号发送。

  下面显示了四个WS2812通过数据性级联的方式。在串行通讯中使用不同高低电平脉冲表示数据0,1编码。
▲ 图1.2.1 级联方法与编码波形

▲ 图1.2.1 级联方法与编码波形

【221. 脉冲编码参数】

脉冲定义时间误差
T0H0 code ,high voltage time0.4us±150ns
T1H1 code ,high voltage time0.85us±150ns
T0L0 code , low voltage time0.85us±150ns
T1L1 code ,low voltage time0.4us±150ns
RESlow voltage timeAbove 50μs

  下面是三个WS2812级联发送过程对应的波形。可以看到通过发送三组24bit的编码,可以控制三个级联的WS2812灯的颜色。数据D1是直接由MCU数据端口控制,D2,D3,D4则是WS8212内部整形放大后再进行传输。

  使用RESET编码,也就是超过50us的低电平形成WS2812输出锁定。

▲ 图1.2.2 三个WS2812级联发送过程对应的波形

▲ 图1.2.2 三个WS2812级联发送过程对应的波形

  每组24bit对应的的GRB编码如下所示。发送颜色顺序为GRB,字节的高位在前。

▲ 图1.2.3 每组24bit对应的的GRB编码

▲ 图1.2.3 每组24bit对应的的GRB编码

▲ 图1.1.3 灯带点亮后的效果

▲ 图1.1.3 灯带点亮后的效果

 

§02 ESP32-SPI


  于控制WS2812的脉冲高低电平在0.85us,0.4us,时间间隔,为了产生这样的脉冲,使用普通的软件控制IO口是无法完成的,下面测试使用其中的 硬件SPI 产生控制脉冲信号。

一、ESP32中的硬件SPI

  在ESP32中具有两路硬件SPI端口,可以最快达到始终速率80MHz,这可以满足对WS2812的控制脉冲的速率。

1、SPI缺省管脚

  如果使用SPI缺省配置管脚,输出速率可以达到80MHz,如果使用其它GPIO,则输出的速率则需要限制在40MHz以下。

【表2-1-1 ESP32 硬件SPI缺省端口】

管脚HSPI(id=1)HSPI(id=2)
SCK1418
MOSI1323
MISO1219

2、ESP32实验转接板

  利用 ESP32实验转接板 ,测试硬件SPI端口。

▲ 图2.1.1  ESP32实验转接板

▲ 图2.1.1 ESP32实验转接板

  使用SPI id=1,对应的SPI,MOSI,MISO的对口为,14,13,12,对应的实验转接板上的输出管脚如下图所示,从右往左分别是:

ESP32转接板SPI管脚定义:
SCK:PIN9
MISO:PIN8
MOSI:PIN7

▲ 图2.1.2 ESP32中对应的SPI,MOSI,MISO的管脚

▲ 图2.1.2 ESP32中对应的SPI,MOSI,MISO的管脚

3、测试SPI输出波形

  初始化SPI端口,使得输出速率为10MHz,输出数据0x55,0xaa,使用示波器观察MOSI,SPI波形。

(1)测试缺省SPI模式
from machine                import Pin,Timer,SPI
import time

hspi = SPI(1, 10000000, sck=Pin(14), mosi=Pin(13), miso=Pin(12))

buf = bytes((0x55,0xaa))
print(buf)

while True:
    hspi.write(buf)
    time.sleep_ms(10)

  通过测试波形可以看到输出SPI的频率为5MHz。SPI正常的电平为低电平。
▲ 图2.1.3 测量SPI,MOSI的输出波形

▲ 图2.1.3 测量SPI,MOSI的输出波形

  设置输出的波特率为2.5MHz,此时便可以输出 0.4us 的低脉冲。

  设置输出波特率为2.5MHz,可以产生所需要的0.4us的电平输出。波形如下图所示:

▲ 图2.1.4 设置输出波特率为2.5MHz,可以产生所需要的0.4us的电平输出

▲ 图2.1.4 设置输出波特率为2.5MHz,可以产生所需要的0.4us的电平输出

二、使用晶体管反向MOSI

  使用晶体管将MOSI波形进行反向,这可以:

  • 能够满足WS2812控制脉冲电平极性要求。它要求控制信号在平时为高电平,通过低电平脉冲获得复位信号、0/1数据位信号。
  • 提高带载能力。

1、信号反向电路

▲ 图2.2.1 MOSI信号反向电路

▲ 图2.2.1 MOSI信号反向电路

2、电路测试

(1)晶体管BC547

  由于BC547B的截止频率只有300MHz,信号通过BC547之后,引起了很大的失真。下图显示了信号波形。

▲ 图2.2.2 MOSI 输入输出信号

▲ 图2.2.2 MOSI 输入输出信号

(2)晶体管9018

  为了提高响应速度,对电路进行如下的调整:

电路元器件参数:
Q1:9018
R1:10k
R2:200

▲ 图2.2.3  电路参数修改之后输入输出波形

▲ 图2.2.3 电路参数修改之后输入输出波形

三、产生控制波形

1、产生RESET信号

  根据WS2812控制信号协议,RESET是时长超过50us的低电平,因此,在2.5MHz的波特率下,连续输出125bit的高电平,也就是16个byte的0xff,则可以产生: 16 × 8 = 128 16 \times 8 = 128 16×8=128个1输出,便可以产生 128 × 0.4 = 51.2 μ s 128 \times 0.4 = 51.2\mu s 128×0.4=51.2μs的低电平。

from machine                import Pin,Timer,SPI
import time

hspi = SPI(1, 2500000, sck=Pin(14), mosi=Pin(13), miso=Pin(12),
           polarity=0)

buf = bytes([0xff]*16)
print(buf)

while True:
    hspi.write(buf)
    time.sleep_ms(10)

▲ 图2.3.1 连续输出16个0xff所产生的RESET信号

▲ 图2.3.1 连续输出16个0xff所产生的RESET信号

2、产生RGB数据

  根据WS2812协议,每一组RGB需要24个bit,每个bit可以有SPI输出的3个bit来表示,因此输出一组RGB数据,则需要SPI输出 24 × 3 = 72 b i t s = 9 b y t e s 24 \times 3 = 72bits = 9bytes 24×3=72bits=9bytes

  由于存在MOSI输出反向,所以对应的RGB输出的高低电平需要进行反相。

RGB的0,1bit对应SPI:
RGB-0:SPI-011
RGB-1:SPI-001
(1)转换代码
from machine                import Pin,Timer,SPI
import time

hspi = SPI(1, 2500000, sck=Pin(14), mosi=Pin(13), miso=Pin(12),
           polarity=0)

def byte2bin(b):
    bstr = bin(b)[2:]
    return '0'*(8-len(bstr)) + bstr

def rgb2byte(r,g,b):
    str = byte2bin(g) + byte2bin(r) + byte2bin(b)
    spistr = ''.join([(lambda s: '011' if s=='0' else '001')(x) for x in str])
    rgbdim = [int(spistr[i*8:i*8+8], 2) for i in range(9)]
    return bytes(rgbdim)

rgbbyte = rgb2byte(0xff,0x80,0x3f)
print(rgbbyte)

rstbyte = bytes([0xff]*16)
outbyte = rstbyte+rgbbyte

while True:
    hspi.write(outbyte)
    time.sleep_ms(10)
(2)输出波形

  输出RGB分别为:0xff, 0x80, 0x3f,对应的数据波形为:

▲ 图2.3.2 带有一个RST信号的一组RGB波形

▲ 图2.3.2 带有一个RST信号的一组RGB波形

  将RGB对应的输出脉冲展开后的波形,可以检查输出波形是否符合WS2812对应的控制信号协议。

▲ 图2.3.3 将RGB对应的输出脉冲展开后的波形

▲ 图2.3.3 将RGB对应的输出脉冲展开后的波形

四、测试WS2812

1、波形失真

  编程输出RGB为(0xff,0x0,0x0),对应WS2812应该是输出红色,但直接接入之后,WS2812输出为白色。

  通过观察DI的波形,可以看到它处于高电平的时间超过400us,并且低电平大约为1.5V。这说明Q1的驱动不足。

▲ 图2.4.1 DI波形以及对应的WS2812颜色

▲ 图2.4.1 DI波形以及对应的WS2812颜色

2、降低R1的阻值

  降低R1阻值,提高Q1响应时间,以及输出低电平降低。最后将R1的阻值更换成3.3k欧姆之后,D1波形有了改善,此时WS2812的颜色与设置的参数相符了。

▲ 图2.4.2 DI波形以及对应的WS2812颜色

▲ 图2.4.2 DI波形以及对应的WS2812颜色

▲ 图2.4.3 最终对应的电路图中的参数

▲ 图2.4.3 最终对应的电路图中的参数

3、RGB转换颜色

  编程依次输出RGB颜色。

from machine                import Pin,Timer,SPI
import time

hspi = SPI(1, 2500000, sck=Pin(14), mosi=Pin(13), miso=Pin(12),
           polarity=0)

def byte2bin(b):
    bstr = bin(b)[2:]
    return '0'*(8-len(bstr)) + bstr

def rgb2byte(r,g,b):
    str = byte2bin(g) + byte2bin(r) + byte2bin(b)
    spistr = ''.join([(lambda s: '011' if s=='0' else '001')(x) for x in str])
    rgbdim = [int(spistr[i*8:i*8+8], 2) for i in range(9)]
    return bytes(rgbdim)

rgbbyte = rgb2byte(0xff,0x0,0x0)
rstbyte = bytes([0xff]*16)
outbyte = rstbyte+rgbbyte+rstbyte

while True:
    rgbbyte = rgb2byte(0xff,0x0,0x0)
    outbyte = rstbyte+rgbbyte+rstbyte
    hspi.write(outbyte)
    time.sleep_ms(500)

    rgbbyte = rgb2byte(0x0,0xff,0x0)
    outbyte = rstbyte+rgbbyte+rstbyte
    hspi.write(outbyte)
    time.sleep_ms(500)

    rgbbyte = rgb2byte(0x0,0x0,0xff)
    outbyte = rstbyte+rgbbyte+rstbyte
    hspi.write(outbyte)
    time.sleep_ms(500)

  下面显示了WS2812在SPI输出波形控制下完成颜色的转换。
▲ 图2.4.4  RGB转换颜色

▲ 图2.4.4 RGB转换颜色

 

验总结 ※


  用ESP32中的硬件SPI输出脉冲波形,控制WS2812响应。

  通过电路调整,选择了高频晶体管9018 作为输出反向晶体管,确定了放大电路参数,测试验证了利用高速SPI控制WS2812的硬件电路和软件。

一、附加测试

1、R2阻值

增加R2的阻值,可以进一步降低输出MOSI的低电平,但是减缓了上升时间,但是控制信号依然可以工作。

▲ 图3.1 更换R2(430欧姆)之后对应的输出波形

▲ 图3.1 更换R2(430欧姆)之后对应的输出波形

2、增加加速电容

▲ 图3.1.2 增加加速电容

▲ 图3.1.2 增加加速电容

▲ 图3.1.3 增加加速电容之后的波形

▲ 图3.1.3 增加加速电容之后的波形

二、提高SPI的波特率

提高SPI的波特率,可以提高设置颜色的准确率。

from machine                import Pin,Timer,SPI
import time

hspi = SPI(1, 3000000, sck=Pin(14), mosi=Pin(13), miso=Pin(12),
           polarity=0)

def byte2bin(b):
    bstr = bin(b)[2:]
    return '0'*(8-len(bstr)) + bstr

def rgb2byte(r,g,b):
    str = byte2bin(g) + byte2bin(r) + byte2bin(b)
    spistr = ''.join([(lambda s: '011' if s=='0' else '001')(x) for x in str])
    rgbdim = [int(spistr[i*8:i*8+8], 2) for i in range(9)]
    return bytes(rgbdim)

rgbbyte = rgb2byte(0xff,0x0,0x0)
rstbyte = bytes([0xff]*16)
outbyte = rstbyte+rgbbyte+rstbyte

hspi.write(outbyte)

while True:

    str = [int(s, 16) for s in input('Input RGB\n').split()]
    print(str)
    rgbbyte = rgb2byte(str[0], str[1], str[2])
    outbyte = rstbyte+rgbbyte+rstbyte

    hspi.write(outbyte)
    hspi.write(outbyte)

    time.sleep_ms(10)


■ 相关文献链接:

● 相关图表链接:

  • 24
    点赞
  • 126
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: 要实现控制ws2812灯珠实现流星效果,我们可以使用Arduino来编写代码和控制。下面是一个简单的实现流程: 首先,我们需要连接ws2812灯珠到Arduino板上。将VCC引脚连接到Arduino的5V引脚,GND引脚连接到Arduino的GND引脚,将DI引脚连接到Arduino的数字引脚,例如D2。 接下来,在Arduino IDE中编写程序。首先,我们需要包含“Adafruit_NeoPixel”库,这是一个用于控制ws2812灯珠的库。 然后,我们需要定义灯珠的数量和引脚。使用“Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, PIN, NEO_GRB + NEO_KHZ800);”来初始化灯珠。 接下来,我们需要在“setup”函数中设置引脚模式和数量。使用“strip.begin();”来初始化灯珠。 然后,在“loop”函数中编写流星效果的代码。我们可以使用for循环控制灯珠的数量,并在每个迭代中通过“strip.setPixelColor(i, strip.Color(255, 255, 255));”来设置灯珠的颜色。然后,我们可以使用“strip.show();”来将颜色应用到灯珠上。 在每个迭代之间,我们可以使用“strip.setPixelColor(i, strip.Color(0, 0, 0));”来将灯珠颜色设置为黑色,以模拟流星移动的效果。可以通过增加延迟来调整流星移动的速度。 最后,我们可以在Arduino上上传代码,灯珠就会展示流星效果了。 需要注意的是,这只是一个简单的流星效果的实现方法。如果想要更复杂的效果,可以在代码中做更多的调整和改进。 ### 回答2: 要实现流星效果,可以通过Arduino控制WS2812灯珠来实现。首先,我们需要将WS2812灯珠与Arduino连接起来。通过连接DI(Digital Input)引脚和5V、GND引脚,将WS2812灯珠与Arduino连接在一起。 接下来,我们需要通过编写代码来实现流星效果。首先,在Arduino中安装FastLED库,该库可以帮助我们更方便地对WS2812灯珠进行控制。 然后,我们需要定义一些变量来控制流星的行为,比如流星的起始位置、流星的速度、流星的长度等。在Arduino的setup函数中,我们可以初始化这些变量,同时设置WS2812灯珠的数量和引脚。 在Arduino的loop函数中,我们可以使用FastLED库提供的函数来控制WS2812灯珠的亮度和颜色。通过循环遍历每个灯珠,我们可以逐渐改变流星的位置和亮度,从而实现流星效果。我们可以通过改变流星的起始位置和速度来控制流星的移动方向和速度。 为了实现流星的效果,我们还可以使用一些特殊的算法,比如渐变亮度、尾巴效果等。通过增加尾巴效果,可以让流星在移动过程中留下一道模糊的尾巴,增加流星的真实感。 最后,通过将Arduino连接到电源,我们可以看到WS2812灯珠闪烁起来,模拟出流星落下的效果。通过调整代码中的参数,我们还可以改变流星的颜色、长度和速度,实现不同的流星效果。 总之,通过使用Arduino控制WS2812灯珠,并结合合适的代码和算法,我们可以轻松实现流星效果。这种效果可以应用于各种场景,比如舞台表演、节日布置等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卓晴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值