Sunday 22 May 2016

RGB lights with openHAB & MQTT & ESP8266

So, you want to control an RGB Led or strip or anything, probably using the ESP8266..
It sounds pretty basic and straight forward, but for some strange reason it isn't.


We will use a Colorpicker in openHAB to get a string with three values in the form of RED,GREEN,BLUE.
This string will be sent over IP using MQTT.
An ESP8266 running NodeMCU firmware will get this string and transform it to 3 distinct PWM outputs.
A simple circuit with 3 N-channel MOSFETs can drive any reasonable RGB load..
openHAB and mosquitto run on a Raspberry Pi B+

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

1)  Create a rule in openHAB's configurations/rules folder like this:

import org.openhab.core.library.types.*

/**
* This is a rule for the RGB_LED-Stairs
*/ 
var HSBType hsbValue
var String allValue

rule "Set RGB-Stairs value"
   when
   Item RGB_Stairs changed
   then
   hsbValue = RGB_Stairs.state as HSBType

   allValue = hsbValue.red.intValue + "," + hsbValue.green.intValue + "," + hsbValue.blue.intValue

   postUpdate(RGB_Stairs_rgb, allValue)
end


allValue is a string that gets the RED,GREEN,BLUE value.
RGB_Stairs_rgb is a name I used for my openHAB's item (you can choose different).
If you want to control more than one RGB Leds, you will need to create another similar rule in a DIFFERENT file..


2)  Create two items in openHAB like this:

Color    RGB_Stairs       "RGB Stairs"   <slider>   (All)
String   RGB_Stairs_rgb   "Stairs-RGB"   <switch>   { mqtt=">[broker:/home/RGB/stairsR/RGB:state:*:default]" }



3)  Create an item in sitemap, like this:

Colorpicker item=RGB_Stairs


 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

That's it for openHAB.
I also included it in persistence so the colorpicker gets saved and restored in case of a restart. For that to work, you need to include the Color item in the persistance, not the String (for some strange reason). In my example that is "RGB_Stairs".
Also, not all persistence options will work correctly. db4o and rrd4j work, but mapdb and logging don't (at least for me).

Of course, this will only save and restore the state of the colorpicker in openHAB page, not the actual state of the RGB lights.
To save and restore the actual lights state I used some lua code to save the values in a file. It works OK, but ESP8266 starts misbehave after about a month! If I just re-upload the code, starts working properly again.
If I don't use file access in the code, it stays reliable for months..

 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

The circuit i used with ESP8266 looks like this:

The mosFETs I used are actually the SI2300.
They turn fully ON with 3.3V and handle more than 5Amps.
They are pretty cheap too.

Remember that the sequence of the colors in an RGB strip, is actually G,R,B

 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

The lua code looks like this:

pwm.setup(5, 970, 0) --GPIO.14
pwm.setup(6, 980, 0) --GPIO.12
pwm.setup(7, 990, 0) --GPIO.13
color = {}
-- START
m = mqtt.Client("ESP03-Stairs-RGB", 180, "", "")
-- ON mqtt receive..
m:on("message", function(mpla, topic, input)
-- MQTT is RED,GREEN,BLUE
  RED,GREEN,BLUE = input:match("([^,]+),([^,]+),([^,]+)")
-- convert 0-100 -> 0-1023
  RED = RED*10.23
  GREEN = GREEN*10.23
  BLUE = BLUE*10.23
-- do
  pwm.setduty(5, RED)
  pwm.setduty(6, GREEN)
  pwm.setduty(7, BLUE)
end)
-- if SUBSCRIPTION fails.. RESTART
m:on("offline", function(recon)
  print ("restarting...")
  node.restart()
end)
-- MQTT CONNECT when wifi ready (main routine)
tmr.alarm(0, 2000, 1, function()
  if wifi.sta.status() == 5 and wifi.sta.getip() ~= nil then
  tmr.stop(0)
    m:connect("192.168.1.20", 1883, 0, function(conn) print("Connnected")
       m:subscribe("home/RGB/stairs/RGB", 0, function(conn) print("Subscrbd") end)
    end)
  end
end)


I use a bit different PWM frequency for each color, in an attempt to reduce the flickering.
1KHz PWM is the maximum for the ESP8266 using NodeMCU.



2 comments: