Using the WS2812B with a PIC microcontroller

For a recent project at work, I had to get a WS2812B LED working with a PIC18F25K80. The WS2812B is a neat little LED, but getting it working was an absolute nightmare! The device uses a non standard communication protocol and the datasheet is lacking, to put it kindly.

The Arduino community has this device down pat with some well established libraries, but the Microchip community has done less with the device. Before I attach the code that I used, I want to go over some of the challenges I had with this device.

First, the device uses a non standard communication protocol that absolutely requires bitbanging and tight timing. I'm not a fan of either, but there are no other devices in this size that offer the full 16.7 million color range that the WS2812B offers. I would have preferred something like I2C or SPI, but I'll take what I can get.

Second, the datasheet is horrible! It is missing key details, and the details that it does have aren't even accurate. The datasheet lists the positive and negative widths and tolerances to indicate a 0 or 1 bit, but these values aren't correct. In particular, I discovered that the "0 code, high voltage time" value is wrong! The datasheet lists it as 0.2 - 0.5µs, but my LED was flickering and failing with a positive width of around 0.4µs.

The important timing details ended up being:

  • A 0 bit is given when the high voltage time is less than roughly 0.35µs. There is no minimum value to this.
  • The low voltage time is almost completely irrelevant, and signal periodicity is irrelevant. As long as you don't pull low for 50µs between high voltage points, you are fine.

What this means is that all you need to worry about is how long your high voltage time lasts. Under 0.35µs is a 0. Over 0.35µ is a 1. I implemented this work in a simple for loop. Normally, this would cause tremendous overhead between each iteration, but since low voltage time doesn't matter, I didn't care.

Here is my implementation, as a header file, source file and sample usage: