Tag Archive: ws2812B

Hello there. I have written this post quite a while ago and kept it as draft for like four months.

So, as discussed in previous post I own a FadeCandy controller and I’ve ordered some WS2812B led strips at eBay. Cheap leds from China. US$ 15 for 5 meters of 30 led/meter led strip. Ordering stuff in China takes about a month to arrive, but it’s dirt cheap. And with the free shipping they offer, I often wonder how they even make the postage costs out of it. Is the mail for free in China?

Anyways, I stuck the led strips to the shelves above my TV and hooked them up to the FadeCandy controller. The length is 2 meter per strip, and I have two of them. The FadeCandy controller can control up to 8 strips with a maximum 64 leds per strips. So I intend to hook up my two strips to the controller, but to begin with, I’ve connected only one. Mainly due power limitations, as for now I am powering it through a powered USB hub. A Sitecom 4 port port USB hub, which comes with a 1 A power supply. (According to USB specs, it should be 4 x 0.5 = 2 Amps)
I started the FadeCandy server with default configuration and ran one of the examples. As they are configured for some 2D array of leds, the effects they produce don’t make sense. However, just to see if it works, that is not an issue.

Running the demo makes the leds light up with some effects, so everything seems to work fine. However, when I stopped the demo, I noticed some leds blinking. When I look at the FadeCandy page on AdaFruit, I noticed it says “Dithering USB-Controlled Driver for RGB NeoPixels”. Temporal dithering, I presume. So that explains what I am seeing. Fortunately, this can be disabled by adding the following to the config file

	    "dither" : false,
	    "interpolate" : false,

So after this initial test, I proceeded to extend the test code I’ve shown in my first post. I would like to create a running rainbow effect. I would like a constant brightness, but changing colours. Googeling for this constant brightness problem, I’ve stumbled across an algorithm that converts from HSV to RGB colourspace. Running this code gives me a nice fading rainbow. Changing the hue, keeping the saturation and brightness constant.

 int index;
 while (true) {
   for (int i = 59; i; i--) {
     data.leds[i] = data.leds[i-1]; 
   // hue, sat, brightness
   hsb2rgbAN2(index+=8%768, 255, 255, data.leds);
   send (Socket, &data, sizeof(data),0);

However, it’s rather bright, so I turned the brightness parameter down a little. However, this gives not the desired result. The nice fading effect is gone, it looks like separate colours running. With lower values, it even goes down to just red, green and blue parts, with dark in between. Looking at the FadeCandy product page again, it says “Firmware that uses unique dithering and color correction algorithms to raise the bar for quality while getting out of the way of your creativity.” Colour correction…. that’s the problem I suppose. I based my configuration on the default configuration, which included

    "color": {
        "gamma": 2.5,
        "whitepoint": [1.0, 1.0, 1.0]

Removing that from my configuration fixes the problem, and gives me a right fading rainbow even at low brightness.

When reading up about the WS2812 LEDs, I discovered there is a clone, SK6812, which is better then the original. The SK6812 uses a PWM frequency of 800 KHz, while the WS2812 only uses 400 KHz. So, I decided to look for the SK6812 and then I found out there is a variant, which next to the red, green and blue led, also contain a white led. The RGBW variants are not supported by the FadeCandy controller.

That’s when I decided to roll my own implementation. So, I started looking around for some libraries which can control those leds. Amongst the libraries I’ve found was FastLED. It supports a wide range of LEDs. At top of their supported list, they list the APA102, and recommend it. This APA102 also has a clone, the SK9822. Where the APA102 has a PWM frequency of 19.2 KHz, the SK9822 only has 4.7 kHz. However, these leds support dimming. When dimming, the APA102 puts another PWM signal over the 19.2 KHz signal, at a much lower rate: 440 Hz. The SK9822 on the other hand uses a current source to apply the dimming.

I’ll save further details for the next post, as this post has been a draft for way too long now, and I am getting into details… and I am about to explain some more details…

A while ago, I got a customised FadeCandy board and some WS2812 leds from a friend. A FadeCandy is a controller for WS2812 leds (and variants). WS2812 leds are individually addressable RGB leds that can be daisy chained, and are used in for example LED strips. The FadeCandy is a controller that is connected to a computer over an USB interface, and up to 8 chains of WS2812 leds.

The customised part of this board is there is a pin header in stead of a mini/micro USB connector. As for that, it’s not simply plug in in a cable, thus I made a simple breakout board to connect a USB cable. I had some USB B female PCB connectors laying around, so I used one of those to connect the FadyCandy to USB.

I made soldered some of the leds to a prototyping pcb, and fried two of them in the process. At first, I didn’t read the datasheet correctly (or rather, I was too quick). The leds I got are WS2812. This is a variant with 6 pins. The WS2812B got 4 pins. The datasteet mentioned VCC and VDD as ‘Power supply control circuit’ and ‘Power supply LED’ so I connected them to the power rail. That turned out to be a mistake. The VCC should have been connected through a 150Ω resistor, so I blew up the first led. A bright flash and it was dead. Note to self: look at the reference connection diagram first. The second led probably died because I’ve overheated it during soldering. It was a little bit off-centered and I tried to correct for that. In the process I think I might have heated it too long. Nevertheless, I created a test PCB with two functional leds. Time to write some software to control those leds.

The FadeCandy controller comes with a server to control the leds. This server implements the OPC protocol. A simple protocol to control leds, which consists of a header followed by a series of RGB values. On the FadeCandy github there are some examples. However these have an abstraction layer, where one configures how the leds are positioned. This allows one to configure a 2D array of leds, and has functions to draw in this 2D array. This is way too complicated for a 2-led setup. Therefore I wrote my own implementation of the OPC protocol, that just writes some RGB values to the server.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>       
#include <sys/types.h>      
#include <netinet/in.h>     
#include <arpa/inet.h>    
#include <netdb.h>
#include <dlfcn.h>

int main(int argc, char* argv[]){
  int Socket;
  struct sockaddr_in saServer4;

  saServer4.sin_addr.s_addr = inet_addr("");

  Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  if (Socket) {
    if (connect(Socket, (struct sockaddr *)&saServer4, sizeof(saServer4))) {
      printf("Connection failed!\n");
    } else {
      uint8_t data[10];
      data[0] = 1; // channel 1
      data[1] = 0; // command 0, send RGB data

      data[2] = 0; // data size high byte
      data[3] = 6; // data size low byte

      data[4] = 255; //R
      data[5] = 0;   //G
      data[6] = 0;   //B

      data[7] = 0;   //R
      data[8] = 0;   //G
      data[9] = 255; //B
      send (Socket,data,sizeof(data),0);
  } else printf("Socket error!\n");

Running this code in combination with the following config file on the FadeCandy server: (overriding the defaults, I will discuss this in a later post)

    "listen": [null, 7890],
    "verbose": true,
    "devices": [
        "type": "fadecandy",
         "map": [
                [ 1, 0, 0, 2 ] 

This allows me to control the leds. But just 2 leds is no fun, so I ordered some led strips. I will discuss those leds strips in a later post. Thanks for reading and stay tuned for the next post ;)