NodeMCU MQTT LED Strip Controller Build & Config How-To Videos

Hi all! I’ve created some quick how-to videos to show the build and configuration of my homemade NodeMCU LED Strip controller, which I use for kitchen under-cabinet lighting and holiday lights. The complete project is written up on the Thingiverse site, but I wanted to post the openHAB specific configuration sample files here for easy linking.

The following items/sitemap and rules entries comprise a single strip and a “group” of strips (if more than one strip is defined and they’re required to be controlled as a group). Single strips are defined by their own MQTT topic, but all strips also subscribe to the “group” MQTT topic and react to commands posted to that topic as a group.

ledstrip.items:


Group gLEDStrip_Kitchen "Kitchen LED Strips"
Group gLEDStrip_Kitchen_Power "Kitchen LED Strips Power"
Group gLEDStrip_Kitchen_FX "Kitchen LED Strips FX"
Group gLEDStrip_Kitchen_Color "Kitchen LED Strips Color"
Group gLEDStrip_Kitchen_Speed "Kitchen LED Strips Speed"
Group gLEDStrip_Kitchen_Intensity "Kitchen LED Strips Intensity"

String LEDStrip_FF_Kitchen_Cabinet_1 "Kitchen LED Strip 1 String" (gLEDStrip_Kitchen) {mqtt=">[broker:home/FF_Kitchen_Cabinet_1/set:state:*:default]"}
Switch LEDStrip_FF_Kitchen_Cabinet_1_Power "Kitchen LED Strip 1 Power" (FF_Kitchen,gLEDStrip_Kitchen_Power) {mqtt=">[broker:home/FF_Kitchen_Cabinet_1/set:command:*:MAP(LEDStripEffectJSON.map)]"}
Number LEDStrip_FF_Kitchen_Cabinet_1_FX "Kitchen LED Strip 1 Fx" (FF_Kitchen,gLEDStrip_Kitchen_FX){mqtt=">[broker:home/FF_Kitchen_Cabinet_1/set:command:*:MAP(LEDStripEffectJSON.map)]"}
Color LEDStrip_FF_Kitchen_Cabinet_1_Color "Kitchen LED Strip 1 Color"	<rgb>	(FF_Kitchen,gLEDStrip_Kitchen_Color)
Number LEDStrip_FF_Kitchen_Cabinet_1_Speed "Kitchen LED Strip 1 Speed [%.0f]"		(FF_Kitchen,gLEDStrip_Kitchen_Speed)
Number LEDStrip_FF_Kitchen_Cabinet_1_Intensity "Kitchen LED Strip 1 Intensity [%d]" (FF_Kitchen,gLEDStrip_Kitchen_Intensity)

String LEDStrip_Kitchen_Cabinet "Kitchen Cabinet String" (gLEDStrip_Kitchen) {mqtt=">[broker:home/LEDStrip_Group2/set:state:*:default]"}
Switch LEDStrip_Kitchen_Cabinet_Power "Kitchen Cabinet Power" (FF_Kitchen,gLEDStrip_Kitchen_Power) {mqtt=">[broker:home/LEDStrip_Group2/set:command:*:MAP(LEDStripEffectJSON.map)]"} 
Number LEDStrip_Kitchen_Cabinet_FX "Kitchen Cabinet Fx" (FF_Kitchen,gLEDStrip_Kitchen_FX){mqtt=">[broker:home/LEDStrip_Group2/set:command:*:MAP(LEDStripEffectJSON.map)]"}
Color LEDStrip_Kitchen_Cabinet_Color "Kitchen Cabinet Color"	<rgb>	(FF_Kitchen,gLEDStrip_Kitchen_Color)
Number LEDStrip_Kitchen_Cabinet_Speed "Kitchen Cabinet Speed [%.0f]"		(FF_Kitchen,gLEDStrip_Kitchen_Speed)
Number LEDStrip_Kitchen_Cabinet_Intensity "Kitchen Cabinet Intensity [%d]" (FF_Kitchen,gLEDStrip_Kitchen_Intensity)

.sitemap:

				Switch item=LEDStrip_FF_Kitchen_Cabinet_1_Power
				Selection item=LEDStrip_FF_Kitchen_Cabinet_1_FX mappings=[1="BPM",2="Noise",3="Fire",4="Rainbow",5="Twinkle",6="Glitter",7="Solid",8="Sinelon",9="Juggle",10="Confetti",11="Dots",12="Lightning",13="Candy Cane",14="Cyclon Rainbow",15="Ripple",16="Christmas Alternate",17="Police All",18="Police One",19="Random Stars",20="Sine Hue",21="Christmas",22="St Patty",23="Valentine",24="Turkey Day",25="Thanksgiving",26="USA",27="Independence",28="Halloween",29="Go Lions",30="Hail",31="Touchdown",32="Punkin",33="Lovey Day",34="Holly Jolly",35="Full Hue",36="Breathe",37="Hue Breathe"]
				Colorpicker item=LEDStrip_FF_Kitchen_Cabinet_1_Color
				Slider item=LEDStrip_FF_Kitchen_Cabinet_1_Speed 
				Slider item=LEDStrip_FF_Kitchen_Cabinet_1_Intensity 

                Switch item=LEDStrip_Group_1_Power
				Selection item=LEDStrip_Group_1_FX mappings=[1="BPM",2="Noise",3="Fire",4="Rainbow",5="Twinkle",6="Glitter",7="Solid",8="Sinelon",9="Juggle",10="Confetti",11="Dots",12="Lightning",13="Candy Cane",14="Cyclon Rainbow",15="Ripple",16="Christmas Alternate",17="Police All",18="Police One",19="Random Stars",20="Sine Hue",21="Christmas",22="St Patty",23="Valentine",24="Turkey Day",25="Thanksgiving",26="USA",27="Independence",28="Halloween",29="Go Lions",30="Hail",31="Touchdown",32="Punkin",33="Lovey Day",34="Holly Jolly",35="Full Hue",36="Breathe",37="Hue Breathe"]
				Colorpicker item=LEDStrip_Group_1_Color
				Slider item=LEDStrip_Group_1_Speed
				Slider item=LEDStrip_Group_1_Intensity

.rules:

rule "LED Strip Group 1 (Kitchen) JSON Color Single Strip"
when Member of gLEDStrip_Kitchen_Color received update
then 
 	val source = triggeringItem.name.split("_Color").get(0)
	logInfo("LED", "Source " + source)
	val item = gLEDStrip_Kitchen.members.findFirst[ l | l.name == source ] as StringItem
	logInfo("LED", "Item " + item.name)
	item.sendCommand("{\"color\": {" + 
		"\"r\": " + (triggeringItem.state as HSBType).red.intValue.toString + "," +
		"\"g\": " + (triggeringItem.state as HSBType).green.intValue.toString + "," +
		"\"b\": " + (triggeringItem.state as HSBType).blue.intValue.toString + "}}") end

rule "LED Strip Group 1 (Kitchen) JSON Speed Single Strip"
when Member of gLEDStrip_Kitchen_Speed received update
then 
	val source = triggeringItem.name.split("_Speed").get(0)
	val value = triggeringItem.state as Number
	logInfo("LED", "Source " + source)
	val item = gLEDStrip_Kitchen.members.findFirst[ l | l.name == source ] as StringItem
	item.sendCommand("{\"transition\": \"" + (value / 100 * 240).intValue.toString + "\"}") end

rule "LED Strip Group 1 (Kitchen) JSON Intensity Single Strip"
when Member of gLEDStrip_Kitchen_Intensity received update
then 
	val source = triggeringItem.name.split("_Intensity").get(0)
	val value = triggeringItem.state as Number
	logInfo("LED", "Source " + source)
	val item = gLEDStrip_Kitchen.members.findFirst[ l | l.name == source ] as StringItem
	item.sendCommand("{\"brightness\":" + (value / 100 * 255).intValue.toString + "}") end

LEDStripEffectJSON.map:

1={"effect":"bpm"}
2={"effect":"noise"}
3={"effect":"fire"}
4={"effect":"rainbow"}
5={"effect":"twinkle"}
6={"effect":"glitter"}
7={"effect":"solid"}
8={"effect":"sinelon"}
9={"effect":"juggle"}
10={"effect":"confetti"}
11={"effect":"dots"}
12={"effect":"lightning"}
13={"effect":"candy cane"}
14={"effect":"cyclon rainbow"}
15={"effect":"ripple"}
16={"effect":"christmas alternate"}
17={"effect":"police all"}
18={"effect":"police one"}
19={"effect":"random stars"}
20={"effect":"sine hue"}
21={"effect":"Christmas"}
22={"effect":"St Patty"}
23={"effect":"Valentine"}
24={"effect":"Turkey Day"}
25={"effect":"Thanksgiving"}
26={"effect":"USA"}
27={"effect":"Independence"}
28={"effect":"Halloween"}
29={"effect":"Go Lions"}
30={"effect":"Hail"}
31={"effect":"Touchdown"}
32={"effect":"Punkin"}
33={"effect":"Lovey Day"}
34={"effect":"Holly Jolly"}
35={"effect":"full hue"}
36={"effect":"breathe"}
37={"effect":"hue breathe"}
ON={"state":"ON"}
OFF={"state":"OFF"}

Direct video links:

Part 1: Hardware Build:

Part 2: Arduino firmware setup/load:

Part 3: OpenHAB configuration:

Part 4: Long LED Strip power considerations

-B.K.

23 Likes

If you use specific code fences you will get some syntax highlighting which will make the rules a little easier to read. How to use code fences

Ugh, I know you’re right, but I did the sitemap file using code fences last night, and I just hate how it splits every line into a separate fence if you select them all and click the formatting button (and you have to remove every single one to make it look right). It does look much better, so I went and re-edited just now.

-B.K.

```php
Paste in sitemap code
```

If you put in the code fences first and paste you sitemap between the fences it doesn’t matter how many white spaces there are, it will keep them all together. I never use the buttons.

Brilliant!! Of course there’s a better way once I finish doing it the hard way :smiley: Thanks for that, I’ll definitely remember it next time!

@rlkoshak can this not be fixed somehow? I see a lot of people have bad post formatting as the engine does split up marked code into multiple lines.

I have no idea. I suppose someone could file an issue over on Discourse, the underlying software that drives the forum. We don’t have that much control over those sorts of behaviors ourselves.

HMMM @ThomDietrich did you not wrote the plugin for the Buttons? I would Guess.

And a deeper search shows a FIX: Apply surround should not be applied individually to each line. for discourse/discourse-spoiler-alert

Maybe this could also be fixed? As it seems its just a single line!

Just a quick update to the first post, to add direct links to the how-to videos, and also to add [ “Switchable” ] tags to Power/Color items (this exposes those items to Google Assistant/Home) and allows voice activated power/color selection, as seen in this demo video:

I´ve got some problems here. I just set everything up like in the description. But I still get some compiling errors:

In file included from D:#Heimautomatisierung\ESP-MQTT-JSON-Digital-LEDs-master\my_ESP_MQTT_Digital_LEDs\my_ESP_MQTT_Digital_LEDs.ino:27:0:

C:\Users\Corny\Documents\Arduino\libraries\FastLED/FastLED.h:17:21: note: #pragma message: FastLED version 3.001.007

pragma message “FastLED version 3.001.007”

                 ^

In file included from C:\Users\Corny\Documents\Arduino\libraries\FastLED/FastLED.h:68:0,

             from D:\#Heimautomatisierung\ESP-MQTT-JSON-Digital-LEDs-master\my_ESP_MQTT_Digital_LEDs\my_ESP_MQTT_Digital_LEDs.ino:27:

C:\Users\Corny\Documents\Arduino\libraries\FastLED/fastspi.h:110:23: note: #pragma message: No hardware SPI pins defined. All SPI access will default to bitbanged output

pragma message “No hardware SPI pins defined. All SPI access will default to bitbanged output”

                   ^

D:#Heimautomatisierung\ESP-MQTT-JSON-Digital-LEDs-master\my_ESP_MQTT_Digital_LEDs\my_ESP_MQTT_Digital_LEDs.ino: In function ‘void loop()’:

D:#Heimautomatisierung\ESP-MQTT-JSON-Digital-LEDs-master\my_ESP_MQTT_Digital_LEDs\my_ESP_MQTT_Digital_LEDs.ino:516:50: warning: NULL used in arithmetic [-Wpointer-arith]

 if (transitionTime == 0 or transitionTime == NULL) {

                                              ^

D:#Heimautomatisierung\ESP-MQTT-JSON-Digital-LEDs-master\my_ESP_MQTT_Digital_LEDs\my_ESP_MQTT_Digital_LEDs.ino:530:50: warning: NULL used in arithmetic [-Wpointer-arith]

 if (transitionTime == 0 or transitionTime == NULL) {

                                              ^

D:#Heimautomatisierung\ESP-MQTT-JSON-Digital-LEDs-master\my_ESP_MQTT_Digital_LEDs\my_ESP_MQTT_Digital_LEDs.ino:542:50: warning: NULL used in arithmetic [-Wpointer-arith]

 if (transitionTime == 0 or transitionTime == NULL) {

…and so on…

Im using a NodeMCU in version 2. In Arduino IDE I chose "NodeMCU 1.0 (ESP-12E Module). I also tried 0.9 but still error.
At least the NodeMCU connects to my WiFi but that was the only thing.

Could someone help me? Im very new to NodeMCUs and the Arduino IDE.

@killercorny Those all seem like warnings I usually get when compiling my code. Does it actually go into the “Uploading” state and finish saving the code to your NodeMCU? If so, you could check to make sure it’s connecting to your wifi and sending out MQTT message using something like MQTT.fx…If it’s connecting to your Wifi and sending out MQTT messages, I would say it is fine!

Yes, its uploading to 100% and in my router I can see that it is connected. Seems like MQTT doesnt work.
How can I test it in mqtt.fx ? Which command do I need? Im still not into MQTT… :persevere:

The serial Monitor also doesnt show anything…

Ok, so if it’s connected to Wifi, that’s a good sign…Now, I’m assuming you have a MQTT broker set up on your network that you configured in the Arduino code, right?

I’ve actually just published a video on my channel that shows how to use MQTT.fx to see messages from my sensors:

Watch it and let me know if you have any questions afterwards.

As for the serial monitor, you’d need to make sure it’s set to the correct baudrate, but then again, I’ve not been using mine either (I usually just program these with the OTA setup, and then use over the air programming for new updates).

Your video actually helps, now I know, MQTT and the NodeMCU are working. I set the baudrate in the serial monitor to 115200 and messages appear:

WiFi connected
IP address: 
192.168.111.124
Ready
IP Address: 192.168.111.124
Attempting MQTT connection...connected
Setting LEDs:
r: 0, g: 0, b: 0
Message arrived [bruh/porch/set] {"effect":"cyclon rainbow"}
cyclon rainbow
Setting LEDs:
r: 0, g: 0, b: 0
Message arrived [bruh/porch/set] {"state":"OFF"}
?⸮⸮?kE @state
Setting LEDs:
r: 0, g: 0, b: 0
Message arrived [bruh/porch/set] {"state":"ON"}
?A⸮⸮?kE @state
Message arrived [bruh/porch/set] {"color": {"r": 100,"g": 39.00,"b": 60.350000000000}}
350000000000}}
Message arrived [bruh/porch/set] {"color": {"r": 100,"g": 39.00,"b": 60.350000000000}}
350000000000}}
Message arrived [bruh/porch/set] {"color": {"r": 100,"g": 41.00,"b": 53.783333335300}}
783333335300}}
Message arrived [bruh/porch/set] {"color": {"r": 100,"g": 99.00,"b": 99.200000000000}}
200000000000}}
Message arrived [bruh/porch/set] {"effect":"bpm"}
bpm

But there´s one big problem. None of the LEDs are lighting up. I´ve got a WS2812b strip and this is the config:
#define NUM_LEDS 8
#define DATA_PIN D4
#define CHIPSET WS2812
#define COLOR_ORDER GRB

Its only 8 Pins because I hooked the strip directly to the NodeMCU, this should be enough for testing purposes.

Are you definitely hooked up to the d4 pin? Does the first led light up the first time you power on the Nodemcu?

You may be having an issue with the ws2812b strip requiring 5v data to light up…the Nodemcu puts out 3v3. I’ve never encountered a problem but there are strips that have this problem. You can either use a level shifter ( 74hct245 works), or put a diode between the 5v power supply and the first led only (and 5v directly to the rest)…this is a known workaround for these (see https://hackaday.com/2017/01/20/cheating-at-5v-ws2812-control-to-use-a-3-3v-data-line/ ), since the first leds brings up the signal level to the required 5v…you’re only making the 3v3 act on a smaller range (-4.4v, due to diode forward bias).

This sounds confusing, but make sense, somehow. What I dont get is, in the Strandtest-example in the Arduion-IDE, the library Adafruit_NeoPixel.h is used, and I dont need to change anything. Its hooked up directly to pin D4 and I dont use a level shifter. How that?

Whatever, I dont want to cut the strip, because there is an presolded connector for power. So I will order some level shifter, Amazon is my friend. :rofl:

It is weird if it’s working with another project file (are you still attached to the same board, same way?) Instead of getting the level shifter, you could try moving the signal wire between outputs (D0-D10) on the NodeMCU board, and seeing if the LEDs flicker on. Perhaps you just have it connected to the wrong pin on the nodeMCU?

Yep, I don’t change anything. I’m still using D4, in your sketch and the strandtest example. I will try an other pin, maybe this works.

EDIT:
I meassured the voltage between GND and the Data pin. It´s around 3,3V in both cases. The difference in my eye is only the used library to controll the strip. Adafruit_NeoPixel.h with 3.3V works but FastLED.h with 3.3V not. Even WS2812B are supported by both libraries.

Interesting! Might be the way Fastled sends their data/pwm (might be faster so overall voltage is lower than the ws2812b threshold). I’m pretty sure a level shifter will solve your problem (just make sure to get the 74hct245 since the i2c level shifters are too slow).

I’ll be updating the pcb board design soon to swap out the level shifters among other things/ideas I have in mind.

I´ve order these one: https://www.amazon.de/gp/product/B0148BLZGE
Now I´m afraid these are not the correct one, like you mentioned.

While researching I found this: https://github.com/FastLED/FastLED/wiki/Interrupt-problems