NeoPixel LED Controller

NeoPixel LED Controller - Example Candle & Strip Lights

Building a NeoPixel LED Controller with MQTT and HomeKit support. Expanding on my previous project to add LED lighting to my work area, I wanted to investigate a lower voltage and more customisable LED system. I had read about WS2812B or NeoPixel LEDs but had not built anything with them. I have since build a whole raft of lighting projects utilising these and even designed a simple PCB to use in my controllers. In this blog post I aim to go over the basics, take a peek at the software I have written and talk about the various projects I have used them in.

NeoPixel LED Controller – Short Demo – The Candles & Desk Strip Are Powered By This Controller

What Are NeoPixel LEDs?

NeoPixel is Adafruit’s brand name for individually-addressable RGB colour pixels and strips based on the WS2812, WS2811 and SK6812 LED/drivers, but it has become shorthand for any individually addressable LED drivers. The cool part about this is the fact that you can set properties on any LED in a whole strip or matrix, this allows us to play about with effects and fades and makes them a lot more versatile that the standard strips I used in my previous project (Build A HomeKit Enabled WiFi LED Strip). They also run on 5v rather than 12v so building a project with a microcontroller is far easier and need less components.

Required Hardware

The hardware you will require for this project is as follows

  1. An existing MQTT server on your network, this is required for messaging,
  2. If you wish to use HomeKit an existing Homebridge server on your network.
  3. An ESP8266 board, something like a Wemos D1 Mini, you can use other boards but you will have to amend the code.
  4. A length of WS2812B strip, something like this, 5 meters (60 LED) costs about £15.
  5. (Optional) A barrel jack socket, to connect DC power to the board.
  6. A suitably rated 5v power supply, the amperage will vary depending on how long your LED strip is. I used a 5v 4A supply I had already.
  7. A suitable current smoothing capacitor to deal with sudden changes in the LED strip current draw. I used a 1000uF 16v capacitor.
  8. Some perfboard to build the project on (or use my handy dandy Gerber files to have PCBs made, or even better get JLCPCB to fab and send it to you.).
  9. (Optional) A screw terminal to attach the LED strip leads to your board.
  10. Some patch wire to link the components on the board.
  11. A suitable enclosure or access to a 3D printer (STL and OpenSCAD files are provided).
  12. Soldering iron, snips etc.

The Circuit

The following shows how to connect the various components, there really is not a lot to it and you could go without any perfboard at all and simply solder the parts together.

NeoPixel LED Controller – Fritzing Circuit Diagram

I have used this circuit so frequently in projects that I have now designed a PCB so I can standardise the layout and case design. The Gerber files are freely available and if you wish you can visit my EasyEDA project page and get JCLPCB to manufacture batches of the board.

NeoPixel LED Controller – Naked Circuit Board
NeoPixel LED Controller – Circuit Board

The Microcontroller Code

The code has been written using the Ardunio platform, although I prefer to to use PlatformIO inside Visual Studio Code rather than the Arduino editor.

All of the code files, fritizing diagram, Gerber and 3d printer files for the NeoPixel LED Controller can be found on my github.

The controller code is similar to my previous project (Build A HomeKit Enabled WiFi LED Strip) in so far as being able to send HSV values to set colours, but it also now allows you to run effects on the connected LEDs. You can even specify a favourite effect so you can easily toggle it via HomeKit. Some of the effects will use the currently selected colour as their base (with a default colour if none is selected) and other effects will run though pre-configured colours.

LED Effects

The current list of effects is as follows, they are taken from a great article on FastLED / NeoPixel LED effects by Tweaking4All.com. I have taken a selection I wished to use and adapted them for my purposes.

IDEffectDescriptionVideo Link
1RGB LoopFades colour in and out from red to green to blue.Link
2Running LightsChase light effect from red to white to blue.Link
3Colour WipeWipe effect using the colour you have selectedLink
4Rainbow CycleRainbow cycle of colours, default effect on stripLink
5Theatre ChaseLEDs chase each other, like an old theatre, uses whatever colour you have selectedLink
6Theatre Chase RainbowRainbow effect version of theatre chaseLink
7FireBurning fire effectLink
8Meteor RainMeteor shooting across the skyLink
9CylonBy your command..Link
10TwinkleTwinkle effect using selected colourLink
11Tinkle RandomTwinkle effect using random coloursLink
12SparkleVariation of twinkle, white sparkle effectLink
13Snow SparkleSnow effect with occasional sparkleLink
14BreathingBreath in out effect with selected colour.
NeoPixel LED Controller – Effects List

Configuring The Code

Firstly you must adjust and renamed the config file, I (now) use LittleFS uploaded config files for most of my projects as it makes my configuration easier for WiFi. MQTT and OTA. On the github page there is an example file that once checked out will need to be renamed to config,json (from config.EXAMPLE.json) and edited to fill in the SSID and password of your WiFI network. You will also need to complete your MQTT server details, I would pay special attention to the device_id and base_topic as they will end up setting the full topic for your MQTT commands, please set then to something sensible.

{
    "name": "Desk LED Strip",
    "device_id": "desk-led-strip",
    "wifi": {
      "ssid": "WIFI_SSID",
      "password": "WIFI_PASSWORD"
    },
    "mqtt": {
      "host": "xxx.xxx.xxx.xxx",
      "port": 1883,
      "base_topic": "basement/light/",
      "username": "MQTT_USERNAME",
      "password": "MQTT_PASSWORD",
      "retained": true
    },
    "effect_sw":{
      "effect_index": 4,
      "effect_seconds": 0
    }
  } 

You can also see there is a section called effect_sw, this is designed to set the parameters for the effect you would like to be able to toggle on and off via HomeKit. The effect_index is a number from the above effects table, the effect_seconds is how long it should run with 0 being forever (this is best for a toggle switch, change if you configure a momentary one). By default it runs the Rainbow Cycle effect.

You will need to configure some settings in the main code, you will need to edit led.h. From here you can edit the pin that will send the control signals to the LED strip, by default it is D5 (LED_PIN). You will also need to set how many LEDs you have in your strip, otherwise they will not behave as expected (NUM_LEDS). Optionally you can set the voltage and amperage limits on the strip, thus limiting the power you will use (LED_STRIP_VOLTAGE, LED_STRIP_MILLIAMPS). I suggest leaving the voltage at 5v and adjusting the amperage to suit.

#define NUM_LEDS 73
#define LED_PIN D5
#define LED_STRIP_VOLTAGE 5
#define LED_STRIP_MILLIAMPS 4000 

Over The Air Updates

The code is configured to allow over the air updates, the thought behind this is that once you have a light in place it may not be easy or practical to connect the device back to a computer to upgrade the firmware. The mDNS name will be in the form of <device_id>.local, for example, using the example config it would have a name of desk-led-strip.local. If you are using PlatformIO (which I highly recommend over the Arduino IDE) you simply need to change the upload_port in the ini file to the name of your mDNS entry.

I will not go through all the code files here as they are available on my github page. You will need to update and upload the config file before compiling and flashing the code to the device of your choice.

MQTT

Once you have the circuit built and the code flashed to your device, it is best to test that it can receive MQTT commands before you try and configure it to work on HomeKit.

For testing MQTT I use MQTT.fx on the Mac, and as it runs on Java this should work on all platforms. I am assuming you have not changed the base_topic and device_id, if you have you can update the tests to reflect this.

Basic Light

You can subscribe to “basement/light/desk-led-strip/hsv” and this will post back a comma delimited string with the HSV value that the light has been set to (for example 0,0,100). It will also retain messages so after a power loss the state is known.

If you send a message to “basement/light/desk-led-strip/hsv/set” with the payload of a comma delimited HSV value such as 0,0,100 it will set the strip to that colour and intensity, it will also then post back to “basement/light/desk-led-strip/hsv” with the HSV change.

Effects

You can set an effect and the duration for the effect should run for by sending a JSON payload to “basement/light/desk-led-strip/effect”. The payload should look like the following.

{effect_index:9, effect_seconds:20}

The above payload would run the Cylon effect for 20 seconds, it mirrors the parameters seen in config file for the effect_sw.

Effect Switch

If you wished to have a toggle-able effect mode without having to send a complex JSON payload (for example in HomeKit) you can define a switch effect in the config file. To turn the effect on or off you can simply send a “true” or “false” payload to “basement/light/desk-led-strip/effect_sw/set”. It will mirror back the state that has been set to “basement/light/desk-led-strip/effect_sw”.

Apple HomeKit via Homebridge

If you have a working Homebridge server you can easily add this device to it and be up and running in no time. You need to install the MQTTthing plugin if you do not have it already and then add the following to your config file, adjusting as required for your MQTT setup.

        {
            "accessory": "mqttthing",
            "type": "lightbulb",
            "name": "Desk LED",
            "url": "mqtt://localhost",
            "username": "USERNAME",
            "password": "PASSWORD",
            "topics": {
                "getHSV": "basement/light/desk-led-strip/hsv",
                "setHSV": "basement/light/desk-led-strip/hsv/set"
            }
        },

If you wanted to add an additional switch for turning on or off a the pre-configured effect mode then add the following to your config file, adjusting as required.

        {
            "accessory": "mqttthing",
            "type": "switch",
            "name": "Desk LED Effect",
            "url": "mqtt://localhost",
            "username": "USERNAME",
            "password": "PASSWORD",
            "topics": {
                "setOn": "basement/light/desk-led-strip/effectsw/set",
                "getOn": "basement/light/desk-led-strip/effectsw"
            }
        },

Once you have restarted Homebridge you will see a new light on your Home app.

3D Printed Case

I have produced a 3D printed case that fits my PCB, this will probably work for a custom build without the PCB but you will have to play around. I am not sure how well it will snap together without the PCB. The STL and OpenSCAD files are on my github under the folder 3d-printed-case.

NeoPixel LED Controller – OpenSCAD

NeoPixel LED Controller – 3D Printed Case

I hope you have found this guide useful, if you have any problems with the NeoPixel LED Controller or any suggestions, feel free to leave a comment or post on my github page.

Lighting Projects Using This Controller

Here are some photos of the lighting projects I have created using this controller, they are used extensively around my house; a display fireplace, a 3D printer running light, multiple desk lights and stair rail lights.

Build A HomeKit Enabled WiFi LED Strip

12v WiFi LED Strip Circuit Diagram

I have a work area that I wanted to provide some additional lighting for, and like everything else in my home I wanted it to work with Apple HomeKit. I did not want to spend a large amount of money buying something like a Phillips Hue Strip so I thought I would build my own. This will be a short guide to how I built a HomeKit Enabled WiFi LED Strip and the software I wrote to run it.

Before you start, if you are not comfortable building electronics projects or you are unsure on how to calculate the power requirements for your LED strips, please do not attempt this project. I have assumed a basic working knowledge of how to write code for Arduino devices and how to flash such code.

Required Hardware

A nice rule of thumb for the power usage (this is taken from the following Adafruit page) of 12v LED strips is as follows.

To find the total maximum current draw per meter, we would multiply 60mA x 10 (ten segments per meter for the 30/LED per meter strip) = 0.6 Amps per meter OR 60mA x 20 (twenty segments per meter for the 60/LED per meter strip) = 1.2 Amps per meter. Again, that’s assuming you would have all the LEDs on at once and that you are powering it from 12V.

The hardware you will require for the project is as follows.

  1. An existing MQTT server on your network, this is required for messaging,
  2. If you wish to use HomeKit an existing Homebridge server on your network.
  3. An ESP8266 board, something like a Wemos D1 Mini, you can use other boards but you will have to amend the code.
  4. A length of 5050 RGB LED strip, something like this, 5 meters costs about £6.
  5. A suitably rated 12v power supply, the amperage will vary depending on how long your LED strip is. I used a 12v 4A supply I had already.
  6. Three suitable MOSFETs I used IRFZ3NN N-channel ones, this should be good for long LED lengths but will require heat sinks if you run more than a few meters (Data Sheet).
  7. A step down DC-DC power converter, this is to drop the 12v down to the 5v required to run the Wemos. I used a MP1584EN based one, you can get fixed 12v to 5v or variable. Please ensure you use a suitably rated one that can handle the amperage, again this will vary by LED strip length.
  8. Some perfboard to build the project on.
  9. Some patch wire to link the components on the board.
  10. A suitable enclosure or access to a 3D printer (STL and OpenSCAD files are provided).
  11. Soldering iron, snips etc.

The Circuit

The following circuit explains how to connect the various components, I will leave it to the reader on how they would like to arrange the board design and I will include a picture of my design. The IRFZ3NN MOSFETs have pin 1 as the GATE, pin 2 as the DRAIN and pin 3 as the SOURCE. If you use a different component please use this information as reference on how to rework the circuit.

12v WiFi LED Strip Circuit Diagram – Fritzing
LED Strip Controller In 3D Printed Case
LED Strip Controller In 3D Printed Case

The Microcontroller Code

The code has been written using the Ardunio platform, although I prefer to to use PlatformIO inside Visual Studio Code rather than the Arduino editor.

All of the code files, fritizing diagram and 3d printer files for HomeKit Enabled WiFi LED Strip can be found on github. LED RGB Strip Controller

Firstly you must adjust and renamed the config file, I use SPIFFS uploaded config files for most of my projects as it makes my configuration easier for WiFi an MQTT. On the github page there is an example file that once checked out will need to be renamed to config,json (from config.EXAMPLE.json) and edited to fill in the SSID and password of your WiFI network. You will also need to complete your MQTT server details, I would pay special attention to the device_id and base_topic as they will end up setting the full topic for your MQTT commands, please set then to something sensible.

{
    "name": "Workbench LED Strip",
    "device_id": "workbench-led-strip",
    "deep_sleep_interval": 600,
    "wifi": {
      "ssid": "WIFI_SSID",
      "password": "WIFI_PASSWORD"
    },
    "mqtt": {
      "host": "xxx.xxx.xxx.xxx",
      "port": 1883,
      "base_topic": "basement/light/",
      "username": "MQTT_USERNAME",
      "password": "MQTT_PASSWORD"
    }
  }

The main entry point to the project sets up the pins that are driving the colour channels, change redPin, greenPin and bluePin as required if you are using a different board or different pins.

int redPin = D8;
int greenPin = D7;
int bluePin = D6;

void setup() {
  Serial.begin(115200);
  analogWriteRange(255);
  
  // Initialize RGB Led strip pins
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

.........

I will not go through all the code files here as they are available on my github page, LED RGB Strip Controller. You will need to update and upload the config file before compiling and flashing the code to the device of your choice.

MQTT

Once you have the HomeKit Enabled WiFi LED Strip circuit built and the code flashed to your device, it is best to test that it can receive MQTT commands before you try and configure it to work on HomeKit.

For testing MQTT I use MQTT.fx on the Mac, and as it runs on Java this should work on all platforms. I am assuming you have not changed the base_topic and device_id, if you have you can update the tests to reflect this.

You can subscribe to “basement/light/workbench-led-strip/hsv” and this will post back a comma delimited string with the HSV value that the light has been set to (for example 0,0,100). It will also retain messages so after a power loss the state is known.

If you send a message to “basement/light/workbench-led-strip/hsv/set” with the payload of a comma delimited HSV value such as 0,0,100 it will set the strip to that colour and intensity, it will also then post back to “basement/light/workbench-led-strip/hsv” with the HSV change.

Please be aware the HSV ranges are as follows H: 0-360, S: 0-100, V: 0-100.

MQTT.fx application

Apple HomeKit via Homebridge

If you have a working Homebridge server you can easily add this device to it and be up and running in no time. You need to install the MQTTthing plugin if you do not have it already and then add the following to your config file, adjusting as required for your MQTT setup.

        {
            "accessory": "mqttthing",
            "type": "lightbulb",
            "name": "Workbench LED",
            "url": "mqtt://localhost",
            "username": "USERNAME",
            "password": "PASSWORD",
            "topics": {
                "getHSV": "basement/light/workbench-led-strip/hsv",
                "setHSV": "basement/light/workbench-led-strip/hsv/set"
            }
        },

Once you have restarted Homebridge you will see a new light on your Home app.

3D Printed Case

I have produced a very basic 3d printed case that suits the size of my circuit board, it is very simple and just pops together. The OpenSCAD and STL files are on the project page under the folder 3d-printed-case.

3D Printed Case OpenSCAD Schematic
3D Printed Case OpenSCAD Schematic

I hope you have found this guide useful, if you have any problems with HomeKit Enabled WiFi LED Strip or any suggestions, feel free to leave a comment or post on my github page.