基于Pico和MicroPython点亮ws2812彩色灯带

基于Pico和MicroPython点亮ws2812彩色灯带

Introduction

点亮发光的LED灯是简单有趣的实验,点亮多个ws2812小灯串联起来的灯带,可对多个彩色小灯进行编程,从而实现各种有趣的显示效果。多个ws2812使用串联的方式级联在一起,微控制器以发出长短脉冲的序列控制彩色小灯显示的颜色和亮度。

此处略过控制ws2812发光的原理和控制方法,直接动手实验,讲述基于Pico电路板和MicroPython点亮ws2812彩色灯带的学习、调试和操作过程。调试过程中,使用了来自电子森林的Step-Pico电路板,同树莓派官方的RPI Pico电路板兼容,但换用了Type-C插座、新增了复位按键,以及4个ws2812彩灯级联起来的灯带,实际使用起来更加方便。

在这里插入图片描述

Step Pico上连接ws2812彩灯部分的原理图

Practice

在网上搜索到比较靠谱的关于使用MicroPython点亮ws2812彩灯的资料,大多来自于github上的micropythno-ws2812项目:

  • https://github.com/JanBednarik/micropython-ws2812

对于访问github不便的开发者,笔者在国内的gitee开源代码站点上做了个镜像(https://gitee.com/suyong_yq/micropython-ws2812),方便获取源码。如图x所示。

在这里插入图片描述

图x 在开源站点上的micropython-ws2812项目

这个项目基于早期使用STM32微控制器的pyb电路板开发,估计也能兼容Pico板子上的MicroPython,其中提供了一些有趣的用例。按照说明,开发者需要先将ws2812.py文件导入到MicroPython中,此处导入到Pico板子上的/lib目录下。如图x所示。

在这里插入图片描述

图x 导入ws2812b.py到Pico上的MicroPython

然后,运行代码仓库提供的用例:

from ws2812 import WS2812

ring = WS2812(spi_bus=1, led_count=4)

data = [
    (24, 0, 0),
    (0, 24, 0),
    (0, 0, 24),
    (0, 0, 0),
]

ring.show(data)

试运行时,发现报错:

>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "/lib/ws2812.py", line 45, in __init__
AttributeError: type object 'SPI' has no attribute 'MASTER'

在Pico的REPL中查看MicroPython的SPI类属性,发现确实没有MASTER这个属性。

>>> import machine
>>> dir(machine)
['__class__', '__name__', 'ADC', 'I2C', 'I2S', 'PWM', 'PWRON_RESET', 'Pin', 'RTC', 'SPI', 'Signal', 'SoftI2C', 'SoftSPI', 'Timer', 'UART', 'USBDevice', 'WDT', 'WDT_RESET', '__dict__', 'bitstream', 'bootloader', 'deepsleep', 'dht_readinto', 'disable_irq', 'enable_irq', 'freq', 'idle', 'lightsleep', 'mem16', 'mem32', 'mem8', 'reset', 'reset_cause', 'soft_reset', 'time_pulse_us', 'unique_id']
>>> from machine import SPI
>>> dir(SPI)
['__class__', '__name__', 'read', 'readinto', 'write', 'LSB', 'MSB', '__bases__', '__dict__', 'deinit', 'init', 'write_readinto']
>>> 

ws2812.py文件在初始化spi设备时确实使用了MASTER属性。

# SPI init
self.spi = pyb.SPI(spi_bus, pyb.SPI.MASTER, baudrate=3200000, polarity=0, phase=1)

猜测,这可能是MicroPython版本更新导致的问题,也可能是MicroPython在不同芯片的跨平台设计的问题。

在寻找新的代码之前,我想先试着人工修复一下。毕竟当前的ws2812.py文件已经把控制逻辑的框架都写好了,只要结合当前的驱动重新做下适配就好。

试着移除pyb.SPI.MASTER的参数,再运行。还有报错:

>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "/lib/ws2812.py", line 48, in __init__
  File "/lib/ws2812.py", line 57, in show
  File "/lib/ws2812.py", line 63, in send_buf
AttributeError: 'SPI' object has no attribute 'send'

试着将send换成write,再运行。这个时候已经不报错了。但板子上的ws2812b彩灯也没亮。

猜测,可能引脚没对上,板子上用GPIO23接入灯带,但用例中没有指定SPI_SOUT信号使用的引脚。查一下运行程序后GPIO23引脚的状态:

>>> machine.Pin(23)
Pin(GPIO23, mode=ALT, pull=PULL_DOWN, alt=31)

此处为未配置alt=31。但后续实验成功的情况下,GPIO32引脚的复用功能应为SPI:

>>> machine.Pin(23)
Pin(GPIO23, mode=ALT, alt=SPI)

同时,经过比对原理图发现,当前板子上接入灯带使用的GPIO23引脚未接入扩展引脚,也就意味着这肯定也不是默认的SPI输出引脚(默认的引脚一定是外接到板子的扩展插针上方便开发者接线)。此时,有两个思路:

  • 在当前软件框架下,试着设定使用GPIO23作为某个硬件SPI模块的输出脚
  • 再找找别的ws2812的库,可以指定控制引脚信号的

在试第一条路的阶段,竟然直接走通了。

在实例化WS2812对象的实例化函数的参数列表里,加入一个指定输出控制引脚的参数。然后在实例化函数内部实例化SPI模块实例的时候,指定mosi参数为传入引脚。为此,有改动如下:

ws2812.py文件中,有:

    def __init__(self, spi_bus=1, pin=23, led_count=1, intensity=1):
        """
        Params:
        * spi_bus = SPI bus ID (0, 1 or 2)
        * pin = output pin to ws2812, mosi of spi
        * led_count = count of LEDs
        * intensity = light intensity (float up to 1)
        """
        self.led_count = led_count
        self.intensity = intensity

        # prepare SPI data buffer (4 bytes for each color)
        self.buf_length = self.led_count * 3 * 4
        self.buf = bytearray(self.buf_length)

        # SPI init
        self.spi = pyb.SPI(spi_bus, baudrate=3200000, polarity=0, phase=1, mosi=pyb.Pin(pin, pyb.Pin.OUT))

此处指定默认使用GPIO23引脚连接灯带,并在实例化SPI对象时,设定mosi的引脚为输出Pin.OUT

然后,main.py文件中实例化WS2812对象时,传入GPIO23引脚的参数:

ring = WS2812(spi_bus=1, pin=23, led_count=4)

运行,有报错信息:

>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "/lib/ws2812.py", line 46, in __init__
ValueError: bad MOSI pin

猜测,可能硬件spi_bus=1可能没有映射到GPIO23的信号。换用spi_bus=0,再试试看:

ring = WS2812(spi_bus=0, pin=23, led_count=4)

运行竟然成功了。没有报错,板子上的ws2812小灯也都亮起来了。Bingo !!!

在这里插入图片描述

图x 点亮ws2812灯带实验

Conclusion

在github上开源的micropython-ws2812项目的基础上,新增了指定SPI_SOUT引脚的实例化参数,实现了基于Pico电路板和MicroPython点亮ws2812b彩色灯带的效果。调试过程在Step Pico电路板上验证成功。

  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值