tinygo-org / pio

Programmable I/O API for RP2040.
BSD 3-Clause "New" or "Revised" License
21 stars 0 forks source link

PICO PIO testing with WS2812B #5

Closed Gustavomurta closed 4 months ago

Gustavomurta commented 12 months ago

Congratulations Patricio! I've already managed to do some tests on the Raspberry Pico with the WS281B example. Thank you. https://github.com/tinygo-org/pio/tree/main/rp2-pio/examples/ws2812

But I found some things that need correction or change.

ws, err := piolib.NewWS2812(sm, ws2812Pin, 16000000)

This function lacked the definition of the Baud rate. Through testing, I discovered the frequency of 16MHz (maybe it is based on Arduino?). func NewWS2812(sm pio.StateMachine, pin machine.Pin, baud uint32) (*WS2812, error)

The color sequence appears to be incorrect. Based on the WS2812B datasheet, we can verify that the color sequence in the 24 bits is green-red-blue and not RGB. https://cdn-shop.adafruit.com/datasheets/WS2812.pdf

image

https://github.com/tinygo-org/pio/blob/main/rp2-pio/piolib/ws2812.go

func (ws *WS2812) SetRGB(r, g, b uint8) {
    color := uint32(r)<<16 | uint32(g)<<8 | uint32(b)
    println("r", r, "g", g, "b", b)
    ws.sm.TxPut(color)
}
Gustavomurta commented 12 months ago

If you find it convenient to make changes to faithfully adapt the bit time specifications (+- 150ns):

WS2812B:

T0H = 400ns / T0L = 850ns T1H = 800ns / T1L = 450ns

image

My measurements with logic analyzer:

T0H = 500ns / T0L = 458 ns (can improve) image

T1H = 875ns / T1L = 417ns (very good) image

soypat commented 10 months ago

I've reverted the changes and moved all changes to a PR for better following of changes.

Gustavomurta commented 10 months ago

Thank you Patrício!

soypat commented 6 months ago

Latest main now contains changes that match the tinygo drivers implementation behaviour, please give it a try!

mishamyrt commented 4 months ago

@soypat First of all I want to say a huge thank you for developing tinygo infrastructure for Pico.

I tested the library too, connected a strip of 92 WS2812 LEDs to the Pico W, added the blocking write function and I managed to set the colour for all diodes.

I noticed a problem: the brightness does not match what I set. If I try to set RGB{1, 0, 0}, the red one shines as if I set RGB{200, 0, 0} or so. There is a small difference between RGB{1, 0, 0} and RGB{255, 0, 0}, but it's very slight.

I'm not sure (and I can't check it since I don't have an oscilloscope), but I think there is a timing problem.

soypat commented 4 months ago

@mishamyrt Hey! thanks for reporting this :)

So the issue you are noticing is only with RGB{1,0,0}? Or does the same happen with RGB{2,0,0} or RGB{0,1,0}?

mishamyrt commented 4 months ago

Yes, the problem is reproduced with any values. They all look too high. As if the brightness is encoded in 2-3 bits.

soypat commented 4 months ago

What version of this repo are you using? You can share your go.mod project file here

soypat commented 4 months ago

@mishamyrt I've implemented a new version of the algorithm to fix timings a bit. Should be consistent with https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf datasheet. Please try it out and let me know if it fixes the issue.

Waveshare note

Note: Waveshare Zero board has a different clock!

Below is a Low bit with the current WS2812B implementation, in its own branch. I'm setting a CLKDIV of whole=17, frac=0 which should yield 1e9/(125000000/17) = 136ns per cycle, but somehow the high time is 640ns, which is not a multiple of 136ns!

image

soypat commented 4 months ago

Solved by merging #10 as far as I can tell! Let me know if not the case (may be for WS2812, but that's a separate issue in any case)