I have been using "WS2812" based LEDs for some years - both on PCB using tiny 1x1mm LEDs, and on LED strips, and fairly light chains and so on. These types of LEDs are becoming very popular, with a range of subtle variations (colour order, if RGB or RGBW, and all sorts of other attributes like voltage and backup data lines).
The key feature is they work by a serial data stream that is chained along the LED strip. Each LED eats its data bits and then acts as a passthrough for remaining data until a reset pause, when all LEDs apply the new value to the LED itself. A clever system really.
For use on PCBs, I have already blogged on use of 1.5mm x 1.6mm shallower version of the same Xinglight LEDs that are way nicer in many ways. I can litter a PCB with status LEDs in all sorts of styles, and have done so on various PCB designs, all using a single GPIO pin to drive them.
But even on a board with just one status LED, this still makes a lot of sense using just one GPIO.
This recorder board is a nice example, 7 LEDs on the board. Making rows of LEDs as a level indicator is great.
Drivers
The fun is drivers for this. You need a way to control the LEDs and what they show.
Thankfully Espressif have a driver, a managed component led_strip, which allows you to create a strip with LEDs in a variety of formats, update LED values, and send.
They use the RMT hardware, which is intended for generating pulse streams used for IR remote controls. This makes a lot of sense to generate the exact timing. Here is an example of timing needed for WS2812.
So, pulses 400ns and 850ns, and gaps 850ns and 400ns. Makes sense to use RMT.
But wait, here is another WS2812 data sheet...
This has pulses 400ns and 800ns, and gaps 850ns and 450ns! OK, both say ±150ns, but why different?A similar chipset SK6812 has these...
This is rather oddly specified as 1.25us total, but pulses of 300ns and 600ns, but gaps of 900ns and 600ns. So very different, and also adding up to 1.2us not 1.25us.
On face value this does not overlap the spec for WS2812 (either one) quite. But close.
The LEDs I am using are Xinglight, and they have a data sheet of...
This is very different, it lists minimum pulses only, of 300ns and 900ns, and gaps 900ns and 300ns, and a longer reset time.
But the part number is XL-1615RGBC-WS2812B includes WS2812B in it, yet this is different to WS2812 timings (either of them). But this overlaps with WS2812, which is good, well sort of, 850ns fails a minimum 900ns, so sort of.
But let's look for the data sheet for that exact part again, and oh, now I see.
What the hell? This is a 1.75us bit timing, and not an overlap with WS2812. Also, note, they have max 0 280ns and min 1 650ns, so what happens between those - there has to be a decision to read as 0 or 1.
But surprise! They all work using the same driver. It really is an appallingly crap set of data sheets.
Using SPI
RMT is great for exact timings, but struggles with the amount of buffer you need (4 bytes per bit) and struggles to cope under heavy load - even when set to use DMA - so when re-flashing the LEDs go disco.
An alternative way to drive these LEDs, which the Espressif driver now handles, is to use the SPI bus, to clock data. This would not handle things like 450ns and 800ns, but can do nice round multiples like 400ns and 800ns pulses and gaps using 3x clock and coding 100 and 110 per bit.
In practice I have made my own SPI drivers now. This is because I want things the Espressif drivers will not do, such as multiple strips on same GPIO but with different RGB order, or RGB and RGBW stacked up. I also want switching one SPI between different GPIOs cleanly with no glitches. The earlier LEDs will quite happily pass on the controls for the later LEDs even if different order and format - clever isn't it.
My code does allow for different chipset timings, with WS2812 being 400/800 and 800/400, SK6812 being 300/900 and 600/600, and Xinglight being 300/900 and 900/300. But I have found with a lot of testing that basically all of these work with various different types of chip. Crazy.
So I have settled on a simpler driver being 300/900 and 900/300 as that seems closest to being in spec for all formats. It makes encoding simple, 4 bits on SPI bus per bit of data on this, so coded as 8 or E per nibble.
I have no clue why so many subtle, but sort of overlapping, and sort of working specifications. What is crazier to me is the exact same chips seem to have multiple data sheets with different specifications.
In practice, it should be simple, a pulse below say 500ns is a 0, and over that is a 1. A gap of under say 50us is a gap to next pulse, and beyond is a reset. There is no need for a ± on any of these, just a clearly defined minimum and maybe a minimum pulse 100ns and recommendation to stay 50ns away from the limits to allow for rise/fall times on real wires.
I have found some cases of differences though. Initially my SPI code switching GPIOs caused a glitch before a gap (reset) then data. This worked on various LEDs, but one WS2811 fairy light strip failed with glitching and corrupted LEDs. I fixed the SPI glitch and it was fine. But it showed a clear distinction in how reset was handled and how a glitch was handled on some chipsets.
No comments:
Post a Comment
Comments are moderated purely to filter out obvious spam, but it means they may not show immediately.