Nachtlicht mit Arduino und MQTT über openHAB steuern

Um zu testen ob die Anbindung eines Arduinos an openHAB über MQTT über eine längere Zeit fehlerfrei funktioniert habe ich ein Nachtlicht gebaut. Es besteht aus einem ca. 15 cm langen rundem Kabelkanal. Darauf habe ich 4 Segmente eines RGB Stripes geklebt. Jeweils zwei Segmente sind in Reihe gelötet. Diese sind parallel an einem Arduino UNO angeschlossen. Der Arduino wird von einem 12V Steckernetzteil mit Strom versorgt. Für den Verbindungsaufbau ist ein Arduino Ethernet Shield aufgesteckt.

Nachtlicht_Steckplatine1
image-347

 

Vorraussetzung ist das openHAB mit MQTT lauffähig ist. Wenn es noch nicht eingerichtet ist am besten den Artikel “MQTT Nachrichten mit dem Arduino empfangen & senden” lesen.

openHAB

openhab.cfg

mqtt:localbroker.url=tcp://localhost:1883
mqtt:localbroker.clientId=openHABserver

 flur.items

Group  gFlur            "Flur"          <corridor> (gAlles)
Group  gNachtlicht      "Nachtlicht"    <corridor> (gFlur)

Color  flNachtlicht     "Nachtlicht"    <slider> (gNachtlicht)
Dimmer flNachtlicht_R   "Rot [%d %%]"   <switch> (gNachtlicht) {mqtt=">[localbroker:/openHAB/Nachtlicht/RED:state:*:default]"}
Dimmer flNachtlicht_G   "Grün [%d %%]"  <switch> (gNachtlicht) {mqtt=">[localbroker:/openHAB/Nachtlicht/GREEN:state:*:default]"}
Dimmer flNachtlicht_B   "Blau [%d %%]"  <switch> (gNachtlicht) {mqtt=">[localbroker:/openHAB/Nachtlicht/BLUE:state:*:default]"}

Auszug aus default.sitemap

 Frame label="Räume" {
    Text label="Flur" icon="corridor" {
    Frame label="Licht" {
       Colorpicker item=flNachtlicht icon="slider"
       Switch item=Test_Switch1
    }
 }

Angezeigt wird auf der openHAB Oberfläche nur ein Colerpicker. Bei änderungen vom Colorpicker wird folgende Regel verwendet um die einzelnen Farbwerte zu errechnen und wiederum den Items für Rot, Grün, Blau zuzuordnen. Dabei wird dann der Status über das MQTT Binding (siehe flur.items) mit dem Topic der einzelnen Farben an MQTT übergeben.

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

var HSBType hsbValue
var int redValue
var int greenValue
var int blueValue
var String RGBvalues

rule "Set flNachtlicht value"
   when
   Item flNachtlicht changed
   then
   hsbValue = flNachtlicht.state as HSBType 

   redValue = hsbValue.red.intValue
   greenValue = hsbValue.green.intValue
   blueValue = hsbValue.blue.intValue

   postUpdate(flNachtlicht_R, redValue)
   postUpdate(flNachtlicht_G, greenValue)
   postUpdate(flNachtlicht_B, blueValue)

   RGBvalues= "Values" + redValue.toString + ";" + greenValue.toString + ";" + blueValue.toString
   logInfo( "flNachtlicht", RGBvalues )

end

Arduino

Das ganze wird an den Arduino übergeben.

Sketch

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h> // http://knolleary.net/arduino-client-for-mqtt/

// MAC Adresse des Ethernet Shields
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
// IP des MQTT Servers
byte server[] = { 192, 168, 2, 9 };
// Ethernet Client zur Kommunikation des MQTT Clients
EthernetClient ethClient;
// MQTT Client zur Kommunikation mit dem Server
// Server - Variable des Types byte mit Serveradresse
// 1883 - Ist der Standard TCP Port
// callback - Function wird aufgerufen wen MQTT Nachrichten eintreffen. Am ende des Sketches
// ethClient - Angabe des Ethernet Clients
PubSubClient mqttClient(server, 1883, callback, ethClient);

// Timervariable für eine Verzögerung. Als alternative zu delay was die verarbeitung anhält.
int timer = 0;
int EndTimer = 200; 

// Pins des RGB LED Strip
int LEDred=5;
int LEDgreen=6;
int LEDblue=3;

// Übermittelte Farbwerte
int LEDredValue = 0;
int LEDgreenValue = 0;
int LEDblueValue = 0;

// Gerade gesetzte Farbe
int CURredValue = 0;
int CURgreenValue = 0;
int CURblueValue = 0;

void setup()
{
 // Setzen der PINS als Ausgang
 pinMode(LEDblue, OUTPUT);
 pinMode(LEDred, OUTPUT);
 pinMode(LEDgreen, OUTPUT);

 // Bei start Farbe Blau setzen
 analogWrite(LEDred, 0);
 analogWrite(LEDgreen, 0);
 analogWrite(LEDblue, 100);

 // Initialisierung des Ethernets
 if (Ethernet.begin(mac) == 0) {
 // Wenn DHCP fehlschlägt dann rot setzen und aufhören
 analogWrite(LEDred, 100);
 analogWrite(LEDgreen, 0);
 analogWrite(LEDblue, 0);
 while (true);
 }
 else {
 // Wenn DHCP OK ist dann grün setzen
 LEDgreenValue = 100;
 }

}

void loop()
{
 // Aufbau der Verbindung mit MQTT falls diese nicht offen ist.
 if (!mqttClient.connected()) {
 mqttClient.connect("arduinoClient");
 // Abonieren von Nachrichten mit dem angegebenen Topics
 mqttClient.subscribe("/openHAB/Nachtlicht/RED/#");
 mqttClient.subscribe("/openHAB/Nachtlicht/GREEN/#");
 mqttClient.subscribe("/openHAB/Nachtlicht/BLUE/#");

 // Alternative Abonierung aller Topics unter /openHAB/Nachtlicht
 // mqttClient.subscribe("/openHAB/Nachtlicht/#");
 }

 if (timer <= EndTimer) timer++;
 else {
 timer = 0;

 if (LEDredValue < CURredValue) CURredValue--;
 else if (LEDredValue > CURredValue) CURredValue++;

 if (LEDgreenValue < CURgreenValue) CURgreenValue--;
 else if (LEDgreenValue > CURgreenValue) CURgreenValue++;

 if (LEDblueValue < CURblueValue) CURblueValue--;
 else if (LEDblueValue > CURblueValue) CURblueValue++;
 }

 analogWrite(LEDred, CURredValue);
 analogWrite(LEDgreen, CURgreenValue);
 analogWrite(LEDblue, CURblueValue);

 mqttClient.loop(); // Schleife für MQTT

}

// ===========================================================
// Callback Funktion von MQTT. Die Funktion wird aufgerufen
// wenn ein Wert empfangen wurde.
// ===========================================================
void callback(char* topic, byte* payload, unsigned int length) {
 // Zähler
 int i = 0;
 // Hilfsvariablen für die Convertierung der Nachricht in ein String
 char message_buff[100];

 // Kopieren der Nachricht und erstellen eines Bytes mit abschließender \0
 for(i=0; i<length; i++) {
 message_buff[i] = payload[i];
 }
 message_buff[i] = '\0';

 // Konvertierung der nachricht in ein String
 String msgString = String(message_buff);

 // Überprüfung des Topis und setzen der Farbe je nach übermittelten Topic
 if (String(topic) == "/openHAB/Nachtlicht/RED") LEDredValue = round(msgString.toInt() * 2.55);
 if (String(topic) == "/openHAB/Nachtlicht/GREEN") LEDgreenValue = round(msgString.toInt() * 2.55);
 if (String(topic) == "/openHAB/Nachtlicht/BLUE") LEDblueValue = round(msgString.toInt() * 2.55);
}

 Ergebniss

Ein kleines Video vom Ergebnis.

13 Comments

  1. Adrian

    I added everything to my configuration but the light doesnt respond to openHAB. It only responds if I send manual mqtt command. For some reason openHAB doesnt send mqtt commands for the rgb light but does for other mqtt devices. I’m ising openHAB 1.71 on RPi2

  2. Paul

    Hi,

    I have got this code working with 2 separate RGB LED lamps.

    I would like to be able to control the colour of the LED through rules, for example when scene 1 is enabled the LED will be Green, When scene 2 is enabled LED will be Blue.

    Do you know how to command the LED from a rule? Currently I am able to turn the LED on through rules but not select a colour.

    Cheers
    Paul

    1. blueAdmin

      Hello,

      you can use a rule like my cron rule

      rule "Nachtlicht An rot"
      when
      // Item Sunset_Event received update ON
      Time cron "0 0 19 * * ?"
      then
      // postUpdate(flNachtlicht, ON)
      redValue = 20
      greenValue = 0
      blueValue = 0

      postUpdate(flNachtlicht_R, redValue)
      postUpdate(flNachtlicht_G, greenValue)
      postUpdate(flNachtlicht_B, blueValue)
      end

      1. Euphi

        Just replace it 🙂

        The used libs are available for ESP8266, too.

        #include
        #include
        #include

        [… var init omitted.. you get the idea]

        void setup(void) {
        pinMode(led_r, OUTPUT);
        pinMode(led_g, OUTPUT);
        pinMode(led_b, OUTPUT);
        digitalWrite(led_r, 0);
        digitalWrite(led_g, 0);
        digitalWrite(led_b, 0);

        WiFi.begin(ssid, password);
        while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(“.”);
        }
        client.setServer(mqtt_server, 1883);
        client.setCallback(callback);
        }

        [….]

        One important note: The maximum value for analogWrite(int, int) is defined in PWMRANGE.

        So you need to multiply the received value with (PWMRANGE/100) – on ESP8266, PWMRANGE is 1023 and not 255 as on most Arduinos.

  3. MaxG

    Nice result!
    I am using OH, and just copied all of it into a blank OH.
    While the OH Nachtlicht switches on, it does not send the RGB values via MQTT.
    MQTT is working and does recieve the 0 messages.
    I am lost? Any ideas?
    2016-08-22 20:22:53 – flNachtlicht received command OFF
    2016-08-22 20:22:53 – flNachtlicht_R state updated to 0
    2016-08-22 20:22:53 – flNachtlicht_G state updated to 0
    2016-08-22 20:22:53 – flNachtlicht_B state updated to 0
    2016-08-22 20:23:01 – flNachtlicht received command ON
    2016-08-22 20:23:07 – flNachtlicht received command 247.91878172588832,77.25490196078431,100
    2016-08-22 20:23:12 – flNachtlicht received command ON
    2016-08-22 20:23:14 – flNachtlicht received command OFF
    2016-08-22 20:23:14 – flNachtlicht_R state updated to 0
    2016-08-22 20:23:14 – flNachtlicht_G state updated to 0
    2016-08-22 20:23:14 – flNachtlicht_B state updated to 0
    2016-08-22 20:23:16 – flNachtlicht received command ON

  4. Ilu

    Hello blueadmin,
    this is a very nice Project! I rebuilt it with a Wemos D1 mini, so everything fits in the original casing of the light strip’s electronics. I used IRF3708 n-channel FETs und no resistors.
    Next Thing I want to do is read the Alarm clock times from my mobile and send it via tasker zu openHAB. I found this solution on another website, but they leave out the tasker configuration! ;-(

  5. Chris

    hello
    I would like to use the sketch but I am not good with programming. I’ve got this message when compiling for arduino uno:
    Arduino: 1.8.3 (Windows Store 1.8.6.0) (Windows 10), Board: “Arduino/Genuino Uno”

    MQTTDimmer:16: error: ‘callback’ was not declared in this scope

    PubSubClient mqttClient(server, 1883, callback, ethClient);

    ^

    exit status 1
    ‘callback’ was not declared in this scope

    Thank you for any help.

  6. Who can help me to control 8 different channels?
    the arduino sketchs works fine i have changed every for 8 channels,
    but i dont know how to get it work on the openhab.

    This is my sketch:
    #include
    #include
    #include // http://knolleary.net/arduino-client-for-mqtt/

    // MAC Adresse des Ethernet Shields
    byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
    // IP des MQTT Servers
    byte server[] = { 192, 168, 1, 12 };
    // Ethernet Client zur Kommunikation des MQTT Clients
    EthernetClient ethClient;
    EthernetClient Client;
    IPAddress broker(192,168,1,12);
    // MQTT Client zur Kommunikation mit dem Server
    // Server – Variable des Types byte mit Serveradresse
    // 1883 – Ist der Standard TCP Port
    // callback – Function wird aufgerufen wen MQTT Nachrichten eintreffen. Am ende des Sketches
    // ethClient – Angabe des Ethernet Clients
    PubSubClient client(ethClient);

    // Timervariable für eine Verzögerung. Als alternative zu delay was die verarbeitung anhält.
    int timer = 0;
    int EndTimer = 200;

    // Pins des DIMMER
    int dim1=4;
    int dim2=5;
    int dim3=6;
    int dim4=7;
    int dim5=8;
    int dim6=9;
    int dim7=10;
    int dim8=11;
    // Übermittelte Farbwerte
    int dim1Value = 0;
    int dim2Value = 0;
    int dim3Value = 0;
    int dim4Value = 0;
    int dim5Value = 0;
    int dim6Value = 0;
    int dim7Value = 0;
    int dim8Value = 0;
    // Gerade gesetzte Farbe
    int CURdim1Value = 0;
    int CURdim2Value = 0;
    int CURdim3Value = 0;
    int CURdim4Value = 0;
    int CURdim5Value = 0;
    int CURdim6Value = 0;
    int CURdim7Value = 0;
    int CURdim8Value = 0;
    void setup()
    {
    // Setzen der PINS als Ausgang
    pinMode(dim8, OUTPUT);
    pinMode(dim7, OUTPUT);
    pinMode(dim6, OUTPUT);
    pinMode(dim5, OUTPUT);
    pinMode(dim4, OUTPUT);
    pinMode(dim3, OUTPUT);
    pinMode(dim1, OUTPUT);
    pinMode(dim2, OUTPUT);

    // Bei start Farbe Blau setzen
    analogWrite(dim1, 0);
    analogWrite(dim2, 0);
    analogWrite(dim3, 100);
    analogWrite(dim4, 0);
    analogWrite(dim5, 0);
    analogWrite(dim6, 100);
    analogWrite(dim7, 100);
    analogWrite(dim8, 100);
    // Initialisierung des Ethernets
    if (Ethernet.begin(mac) == 0) {

    // Wenn DHCP fehlschlägt dann rot setzen und aufhören
    analogWrite(dim1, 100);
    analogWrite(dim2, 0);
    analogWrite(dim3, 0);
    analogWrite(dim4, 0);
    analogWrite(dim5, 0);
    analogWrite(dim6, 0);
    analogWrite(dim7, 0);
    analogWrite(dim8, 0);
    while (true);
    }
    else {
    // Wenn DHCP OK ist dann grün setzen
    dim2Value = 100;
    }

    }

    void loop()
    {
    // Aufbau der Verbindung mit MQTT falls diese nicht offen ist.
    if (!client.connected()) {
    client.connect(“arduinoClient”);
    // Abonieren von Nachrichten mit dem angegebenen Topics
    client.subscribe(“/dd16/dimmer/1/#”);
    client.subscribe(“/dd16/dimmer/2/#”);
    client.subscribe(“/dd16/dimmer/3/#”);
    client.subscribe(“/dd16/dimmer/4/#”);
    client.subscribe(“/dd16/dimmer/5/#”);
    client.subscribe(“/dd16/dimmer/6/#”);
    client.subscribe(“/dd16/dimmer/7/#”);
    client.subscribe(“/dd16/dimmer/8/#”);
    // Alternative Abonierung aller Topics unter /openHAB/Nachtlicht
    // mqttClient.subscribe(“/openHAB/Nachtlicht/#”);
    }

    if (timer <= EndTimer) timer++;
    else {
    timer = 0;

    if (dim1Value CURdim1Value) CURdim1Value++;

    if (dim2Value CURdim2Value) CURdim2Value++;

    if (dim3Value CURdim3Value) CURdim3Value++;

    if (dim4Value CURdim3Value) CURdim3Value++;

    if (dim5Value CURdim5Value) CURdim5Value++;

    if (dim6Value CURdim6Value) CURdim6Value++;

    if (dim7Value CURdim7Value) CURdim7Value++;

    if (dim8Value CURdim8Value) CURdim8Value++;
    }

    analogWrite(dim1, CURdim1Value);
    analogWrite(dim2, CURdim2Value);
    analogWrite(dim3, CURdim3Value);
    analogWrite(dim4, CURdim4Value);
    analogWrite(dim5, CURdim5Value);
    analogWrite(dim6, CURdim6Value);
    analogWrite(dim7, CURdim7Value);
    analogWrite(dim8, CURdim8Value);
    client.loop(); // Schleife für MQTT

    }

    // ===========================================================
    // Callback Funktion von MQTT. Die Funktion wird aufgerufen
    // wenn ein Wert empfangen wurde.
    // ===========================================================
    void callback(char* topic, byte* payload, unsigned int length) {
    // Zähler
    int i = 0;
    // Hilfsvariablen für die Convertierung der Nachricht in ein String
    char message_buff[100];

    // Kopieren der Nachricht und erstellen eines Bytes mit abschließender \0
    for(i=0; i<length; i++) {
    message_buff[i] = payload[i];
    }
    message_buff[i] = '\0';

    // Konvertierung der nachricht in ein String
    String msgString = String(message_buff);

    // Überprüfung des Topis und setzen der Farbe je nach übermittelten Topic
    if (String(topic) == "/dd16/dimmer/1") dim1Value = round(msgString.toInt() * 2.55);
    if (String(topic) == "/dd16/dimmer/2") dim2Value = round(msgString.toInt() * 2.55);
    if (String(topic) == "/dd16/dimmer/3") dim3Value = round(msgString.toInt() * 2.55);
    if (String(topic) == "/dd16/dimmer/4") dim4Value = round(msgString.toInt() * 2.55);
    if (String(topic) == "/dd16/dimmer/5") dim5Value = round(msgString.toInt() * 2.55);
    if (String(topic) == "/dd16/dimmer/6") dim6Value = round(msgString.toInt() * 2.55);
    if (String(topic) == "/dd16/dimmer/7") dim7Value = round(msgString.toInt() * 2.55);
    if (String(topic) == "/dd16/dimmer/8") dim8Value = round(msgString.toInt() * 2.55);
    }

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.