分享

MicroPython之 炫彩跑马灯(TPYBoard V10X系列教程28)

 长沙7喜 2018-01-18


 

实验器材

TPYBoard v102 1

ws2812b RGB-Ring-8 1

micro USB数据线 1

杜邦线 若干


WS2812B介绍

     WS2812B是一个集控制电路与发光电路于一体的智能外控LED光源。 其外型与一个5050LED灯珠相同, 每个元件即为一个像素点。像素点内部包含了智能数字接口数据锁存信号整形放大驱动电路, 还包含有高精度的内部振荡器和可编程定电流控制部分, 有效保证了像素点光的颜色高度一致。

数据协议采用单线归零码的通讯方式, 像素点在上电复位以后, DIN端接受从控制器传输过来的数据, 首先送过来的24bit数据被第一个像素点提取后, 送到像素点内部的数据锁存器, 剩余的数据经过内部整形处理电路整形放大后通过DO端口开始转发输出给下一个级联的像素点, 每经过一个像素点的传输, 信号减少24bit。像素点采用自动整形转发技术, 使得该像素点的级联个数不受信号传送的限制, 仅仅受限信号传输速度要求。

 

实物图

 

上图是8个灯珠的。

WS2812B引脚说明

管脚名

功能描述

5V

供电引脚,输入5V

GND

电源接地

DOUT(DO)

信号输出

DIN(DI)

数据信号输入


硬件连接

TPYBoard v102WS2812B的接线示意图,如下:

TPYBoard v102

WS2812B

VIN

5V

GND

GND

X7(MISO SPI1)

DO

X8(MOSI SPI1)

DI


程序源码如下:

import pyb

import math

 

from ws2812 import WS2812

 

 

ring = WS2812(spi_bus=1, led_count=8, intensity=0.1)

 

 

def data_generator(led_count):

    data = [(0, 0, 0) for i in range(led_count)]

    step = 0

    while True:

        red = int((1 + math.sin(step * 0.1324)) * 127)

        green = int((1 + math.sin(step * 0.1654)) * 127)

        blue = int((1 + math.sin(step * 0.1)) * 127)

        data[step % led_count] = (red, green, blue)

        yield data

        step += 1

 

 

for data in data_generator(ring.led_count):

    ring.show(data)

    pyb.delay(100)

 

里面还需要引入一个ws2812.py 文件。内容如下:

import gc

import pyb

 

 

class WS2812:

    '''

    Driver for WS2812 RGB LEDs. May be used for controlling single LED or chain

    of LEDs.

 

    Example of use:

 

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

        data = [

            (255, 0, 0),    # red

            (0, 255, 0),    # green

            (0, 0, 255),    # blue

            (85, 85, 85),   # white

        ]

        chain.show(data)

 

    Version: 1.0

    '''

    buf_bytes = (0x11, 0x13, 0x31, 0x33)

 

    def __init__(self, spi_bus=1, led_count=1, intensity=1):

        '''

        Params:

        * spi_bus = SPI bus ID (1 or 2)

        * 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, pyb.SPI.MASTER, baudrate=3200000, polarity=0, phase=1)

 

        # turn LEDs off

        self.show([])

 

    def show(self, data):

        '''

        Show RGB data on LEDs. Expected data = [(R, G, B), ...] where R, G and B

        are intensities of colors in range from 0 to 255. One RGB tuple for each

        LED. Count of tuples may be less than count of connected LEDs.

        '''

        self.fill_buf(data)

        self.send_buf()

 

    def send_buf(self):

        '''

        Send buffer over SPI.

        '''

        self.spi.send(self.buf)

        gc.collect()

 

    def update_buf(self, data, start=0):

        '''

        Fill a part of the buffer with RGB data.

 

        Order of colors in buffer is changed from RGB to GRB because WS2812 LED

        has GRB order of colors. Each color is represented by 4 bytes in buffer

        (1 byte for each 2 bits).

 

        Returns the index of the first unfilled LED

 

        Note: If you find this function ugly, it's because speed optimisations

        beated purity of code.

        '''

 

        buf = self.buf

        buf_bytes = self.buf_bytes

        intensity = self.intensity

 

        mask = 0x03

        index = start * 12

        for red, green, blue in data:

            red = int(red * intensity)

            green = int(green * intensity)

            blue = int(blue * intensity)

 

            buf[index] = buf_bytes[green >> 6 & mask]

            buf[index+1] = buf_bytes[green >> 4 & mask]

            buf[index+2] = buf_bytes[green >> 2 & mask]

            buf[index+3] = buf_bytes[green & mask]

 

            buf[index+4] = buf_bytes[red >> 6 & mask]

            buf[index+5] = buf_bytes[red >> 4 & mask]

            buf[index+6] = buf_bytes[red >> 2 & mask]

            buf[index+7] = buf_bytes[red & mask]

 

            buf[index+8] = buf_bytes[blue >> 6 & mask]

            buf[index+9] = buf_bytes[blue >> 4 & mask]

            buf[index+10] = buf_bytes[blue >> 2 & mask]

            buf[index+11] = buf_bytes[blue & mask]

 

            index += 12

 

        return index // 12

 

    def fill_buf(self, data):

        '''

        Fill buffer with RGB data.

 

        All LEDs after the data are turned off.

        '''

        end = self.update_buf(data)

 

        # turn off the rest of the LEDs

        buf = self.buf

        off = self.buf_bytes[0]

        for index in range(end * 12, self.buf_length):

            buf[index] = off

            index += 1

 

本次参考的github上的一个项目。项目地址:

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

给大家看一下效果(额 最后一个灯珠坏了 大家可以自行忽略……)

 

https://v.qq.com/x/page/d05297wxo1b.html

 

本次实验用的是8个灯珠,大家可以尝试更多用更多灯珠的,或者买灯带,那样呈现的效果会更酷、更炫!

 




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多