6
\$\begingroup\$

The WS2811/2812 protocol is well-defined and hence the chip now seems to dominate addressable strip lighting products.

People have managed to use SPI and UART to control it, and someone even did it with GPIOs. But all of them never fail to comment on the relatively tight timing constraints it involves.

My question is, before these clever people came up with clever solutions to bitbanging this protocol, what was the canonical way to talk this protocol? Definitely something non-bitbanging, but also something that wasn't "abusing" existing hardware in a way that wasn't intended. I imagine some sort of hardware FIFO which loads up enough bits beforehand that the timing is not challenging to meet with Arduino on AVR, ESPs, PIC etc.

I have searched extensively and can only find clever libraries, no canonical/standard/straightforward hardware ideas/schematics.

\$\endgroup\$
5
  • \$\begingroup\$ Not sure what you're looking for. You can always program an FPGA (and it wouldn't take much code) if you want to create an intermediary block to link it to some computational device that can't manage the timing directly or through peripherals it has on board (perhaps because it's running gobs of compiled code on a sluggish non-real-time operating system). For most any MCU popular these days the timing is not much of an issue when doing bare metal programming. Some have DMA working, I understand. It may take a bit if head scratching, but that's programming. \$\endgroup\$ Commented May 8 at 8:18
  • \$\begingroup\$ I doubt anyone has ever made an MCU with a 'WS2812' peripheral, but my doubt proves nothing. You could pore through the various Chinese offerings and see. \$\endgroup\$ Commented May 8 at 8:19
  • \$\begingroup\$ @SpehroPefhany My question is basically that all of these libraries and solutions seem "clever" rather than "standard". I don't mind complexity, but the feeling that serial peripherals are being "abused" for this makes me ask what's the "non-abuse" way of talking this protocol. DMA seems like an answer. An FPGA seems perhaps overkill, can a generic FIFO hardware do the job? \$\endgroup\$
    – Milind R
    Commented May 8 at 8:25
  • 2
    \$\begingroup\$ It's not abuse to use documented characteristics of a part, IMO. \$\endgroup\$ Commented May 8 at 9:15
  • 1
    \$\begingroup\$ When those LED strips became available, there were already a range of MCUs with enough speed to control them by bitbanging. I'm sure somebody has made a fully hardware solution for fun, but it's not needed. \$\endgroup\$
    – Rich
    Commented May 8 at 22:09

4 Answers 4

6
\$\begingroup\$

The WS2811 protocol is relatively easy to generate. The different length pulses can be generated by monostables, or by a small counter clocked at a suitable rate. Given a byte for the desired light level, the byte can be clocked out bit-wise from a parallel to serial shift register.

The original designers of systems to control these LEDs would use just these components, jelly-bean prices and a few square inches of board for TTL or CMOS counters and shift registers.

Once controls for these needed to go into millions of units, so the designers were shaving pennies and size, those few parts could be compressed down into a tiny corner of an ASIC or FPGA that was running the rest of the system.

What the 'clever' people are doing with SPI, UARTs and bit-banging GPIOs is doing what all (most) engineers enjoy doing, showing that they can do something without the cost and area of the previous solutions.

IIRC, there are libraries to drive these things available for Arduino and the like, a de facto standard if ever there was one.

\$\endgroup\$
3
  • \$\begingroup\$ There are definitely libraries for Arduino and the like, but your suggestion about a parallel-to-serial shift register/length counter is more what I hoped to see. You'll have to admit that "bit-banging" inherently carries a "this is a hack" judgement with it. \$\endgroup\$
    – Milind R
    Commented May 14 at 5:12
  • \$\begingroup\$ @MilindR I wasn't suggesting a length counter (whatever that might be), I was suggesting a counter of trivial length. You're asking the wrong person to agree with you about the hackiness of bit banging. \$\endgroup\$
    – Neil_UK
    Commented May 14 at 5:58
  • \$\begingroup\$ Haha I assumed you meant a counter that counts length of messages, but I didn't think too deep about how to parse that phrase. \$\endgroup\$
    – Milind R
    Commented May 14 at 9:48
2
\$\begingroup\$

I would go so far as to not to describe any of the solutions that use typical microcontroller serial peripherals as being particularly clever. Yes, it's not the typical/intended usage of that peripheral, and you need to make sure you can keep feeding the peripheral without gaps, but I doubt that the designers of the WS2811/2812 protocol did not anticipate that this would be possible.

In fact, with just one data line, only cheap inaccurate sources in each device and no fancy PLLs, there are only so many ways to design such a one-pin protocol, and it will always involve some kind of pulse-width encoding. The WS2811/2812 protocol has the advantage that the receiver only needs to distinguish two different pulse lengths, for typical UART it's nine different lengths (i. e. number of bits).

The protocol could have been designed to be more accommodating to microcontrollers by having a way to pause and continue the transmission, but it wasn't. This is less of an issue with modern controllers anyways because we usually have DMA and multi-transfer FIFOs.

\$\endgroup\$
1
  • \$\begingroup\$ DMA is what really makes that robust though. Most libraries online aren't using large enough FIFOs to allow enough cycles for the microcontroller comfortably doing other things - not sure why. \$\endgroup\$
    – Milind R
    Commented May 14 at 5:13
2
\$\begingroup\$

The timing protocol is not that unforgiving.

You can interrupt the data stream after each LED, as long as you don't reach the minimum time for a bus reset, because LEDs later on the chain have not even been taken out of reset at this point, so they have no timing reference.

Also, "long pulse/short pause for 1, short pulse/long pause for 0" is equivalent to "output 1 for the short pulse duration, then the bit value for the difference between both, then 0 for the remainder of the bit time", so you can realize this with a branch-free assembler fragment that has predictable timing if you disable interrupts.

\$\endgroup\$
1
\$\begingroup\$

I don't know if it is canonical, but many MCUs include an output port state machine feature that is perfect for straightforwardly generating these signals.

On the tinyAVR chips, these are called Configurable Logic Cells (CLC) and on the RP2040 chips they are called programmable I/O (PIO) blocks. They are straightforward to configure to directly generate perfect WS2812B signals - no clever tricks involved. Both of these chips specifically include these types of signals as examples of intended uses for the hardware.

And, for the record, it turns out that WS2812B protocol is not really that picky about timing (my article about WS2812B timing).

\$\endgroup\$
1
  • \$\begingroup\$ bigjosh - Hi, Thanks for writing an answer. However, currently this answer breaks the site rule on promotion, as you have linked to your site without disclosing that affiliation within the answer. Therefore please can you edit the answer and add a suitable disclosure (e.g. "This is my site") just before the link to your site. TY \$\endgroup\$
    – SamGibson
    Commented May 15 at 3:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.