smart-leds-rs / ws2812-spi-rs

Use ws2812 on rust with embedded-hal spi
Apache License 2.0
64 stars 23 forks source link

First byte of first pixel is 0x80 (always bright green) #2

Closed Rahix closed 5 years ago

Rahix commented 5 years ago

On my board (atsamd21 based) the first byte sent over spi seems to contain wrong information.

david-sawatzke commented 5 years ago

The first byte in general or the first byte of every write? The first byte in general seems somewhat unavoidable, since we get the Peripheral in some strange state (namely with mosi not at 0v since powen on). We could just write a zero color on init, but thats kinda hacky.

david-sawatzke commented 5 years ago

IRL conversation determined that to be an issue with samd21-hal not doing IdleLow.

LongLiveCHIEF commented 3 years ago

@david-sawatzke do you remember if there was a fix for this? The mosi_idle_high feature doesn't do the trick for this chip

david-sawatzke commented 3 years ago

Huh, mosi_idle_high was the fix in that case. Not sure what's wrong in your case.

LongLiveCHIEF commented 3 years ago

I have a string of 20 ws2812's, and a simple blinking example, using xiao_m0 (pac is atsamd21g), and the first led is always green, while the rest blink on and off as expected.

I have the mosi_idle_high feature enabled cargo.toml, and my code is pretty simple (taken from the example/rgb-blinky in that same branch (full example/rgb-blinky.rs source):

    const NUM_LEDS: usize = 19;
    let mut data: [RGB8; NUM_LEDS] = [RGB8::default(); NUM_LEDS];
    let empty: [RGB8; NUM_LEDS] = [RGB8::default(); NUM_LEDS];
    let mut ws = Ws2812::new(spi);
    loop {
        for j in 0..NUM_LEDS {
            data[j] = RGB8 {
                r: 0,
                g: 0,
                b: 0x10,
            }
        }
        ws.write(data.iter().cloned()).unwrap();
        delay.delay_ms(1000 as u16);
        ws.write(empty.iter().cloned()).unwrap();
        delay.delay_ms(1000 as u16);
    }

MOSI is still idling high on the logic analyzer, but when I specify the rgb led spi stack decoder, it's showing a reset before the data. So I'm a bit puzzled myself.

I can send a whole logic analyzer dump if you want, but for now, I took this screen grab to give you the general idea

led_logic_analyzer

LongLiveCHIEF commented 3 years ago

@david-sawatzke after looking above, lmk if you want me to open a new issue. For now, i'm operating under the assumption I'm doing something wrong... so I'm just digging deeper to grok some of the lower level pieces before I planned on opening any issues.

LongLiveCHIEF commented 3 years ago

rgb-blinky.zip

You should be able to open that with pulseview. it's just an export of the selected region in the capture from the commentt above with a little bit of lead and end room of the mosi idle to spare.

david-sawatzke commented 3 years ago

I have to admit, I'm somewhat stumped. The low time is even exceeding the 50μs mentioned in the datasheet.

You've captured this stuff with 3MHz, maybe (hopefully) that's not enough, could you try again with a higher samplerate?

I've also tried your code on my trinket m0 (slightly adapted), and it seems to work fine with my ws2812 leds, and the capture looks pretty much identical (trinket_m0_19_ws2812_capture_2.zip)

Maybe you've got weird ws2812 leds, do they work with other libraries? If you increase the low time, does that help?

LongLiveCHIEF commented 3 years ago

I tried a capture at 8MHz and 24MHZ and didn't find any ninja bits. The output looks the same as the previous capture.

I have a whole tub of various ws28xx's I've purchased over a 10 year span, and a dozen other arm boards, so I'll do some mixing and matching and see what happens. Will try increasing low time first though as you suggested.

I'll let you know how it goes. Might be a day or two before I get time to finish all the experiments.

LongLiveCHIEF commented 3 years ago

switched to a newer set of ws2812's, and no green pixel. Same code. I think the set I was using to test are an older version of ws2812's that might have a longer time to reset.

Here's what I was originally testing on: Amazon link - Alitove WS1812B

LongLiveCHIEF commented 3 years ago

it's definitely timing based. changing the low time now has the first led completely blank. The other thing I noticed is that the brightness is progressively weaker for each same color pixel, until a new pixel color comes along, and then it starts at full brightness and diminishes again.

Swapping to the newer strip does not have this issue.

I know that some of the older ws2812B's have a different timing tolerance, so I'm guessing that's what I'm dealing with here.

david-sawatzke commented 3 years ago

Well, the datasheet seems to be wrong. Again. They changed their reset timings for a newer spin, Adafruit has a low time of 300μs, I'll spin up a PR.