完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
从某多平台花了15元钱买了一米长的WS2812B彩灯,用于我的Pico编程试验,这种灯的神奇之处在于只需一根信号线,能够控制串联在一起的30颗LED灯珠(好像能长达1024颗灯),实现各种彩灯效果。
接线非常简单,正极接5V(我的灯带只有1米长,用树莓派Pico供电并不吃力,如果比较长的灯带,需要额外电源),一端接地,树莓派GP15接信号线Din。灯带里面的Do不用管它,它实际上是Dout的意思,信号经过Din处理后,点亮那个灯,吃掉一些字节,再经过Dout出来,从而可以串联更多的灯。 官方文档《Raspberry Pi Pico Python SDK》里有一节介绍PIO控制WS2812灯的代码,直接抄过来,修改一下灯的个数,引脚编号PIN_NUM,代码虽然不理解,但程序可以马上运行。 # Example using PIO to drive a set of WS2812 LEDs. import array, time from machine import Pin import rp2 # Configure the number of WS2812 LEDs. NUM_LEDS = 30 PIN_NUM = 15 brightness = 0.2 @rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def ws2812(): T1 = 2 T2 = 5 T3 = 3 wrap_target() label("bitloop") out(x, 1) .side(0) [T3 - 1] jmp(not_x, "do_zero") .side(1) [T1 - 1] jmp("bitloop") .side(1) [T2 - 1] label("do_zero") nop() .side(0) [T2 - 1] wrap() # Create the StateMachine with the ws2812 program, outputting on pin sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM)) # Start the StateMachine, it will wait for data on its FIFO. sm.active(1) # Display a pattern on the LEDs via an array of LED RGB values. ar = array.array("I", [0 for _ in range(NUM_LEDS)]) ########################################################################## def pixels_show(): dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)]) for i,c in enumerate(ar): r = int(((c >> 8) & 0xFF) * brightness) g = int(((c >> 16) & 0xFF) * brightness) b = int((c & 0xFF) * brightness) dimmer_ar = (g<<16) + (r<<8) + b sm.put(dimmer_ar, 8) time.sleep_ms(10) def pixels_set(i, color): ar = (color[1]<<16) + (color[0]<<8) + color[2] def pixels_fill(color): for i in range(len(ar)): pixels_set(i, color) def color_chase(color, wait): for i in range(NUM_LEDS): pixels_set(i, color) time.sleep(wait) pixels_show() time.sleep(0.2) def wheel(pos): # Input a value 0 to 255 to get a color value. # The colours are a transition r - g - b - back to r. if pos < 0 or pos > 255: return (0, 0, 0) if pos < 85: return (255 - pos * 3, pos * 3, 0) if pos < 170: pos -= 85 return (0, 255 - pos * 3, pos * 3) pos -= 170 return (pos * 3, 0, 255 - pos * 3) def rainbow_cycle(wait): for j in range(255): for i in range(NUM_LEDS): rc_index = (i * 256 // NUM_LEDS) + j pixels_set(i, wheel(rc_index & 255)) pixels_show() time.sleep(wait) BLACK = (0, 0, 0) RED = (255, 0, 0) YELLOW = (255, 150, 0) GREEN = (0, 255, 0) CYAN = (0, 255, 255) BLUE = (0, 0, 255) PURPLE = (180, 0, 255) WHITE = (255, 255, 255) COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE) print("fills") for color in COLORS: pixels_fill(color) pixels_show() time.sleep(0.2) print("chases") for color in COLORS: color_chase(color, 0.01) print("rainbow") rainbow_cycle(0) 网上还有一个更精简的版本,便于慢慢理解程序的主要逻辑。 import array import utime import machine import rp2 NUM_LEDS = 30 @rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def ws2812(): T1 = 2 T2 = 5 T3 = 3 wrap_target() label("bitloop") out(x, 1) .side(0) [T3 - 1] jmp(not_x, "do_zero") .side(1) [T1 - 1] jmp("bitloop") .side(1) [T2 - 1] label("do_zero") nop() .side(0) [T2 - 1] wrap() # 建立状态机,设置输出针的编号 sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=machine.Pin(15)) # Start the StateMachine, it will wait for data on its FIFO. sm.active(1) # Display a pattern on the LEDs via an array of LED RGB values. ar = array.array("I", [0 for _ in range(NUM_LEDS)]) # Cycle colours. for i in range(4 * NUM_LEDS): for j in range(NUM_LEDS): r = j * 100 // (NUM_LEDS - 1) b = 100 - j * 100 // (NUM_LEDS - 1) if j != i % NUM_LEDS: r >>= 3 b >>= 3 ar[j] = r << 16 | b sm.put(ar, 8) utime.sleep_ms(20) # Fade out. for _ in range(24): for j in range(NUM_LEDS): ar[j] >>= 1 sm.put(ar, 8) utime.sleep_ms(50) 树莓派Pico控制WS2812b彩色灯珠 这里用到了PIO(Programmable IO )的概念,可以嵌入汇编语句,细节还有待后面进一步的学习。 还有一个状态机的概念,暂时也不太理解,没关系,先抄着慢慢学。 再来学习一下WS2812B的数据通讯协议,看用户手册,有这样一段话: 数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。像素点采用自动整形转发技术,使得该像素点的级联个数不受信号传送的限制,仅受限信号传输速度要求。可以看出,每经过一个像素点,吃掉24个二进制位,信号就是这样从头传到尾的。 这24个二进制位就是颜色的RGB值,不对,是GRB值,与电脑上常见的红绿蓝顺序有点不一样,所以可以在源代码里看到这样的写法: (g<<16) + (r<<8) + b 说明书中提到的主要特点:
|
|
|
|
只有小组成员才能发言,加入小组>>
3254 浏览 9 评论
2937 浏览 16 评论
3439 浏览 1 评论
8941 浏览 16 评论
4030 浏览 18 评论
1072浏览 3评论
556浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
550浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2285浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1843浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-5 10:23 , Processed in 1.146158 second(s), Total 49, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号