Page 1 of 1
Possible issue with WS2812 driver on pyboard-D
Posted: Wed Oct 30, 2019 9:03 pm
by mathieu
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)
Re: Possible issue with WS2812 driver on pyboard-D
Posted: Thu Oct 31, 2019 10:11 pm
by mathieu
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)
Re: Possible issue with WS2812 driver on pyboard-D
Posted: Fri Nov 01, 2019 11:02 am
by pythoncoder
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.
Re: Possible issue with WS2812 driver on pyboard-D
Posted: Fri Nov 01, 2019 1:06 pm
by mathieu
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.
Re: Possible issue with WS2812 driver on pyboard-D
Posted: Fri Nov 01, 2019 2:09 pm
by Roberthh
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).