Possible issue with WS2812 driver on pyboard-D

The official PYBD running MicroPython, and its accessories.
Target audience: Users with a PYBD
Post Reply
User avatar
mathieu
Posts: 88
Joined: Fri Nov 10, 2017 9:57 pm

Possible issue with WS2812 driver on pyboard-D

Post by mathieu » Wed Oct 30, 2019 9:03 pm

The example code from <https://github.com/JanBednarik/micropython-ws2812> produces the expected result on a pyboard 1.1, but the same code on my pyboard-D lights up the whole LED strip in white, and I'm unable to change any LED. SPI 1 and 2 behave in exactly the same way.

Has someone noticed this before, or is it an issue on my end?

Code: Select all

from ws2812 import WS2812
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)

User avatar
mathieu
Posts: 88
Joined: Fri Nov 10, 2017 9:57 pm

Re: Possible issue with WS2812 driver on pyboard-D

Post by mathieu » Thu Oct 31, 2019 10:11 pm

Replying to my own thread: I was able to fix the issue by replacing, in the ws2812 module,

Code: Select all

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

Code: Select all

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

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Possible issue with WS2812 driver on pyboard-D

Post by pythoncoder » Fri Nov 01, 2019 11:02 am

Does this work?

Code: Select all

self.spi = pyb.SPI(spi_bus, pyb.SPI.MASTER, baudrate=6400000, polarity=0, phase=0)
It would be good to know if the fix is down to the baudrate change or separating initialisation from instantiation.
Peter Hinch
Index to my micropython libraries.

User avatar
mathieu
Posts: 88
Joined: Fri Nov 10, 2017 9:57 pm

Re: Possible issue with WS2812 driver on pyboard-D

Post by mathieu » Fri Nov 01, 2019 1:06 pm

pythoncoder wrote:
Fri Nov 01, 2019 11:02 am
It would be good to know if the fix is down to the baudrate change or separating initialisation from instantiation.
Just checked and the single-line declaration also works. This must be linked to the approximate baudrate (see http://docs.micropython.org/en/v1.9.3/p ... b.SPI.html). Another reason to prefer SK9822 or APA102 leds (which can be driven through regular SPI) over WS2812, I guess.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Possible issue with WS2812 driver on pyboard-D

Post by Roberthh » Fri Nov 01, 2019 2:09 pm

I checked that with my simple WS2812 driver below. Yes. The problem is, that the granularity of the SPI timing is not sufficient. At 3200000, the bit time is ~500ns, at 3800000 the bit time decreases to 250 ns.

Code: Select all

from machine import SPI, disable_irq, enable_irq
from time import sleep, sleep_us

def send_spi(data, spi):
    no_pixel = len(data)
    buffer = bytearray(no_pixel * 3 * 3)
    index = 0
    for pixel in data:
        for byte in pixel:
            bits = 0
            mask = 0x80
            while mask:
                bits <<= 3
                if byte & mask:
                    bits |= 0x06
                else:
                    bits |= 0x04
                mask >>= 1
            buffer[index] = (bits >> 16) & 0xff
            buffer[index + 1] = (bits >> 8) & 0xff
            buffer[index + 2] = (bits) & 0xff
            index += 3
    sleep_us(60)  # ensure initial reset
    state = disable_irq()
    spi.write(buffer)
    enable_irq(state)

def run(rate = 3200000):

    data = 6 * [
        (85, 0, 0),    # green
        (0, 85, 0),    # red
        (0, 0, 85),    # blue
        (85, 85, 85),   # white
        ]

    print(data)
    blank = 24 * [(0, 0, 0)]
    spi = SPI(1, baudrate=rate, polarity=0, firstbit=SPI.MSB, bits=8)

    for _ in range(5):
        send_spi(data, spi)
        sleep(1)
        send_spi(blank, spi)
        sleep(1)
edit: That was at a clock rate of 120 Mhz. Setting the clock to 192 Mhz got a better match to 3200000 baud (2940000).

Post Reply