Controlling Neopixel or RGB LED with Openhab

Controlling Neopixels or RGB LEDs from an ESP8266, controlled by OpenHab is fairly simple. I will present here a working system with a Colorpicker, some predefined buttons and sliders. It will be updateable by OTA and provide some  feedback to openhab on the node parameters

Using a Colorpicker
The sitemap and items file are fairly easy, just using a Colorpicker. I will describe some additions, but the basic files are quite simple

itemsfile

Group All
Color RGBLed "NeoPixel Color" (All)
String RGBLedColor (All) {mqtt=">[mosquitto:OpenHab/RGB:command:*:default]"}

There are 2 items here. One item contains the HSB value, coming from the colorpicker, The other item, that will not be visible on the screen, will contain the calculated RGB code that will be sent out via MQTT.

sitemap file is as follows:

sitemap NeoPixel label="NeoPixel"
{
	Frame label="NeoPixel" {
		Colorpicker item=RGBLed icon="slider"
	}
}

The colorpicker sends an HSB (Hue, Saturation, Brightness) code, but that isnt anything a regular Neopixel LED or regular RGB LED can use, so I set up a rule that triggers on any change of the RGB item to change the HSB code into a regular RGB code. That RGBcode is joined in 1 string called ’ color’. The rule then assigns that ‘color’ string to a new item called “RGBLedColor”

rules file

import org.eclipse.smarthome.core.library.types.DecimalType
import org.eclipse.smarthome.core.library.types.HSBType

rule "Set HSB value of item RGBLed to RGB color value"
when
	Item RGBLed changed
then
	val hsbValue = RGBLed.state as HSBType

	val brightness = hsbValue.brightness.intValue 
	val redValue = ((((hsbValue.red.intValue * 255) / 100) *brightness) /100).toString
	val greenValue = ((((hsbValue.green.intValue * 255) / 100) *brightness) /100).toString
	val blueValue = ((((hsbValue.blue.intValue * 255) / 100) *brightness) /100).toString

	val color = redValue + "," + greenValue + "," + blueValue

	sendCommand( RGBLedColor, color)
end

//part of Neopixel conf files

On the receiving end, there is a Wemos D1 mini that controls a NeoPix strip. The ‘color’ string is split in its separate RGB values. As such it could also be used for an RGB LED or seperate Red, Green, Blue Led’s.
The code is reacting to one MQTT topic, basically switching the entire strip at one go in the desired color and brightness, but I added a structure catching some other MQTT topics that now go to empty routines but that could be used for patterns like a breathing light or a moving pattern. As illustration I added a simple red-blue pattern that responds to MQTT “OpenHab/RGB/scene” with payload “2”  I am using the broker name ‘mosquitto’, if your broker has a different name you needto modify that.

I have to say though that this is not the most efficient way of adding topics, but for beginners it is easiest to follow.
A much more efficient way is to keep the topics of one specified length with only say the last 2 or 3 characters defining the desired action and then only checking for those last characters. A good example of this is for instance in the gateway or sonoff code on https://github.com/computourist/ESP8266-MQTT-client4. For readability sake however, in this example I have chosen to use a more traditional approch and as long as you just want to control some LEDs it is easier.

The ESP8266 code does send some information back: it returns the software version, the IP number and the RSSI.
With regard to the software version and IP number… if you have several ESP8266’s and or Arduino’s in your system, it is easy to lose track which one does what and with what software.

The ESP8266 code is OTA updateable
I have used a fork of the O’Leary PubSub library that makes it easier to send variables as the MQTT payload without having to resort to setting up buffer space and using c_string. Library is here4: https://github.com/Imroy/pubsubclient4.
If you already have the O’Leary PubSub library installed, you will need to put the library files in your sketch folder and change #include <PubSubClient.h> into #include “PubSubClient.h”

Sending predefined colors
If next to the Colorpicker you also want to be able to send predefined colors via a button, then you only need to add some lines in the items and sitemap file:

add to itemsfile:

    Switch NEO_RED	"Red"	<red> {mqtt=">[mosquitto:OpenHab/RGB:command:ON:255,0,0]"}
    Switch NEO_YELLOW	"Yellow"	<yellow>	{mqtt=">[mosquitto:OpenHab/RGB:command:ON:100,96,0]"}
    Switch NEO_BLUE	"Blue"	<darkblue>{mqtt=">[mosquitto:OpenHab/RGB:command:ON:0,0,255]"}

add to the sitemap:

Switch item=NEO_RED mappings=[ON="ON"]
Switch item=NEO_YELLOW mappings=[ON="ON"]
Switch item=NEO_BLUE mappings=[ON="ON"]

As it can be a bit of a bother to find and type all the codes for the colors you may want, I added for download some 160 predefined color settings to pick and add to your sitemap and itemsfile, including some simple icons. As these items already send an R,G,B, code they do not need the rulesfile, only the colorpicker does.

How about Sliders
Perhaps you do not want to use a colorpicker but just individual sliders for Red, Green and Blue.
That is quite easy too.
add the following to your itemsfile:

Dimmer NEO_SLIDERRED "Neopixel Red [%d %%]"  <red> {mqtt=">[mosquitto:OpenHab/RGB/RED:command:*:default]"}
Dimmer NEO_SLIDERGREEN "Neopixel Green [%d %%]" <green> {mqtt=">[mosquitto:OpenHab/RGB/GREEN:command:*:default]"}
Dimmer NEO_SLIDERBLUE "Neopixel Blue [%d %%]" <blue> {mqtt=">[mosquitto:OpenHab/RGB/BLUE:command:*:default]"}

and this to your sitemap

Slider item=NEO_SLIDERRED 
Slider item=NEO_SLIDERGREEN
Slider item=NEO_SLIDERBLUE

Normally that would be enough already, but our ESP8266 program is expecting one input rather than seperate RGB inputs. That is because the colorpicker we used before sends one string of info.
We could add topics to the ESp8266 program to respond to individual RG and B values (and that is what the MQTT topics OpenHab/RGB/RED, OpenHab/RGB/GREEN, and OpenHab/RGB/Blue would be for), but it might be easier to combine those and send as one. For that we need a new rule.

add this to your rules file:

rule "Send  RGB items from slider"
when
Item NEO_SLIDERRED changed or
Item NEO_SLIDERGREEN changed or
Item NEO_SLIDERBLUE changed
then
val redValue=  Math::round(2.55* (NEO_SLIDERRED.state as DecimalType).intValue)
val greenValue=  Math::round(2.55* (NEO_SLIDERGREEN.state as DecimalType).intValue) //
val blueValue=  Math::round(2.55* (NEO_SLIDERBLUE.state as Number).intValue)
val color = redValue + "," + greenValue + "," + blueValue
	sendCommand( RGBLedColor, color)
end

While we are at it
If you want the Filename, IP number and RSSI to show up, add the following to your items file:

Number W_RSSI  "RSSI [%d dbm]" <signal>  {mqtt="<[mosquitto:home/nb/weer/RSSI:state:default]"}
String W_IP "IP [%s]" <network>   {mqtt="<[mosquitto:home/nb/weer/IP:state:default]"}
String W_version "Software versie [%s]" <version>  {mqtt="<[mosquitto:home/nb/weer/version:state:default]"}
String W_MAC "MAC [%s]" <mac> (Wweather) {mqtt="<[mosquitto:home/nb/weer/mac:state:default]"}
Number W_IP_Uptime "Uptime [%d min]" <clock> (Wweather) {mqtt="<[mosquitto:home/nb/weer/uptime:state:default]"}

and the following lines to your sitemap:

   Text item=W_RSSI
   Text item=W_IP
   Text item=W_version
   Text item=W_MAC
   Text item=W_IP_Uptime

download11
https://drive.google.com/open?id=0B9IqgvBSA4aUVzgzRE9MUUY3U2M11

Although I tried on a Wemos D1 mini, I presume this will also work perfectly on the ESP8266-01. Perhaps a great way to use those if you still have on your scrapheap as this is typically a minimal pin project.

The ESP8266 program
The Esp8266 program is rather self explanatory and going into it too deep might fall outside the openhab scope a bit, but in brief, you will find several ino files and a userconfig.h file. These all should be in the same directory and it is sufficient to open the NeopixelOpenhab_vx.ino file in your IDE. The other files will then open up too.

You need to make a few modifications in the userdata.h file.

The essential changes are your password, your SSID and the address of your MQTT server. The other options are indeed ‘optional’, can leave them as is.
the Filename is sent back to openhab as an MQTT message, so in the future you will still know what file it was you put in your ESP8266. obviously you would need to fill out the correct filename. Maybe there is a possibility to automatically pull the filename from the system but if it is, then I haven’t found out about it yet

Advertisements

Driving an IR LED: constant current source or not

If one uses an IR LED for remote control, it is generally unwise to hang that LED directly (with a series resistor ofcourse) on the Output pin of your Arduino (or other microcontroller). The I/O pin of an Arduino can deliver 20mA, which is generally enough for a regular LED, but IR LED’s usually have a taste for more current as they have to bridge a distance to the receiver (such as a TV).
There are basically two ways to drive an IR LED then: with a transistor (or a FET for that matter) that has the LED plus series resistor in the collector (or drain) line or with a constant current source.

Now ‘constant current source’ in this aspect is a bit odd as the LED will be switched on and off so the current is not constant, but it refers to the current that flows to the LED in ‘open’ state.

Both the regular ttansistor driver  and the constant current source have their pro’s and con’s sp lets discuss both.

IR-leddriverSuppose we want to drive 2 IR LED’s -say the IR204- from a 5 Volt source and we do that with a simple transistor driver as pictured to the right. As we want to drive then with 200mA a simple BC547 isnt enough so we have chosen for the  BC337. Around a collector current of 200mA the hFe is 80 and the Vcc is 0.7V.
That leads to the component values as pictured to the right, but the only value we really need to be concerned about is R1 that has a value of 6.5 Ohm at 0.26 Watt. One could use a 1/4 Watt transistor for that as the LED is not always on.

 

IR stroombronSuppose we want to do the same with a constant current source, as pictured in the  bottom figure to the right. Basically this needs 2 extra components (the 2 diodes) and a resistor in the emitter line rather than in the collector line.
The principle of a constant current source  probably is known: The two diodes keep the base of the transistor at 1.2V. Consequently the Emittor of the transistor is at 1.2-0.7=0.5Volt. Therefore the Current  through the transistor is defined by Ve/R1 and at a value of 2.5 that makes 200mA. The dissipation in the resistor is 0.5*0.2=0.1 Watt.

So what are the advantages of  the constant current source over the  simple transistor driver?
Well, there are a few:

  • The resistor can be of a lower wattage: 100mW vs 260mW. That might not seem such a big issue, but if you are driving a bigger current, that could be an issue.
  • Suppose you want to change the voltage? With the constant current source you just up the voltage and that is it. With the simple transistor driver you will need to re-calculate the series resistor, both in resistance as well in Wattage.
  • Same goes for adding more IR LED’s (as long as the supplied voltage allows it): no need to recalculate the value of R1
    So doesnt the simple transistor driver have any advantages?
  • It lacks two components
  • With the two IRLED’s it can still work with a voltage as low as 3.7 Volt, whereas The Constant Current source needs at least 4.2 Volt (if you use 2 IR LEDs).
  • If you are using 3.3 Volts both circuits can be used if you drop one IR LED. However should you still need 2 IR LED’s you are out of luck with the constant current source as it is  risky to put two LED’s  directly parallel if they are not exactly the same. With the simple transistor driver it is always possible to put two or more different IR LED’s parallel when they each have their own  series resistor.

So, what is best for you, depends on your situation. If you are exactly sure what you are building, you know what your number of LED’s needs to be and what Vcc they will be getting, the simple transistor driver is probably best.
If you just want a more universal module that you can use in various situations, then the constant current source is probably better.

“You forgot to mention the constant current circuit uses less energy”
Now there are  a few fairy tales about the constant current source vs the simple driver. One of them is particularly persistent and it claims that the constant current source ‘uses less energy’ than the transistor driver.
That of course is complete bogus. It is probably based on the perception that  -as shown above-  a lot of energy is dissipated in the series resistor R1 and less in the emittor resistor (0.26 Watt vs 0.1 Watt in our example). That is a complete misunderstanding of the formula P=I*V.
If you just look at the Supply voltage (5 Volt) and the current that flows (200mA), the power usage of both circuits is 1 Watt. Sure, it is true that of that 1 Watt in one case 0.26 Watt is used by the series resistor as opposed to  0.1 Watt in the emittor resistor, but that doesnt change the overall use of 1 Watt  by both circuits.
So there is more power available for the IR LED !”   Nope, we have constructed both circuits  such that the LED’s get 200mA. Over 3 Volts (as they are in Series)  that means that the LED’s dissipate 0.6 Watt in both circuits.
Ah see 0.6 Watt + 0.26 Watt = 0.86 Watt while 0.6 Watt + 0.1 Watt =0.7 Watt, so the constant current source IS using less energy
Nope, as said before  both circuits  use 5*0.2 = 1 Watt. The difference of the 0.26-0.1=0.16 Watt is in the transistor. In the Simple driver the transistor dissipates (1-0.86=) 0.14 Watt  but in the constant current source the transistor dissipates (1-0.7=) 0.3 Watt.
The 0.14 Watt dissipation in the transistor also follows from Vce*Ic=0.7*0.2=0.14mW. Now ofcourse the believers in the fairy tale will say:
“But the same goes for the Vce*Ic in the constant current circuit that also uses 0.14 Watt and not 0.3 Watt

Again wrong and it illustrates the complete misunderstanding of what a constant current source does. It keeps the current constant and it does that by changing the resistance of the Vce pathway. So the Vce of 0.7 Volt is for that transistor to be in full saturation and that is exactly that that transistor is not

 

Power LED drivers

R2 determines the current.
Calculations:
– LED current is approximately equal to: 0.5 / R2
– R3 power: the power dissipated by the resistor is approximately: 0.25 / R2.
choose a resistor value at least 2x the power calculated so the resistor does not get burning hot. so for 700mA LED current: R2 = 0.5 / 0.7 = 0.71 ohms. closest standard resistor is 0.75 ohms. R2 power = 0.25 / 0.71 = 0.35 watts. we’ll need at least a 1/2 watt rated resistor.
led-driver3

The design of this LED driver is very simple and probably can be found in many variations on the interenet: T2 operates in linear mode and acts as a variable resistor that controls the current through the LED’s. R1 pulls-up the gate of T2 so that T2 starts up in its conductive state.
As the current begins to flow through the LED’s, T2, and R2, the voltage drop across R2 increases until it is high enough to switch on T1, and in so doing starts to pull the gate of T2 to ground.
This causes T2 to increase its resistance, which decreases current flow through itself, the LED’s, and R2, which decreases the voltage drop across R2, which causes T1 to let T2’s gate float back toward positive supply, thus increasing the current flow. Within a few milliseconds, the current flow stabilizes around a specific set point determined by the value of R2. The required supply voltage overhead is only about 0,6-1.2 volts, less than half of what for instance an LM317 regulator circuit requires.

As the value of R2 is based on the transition emitter-base voltage of T1, calculating it is easy. Most conventional silicon general-purpose NPN transistors switch fully at around 0.7VDC and start to transition from off to on at 0.56-0.58VDC. Assuming a transition voltage of 0.58VDC and a target load current of 320mA, the math is as follows (Ohms law):

R = V / I
R = 0.58VDC / 0.320A
R = 1.8 Ohms

Calculating the power dissipation for R2 under normal operation is done by Watt’s Law:

P = V * I
P = 0.58VDC * 0.320A
P = 0.185 Watt

In this case a quarter-watt resistor will work but a one-watt would have a safety margin of double. Using a design with an LM317 would lead to a much greater loss.

Choosing the input voltage is simple. In the example above I have used 3 LED’s, so you would have to total the forward voltage of those and add about 1.2 Volts:

For example:
Supply voltage for red LEDs=3*2.5V+1.2V=8.7V
Supply voltage for blue LEDs=3*3.8V+1.2V=12,6V

Perhaps you could even get away with an excess voltage of 0.6 instead of 1.2 Volts

The circuit has a disadvantage: It tries to push as much current through the load as it can as long as the voltage across R2 doesn’t exceed what starts to turn T1 on. So, for increased fault tolerance, the power rating for R2 could be selected based on the worst-case scenario of the maximum amount of available current flow in the event of a failure: a short across the LED’s as well as T2. For that, simply calculate dropping the supply power (voltage times current) across R1. It’s generally cheaper to simply use a fuse rated for just above the desired current set point, though, as a power supply providing 1A @ 12VDC would require a 15-watt resistor for R2 and this would be far more costly than a simple fuse.

Dissipation through the MOSFET under operating conditions is calculated the same way, only the voltage used in the calculation should be the supply voltage so that the heatsink selection will account for the worst-case scenario of a dead-shorted load at the target current. In the above example, assuming a 12VDC supply and 320mA current limit, the math works out as follows:

P = V * I
P = 12VDC * 0.750A
P = 3.84 watts

The IRF520 can handle 9.2A at 100VDC, and can dissipate 60 watts, so only a modest heatsink might be necessary.
To calculate dissipation through T2 with an accidentally shorted load, simply calculate the maximum supply power that T2 will see. If the supply is unregulated and capable of large current flows in short time spans (e.g., batteries), again a fuse would be wise as a last-ditch protective measure against catastrophic failures by blowing the circuit open so it cannot try to short the supply. If the set current is 320mA, a 500mA fuse in series with this circuit would be a wise, and relatively inexpensive, addition – all the more so for portable projects using lithium batteries, given how these like to catch fire (and for nonrechargeable lithium primaries, explode) when shorted.
The only limiting factors on load current and supply voltage relate to the components – using a suitable resistor for R2, this circuit can easily regulate up to a few amps of current in as little as one square inch of board space. R1 is not too critical: 1Megaohm will work and I also have seen 10k for R1 and 33Ohm for R2 driving 3 LED’s at a 12 V supply. A good way to calculate the value of R1 is: R1= (Vcc – 1.4)/(I/20)

If you need precision, the easiest way to get it is to build a test circuit with a fixed supply (12VDC is a great value, but use the desired or intended supply voltage if there’s a need to be precise), a dead short for a load, and a 100 ohm resistor for R2. This will set the current limit to about 6mA. Once the circuit is powered up, measure the drop across R2 to determine the exact transition voltage for T2, and calculate a specific value for R2 for your current requirements based on the math described earlier.

PWMled-driver4
The extra parts for PWM support include T3, R3. Since T3 is a PNP transistor and R4 biases its base to ground, T3 starts up turned on and pulls T1’s gate to ground regardless of what T2 is doing, and this forces both T1 and T2 to turn off. R3 limits current draw to the PWM signal source. Provide a positive voltage greater than ~0.7VDC to T3 through R3, and T3 turns off, which allows the rest of the regulator to function as described above. In this manner a PWM signal can be used to vary the brightness of a load of power LEDs, or a simple on-off switch effect can be implemented by merely pulling T3’s base to positive supply with a few milliamperes of current. In this manner it would be possible to use the circuit as a self-current-limiting switch that only needs a tiny little low-current button as its actuator even though the load could be an amp or more.

For LEDs, this circuit is  very simple and wastes very little power if the source and load voltages are kept close to each other. Ideally this circuit works most efficiently with the supply being right at 1.5VDC above the ideal load voltage at the set current. The power source should be able to supply the required amount of current.

If the circuit is used for other loads than LED’s there will be some ripple depending on the type of load being powered, especially during power-up, but decoupling capacitors could be used to compensate for this. The circuit can be driven directly from any logic circuit (even at 3.3VDC).

The circuit can drive resistive, inductive, capacitive, or mixed loads. Capacitive loads may well experience slower charge times, as the circuit will clamp the charge current. Inductive loads should be paralleled with a reverse-polarity diode as is common with e.g. relais (and in some cases, also a proper snubber capacitor) to suppress any back-EMF from the load when power is disconnected so that the voltage spike won’t damage the MOSFET. (Most power MOSFETs include integrated protection diodes, but this should never be relied upon as the sole protection mechanism.)

A simple LED driver with a 2N3055
led-driver5

Even simpler
If you do not have a MOSFET, but you happen to maybe still have an old trusty 2N3055 (or similar like the TIP series) workhorse laying around, the following circuit is for you:

The current is determined by R2 and is:
I =0.8/R2

The maximum value of I in this driver is 10A. .
DC-power supply 9V-15V DC

R2 for 1W LED -2.7ohms 1W
R2 for 3W LED -1.5-ohms 1W
R2 for 5W LED -0.6-ohms or 2 x 1.2-ohms/1W in parallel

Using an LED
stroombron2 Instead of 2 diodes it is also possible to use an LED to set the reference voltage. Ofcourse for this one needs to know the exact voltage of the LED.
Calculations of the resistors is as follows:
R1=(Vd-Vbe)/IR1
R2=(Vs-Vd)/(Id*KB) in which Vd= the LED voltage, Id the current through the circuit LED and where K = 1.2 to 2 (so that R1 is low enough to ensure adequate IB)

LED Fade

/*
* Code for cross-fading 3 LEDs, red, green and blue, or one tri-color LED, using PWM
* The program cross-fades slowly from red to green, green to blue, and blue to red
*
* Clay Shirky <clay.shirky@nyu.edu>
*/

// Output
int redPin   = 9;   // Red LED,   connected to digital pin 9
int greenPin = 10;  // Green LED, connected to digital pin 10
int bluePin  = 11;  // Blue LED,  connected to digital pin 11

// Program variables
int redVal   = 255; // Variables to store the values to send to the pins
int greenVal = 1;   // Initial values are Red full, Green and Blue off
int blueVal  = 1;

int i = 0;     // Loop counter
int wait = 50; // 50ms (.05 second) delay; shorten for faster fades
int DEBUG = 0; // DEBUG counter; if set to 1, will write values back via serial

void setup()
{
pinMode(redPin,   OUTPUT);   // sets the pins as output
pinMode(greenPin, OUTPUT);
pinMode(bluePin,  OUTPUT);
if (DEBUG) {           // If we want to see the pin values for debugging…
Serial.begin(9600);  // …set up the serial ouput on 0004 style
}
}

// Main program
void loop()
{
i += 1;      // Increment counter
if (i < 255) // First phase of fades
{
redVal   -= 1; // Red down
greenVal += 1; // Green up
blueVal   = 1; // Blue low
}
else if (i < 509) // Second phase of fades
{
redVal    = 1; // Red low
greenVal -= 1; // Green down
blueVal  += 1; // Blue up
}
else if (i < 763) // Third phase of fades
{
redVal  += 1; // Red up
greenVal = 1; // Green low
blueVal -= 1; // Blue down
}
else // Re-set the counter, and start the fades again
{
i = 1;
}

analogWrite(redPin,   redVal);   // Write current values to LED pins
analogWrite(greenPin, greenVal);
analogWrite(bluePin,  blueVal);

if (DEBUG) { // If we want to read the output
DEBUG += 1;     // Increment the DEBUG counter
if (DEBUG > 10) // Print every 10 loops
{
DEBUG = 1;     // Reset the counter

Serial.print(i);       // Serial commands in 0004 style
Serial.print(“\t”);    // Print a tab
Serial.print(“R:”);    // Indicate that output is red value
Serial.print(redVal);  // Print red value
Serial.print(“\t”);    // Print a tab
Serial.print(“G:”);    // Repeat for green and blue…
Serial.print(greenVal);
Serial.print(“\t”);
Serial.print(“B:”);
Serial.println(blueVal); // println, to end with a carriage return
}
}
delay(wait); // Pause for ‘wait’ milliseconds before resuming the loop
}