Ich habe vor einiger Zeit mal angefangen den Arduino Mega und das Ethernet Shield von Sainsmart zu einem kleinen Controller für das Wohnzimmer aufzubauen. Es soll zum Schluss folgende aufgaben übernehmen:
- Schalten von 434 Mhz Funk-Schalt Steckdosen
- Ansteuerung einer kleinen RGB-LED leiste für die Vitrine (meine alte Dioder Leiste)
- Senden von IR-Signalen
- Messen der Temperatur im Raum
Dazu hatte ich alle Komponenten einzeln getestet und mit kleinen versuche die einzelnen Bibliotheken kennen gelernt. Für den Bestellten 434 Mhz Sender verwende ich die RC-Switch Bibliothek. Um die IR-Signale zu senden benutze ich die erweiterte IR-Bibliothek CY´s IRib. Das Messen der Temperaturen erfolgt durch die Dallas Temperature Control Bibliothek wie schon in meinen anderern Beiträgen. Die RGB-Leiste steuere ich über die PWM PINs des Arduino selber. Für die Steuerung verwende ich die MQTT PubSubClient Bibliothek. Die Verwendung von MQTT und dem Arduino hatte ich auch schon früher Beschrieben.
Der Aufbau
Für die ersten Tests hatte ich am Anfang alles auf einem Steckbrett getestet. Der Aufbau ist für jede Funktion weiter gewachsen.
434 Mhz Empfänger
Der Empfänger ist extra am 12v des Netzteils angeschlossen. Der Sender darf laut Datenblatt an 1,5V – 12V betrieben werden. Am Anfang hatte ich den Sender an 5V aber an 12V ist die Sendeleistung wesentlich besser und die Funksteckdosen schalten zuverlässiger. Am Arduino ist der Dateneingang an PIN 40.
IR-LIB
Die Infrarot Diode ist von meiner alten Microsoft MCE Fernbedienung. Am USB-Empfänger waren kleine IR-Dioden für das schalten eines Satelliten Receivers dabei. Es sind aber auch andere IR-Dioden möglich. Man findet zu den Dioden und den Aufbau der Schaltung auf der Seite der Bibliothek sehr gute Anleitungen.
Am Arduino MEGA verwende ich den PIN 46. Dieser ist nicht frei wählbar, den er ist von den verwendeten Timer abhängig. Am besten guckt man im Ordner der IRLib Bibliothek nach der Datei “IRLibTimer.h”. Wenn man diese mit einem Texteditor öffnet findet man Abfragen zum Typ des Boards. Innerhalb der Sektionen der Boards kann man den PIN bzw. den dazugehörigen Timer wählen. Wenn man mehrere Bibliotheken in Verwendung hat die einen Timer benötigen, ist es sehr wichtig das man unterschiedliche Timer benutzt. Ich verwende Timer5 und muss deswegen PIN 46 benutzen.
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //#define IR_SEND_TIMER1 11 //#define IR_SEND_TIMER2 9 //#define IR_SEND_TIMER3 5 //#define IR_SEND_TIMER4 6 #define IR_SEND_TIMER5 46
Mann muss ein wenig aufpassen den wenn man den Timer ändert, wird dieser für ein anderes Sketch auch verwendet.
Beim Anschluss habe ich erst eine Transistorschaltung vor der Diode um die Leistung zu erhöhen. Dies hat aber in Zusammenhang mit der LED-Leiste zu einer hohen Last geführt und der Arduino hat sich aufgehängt. Deswegen habe ich die Diode ohne Vorwiderstand direkt angeschlossen. Die genaue Schaltung im Kopf der Diode kenne ich nicht und mit Vorwiderstand war das senden der Befehle erfolgreich. Eine normale IR-Diode braucht sicher ein Vorwiderstand.
Temperatur Sensoren
Die Temperatur Sensoren sind wie in meinen anderen Beiträgen angeschlossen. Am MEGA verwende ich aber PIN 33.
RGB LED
Beim RGB LED Strip habe ich mich an den Aufbau wie bei meinem Nachtlicht gehalten. Die Stromversorgung kommt auch von einem externen 12V Netzteil. Die 12V werden über drei STP16NF06 MOSFETs gesteuert. Sehr gute Beschreibungen findet man im Internet. Der Aufbau ist oft ein wenig anders, je nachdem wie die Eingänge geschaltet werden. Ich habe jeden Eingang mit eine 10kOhm Widerstand an Messe gelegt. Dadurch ist der Eingang immer auf “LOW”, bis ich den Eingang mit dem Arduino schalte. Dieser Aufbau funktionierte für mich am besten und zuverlässigsten
Hierbei sei nochmals drauf hingewiesen das die meisten Schaltungen nicht von mir kommen und ich auch keine Garantie auf Richtigkeit gebe. Alles ist auf eigene Gefahr. Generell habe ich im Internet viele Schaltungen gefunden, die fehlerhaft waren oder einfach kleine Fehler im Aufbau haben. Dabei zerstört man leicht Bausteine.
Einbau im Gehäuse
Danach habe ich alles in ein kleines Gehäuse gebaut, damit es geschützt ist. Die Anschlüsse sind alle über Molex Stecker ausgeführt.
Software
openHAB Items
Number wzGrad1 "Temperatur 1 [%.1f °C]" <temperature> (gWohnzimmer) {mqtt="<[localbroker:/openHAB/wzGrad1:state:default]"} Number wzGrad2 "Temperatur 2 [%.1f °C]" <temperature> (gWohnzimmer) {mqtt="<[localbroker:/openHAB/wzGrad2:state:default]"} Switch LGTV_Power "Power" <power> (gLGTV) { mqtt=">[localbroker:/openHAB/wzIR/NEC32:command:ON:551494620],>[localbroker:/openHAB/wzIR/NEC32:command:OFF:551527260]" } String LGTV_Input "Eingang" <input> (gLGTV) { mqtt=">[localbroker:/openHAB/wzIR/NEC32:command:TV:551512980],>[localbroker:/openHAB/wzIR/NEC32:command:HDMI1:551515020], Color wzVitrine "TV Vitrinenlicht" <slider> (gVitrine) Dimmer wzVitrine_All "Helligkeit [%d %%]" <switch> (gVitrine) Dimmer wzVitrine_R "Rot [%d %%]" <switch> (gVitrine) {mqtt=">[localbroker:/openHAB/wzVitrine/RED:state:*:default]"} Dimmer wzVitrine_G "Grün [%d %%]" <switch> (gVitrine) {mqtt=">[localbroker:/openHAB/wzVitrine/GREEN:state:*:default]"} Dimmer wzVitrine_B "Blau [%d %%]" <switch> (gVitrine) {mqtt=">[localbroker:/openHAB/wzVitrine/BLUE:state:*:default]"}
openHAB RGB-LED Regel
import org.openhab.core.library.types.* var HSBType hsbValue var int redValue var int greenValue var int blueValue var String RGBvalues rule Startup when System started then redValue = 0 greenValue = 0 blueValue = 0 postUpdate(wzVitrine_R, redValue) postUpdate(wzVitrine_G, greenValue) postUpdate(wzVitrine_B, blueValue) postUpdate(wzVitrine, OFF) end rule "Set wzVitrine value" when Item wzVitrine changed then hsbValue = wzVitrine.state as HSBType redValue = hsbValue.red.intValue greenValue = hsbValue.green.intValue blueValue = hsbValue.blue.intValue postUpdate(wzVitrine_R, redValue) postUpdate(wzVitrine_G, greenValue) postUpdate(wzVitrine_B, blueValue) RGBvalues= "Values" + redValue.toString + ";" + greenValue.toString + ";" + blueValue.toString logInfo( "wzVitrine", RGBvalues ) end
Arduino Sketch
Der Arduino Sketch ist im moment immer noch in Bearbeitung. Anbei mein aktueller Stand.
#include <SPI.h> #include <Ethernet.h> #include <PubSubClient.h> #include <RCSwitch.h> #include <OneWire.h> #include <DallasTemperature.h> #include <IRLib.h> // debug = 1 Schlatet die Serielle ausgabe ein. int debug = 0; // -------------------------------- // Ethernet Server // http://arduino.cc/de/Reference/Ethernet // -------------------------------- // MAC Adresse des Ethernet Shields byte ethMac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x33, 0xE5 }; EthernetClient ethClient; // -------------------------------- // MQTT Client // http://knolleary.net/arduino-client-for-mqtt/ // -------------------------------- byte MQTTserver[] = { 192, 168, 2, 9 }; PubSubClient MQTTClient(MQTTserver, 1883, callback, ethClient); // -------------------------------- // LED Leiste // -------------------------------- // Pins des RGB LED Strip int LEDredPIN=5; int LEDgreenPIN=6; int LEDbluePIN=3; // Übermittelte Farbwerte int LEDredValue = 0; int LEDgreenValue = 0; int LEDblueValue = 0; // Gerade gesetzte Farbe int LEDredCurrent = 0; int LEDgreenCurrent = 0; int LEDblueCurrent = 0; // Timervariable für eine Verzögerung. Als alternative zu delay was die verarbeitung anhält. int LEDtimer = 0; int LEDendTimer = 50; // -------------------------------- // RC-Switch // https://code.google.com/p/rc-switch/ // -------------------------------- RCSwitch RCsender = RCSwitch(); String rcID = ""; // Übermittelte ID String rcCommand = ""; // Übermittelter Befehl char rcID1[6]; // ID erster Teil char rcID2[6]; // ID zweiter Teil // -------------------------------- // Infrarot // http://tech.cyborg5.com/2013/03/14/irlib-tutorial-part-1-hardware-set-up/ // Timer PINs Übersicht http://playground.arduino.cc/Main/TimerPWMCheatsheet // Timer setzen für MEGA 2560 in IRLibTimer.h - #define IR_SEND_TIMER5 46 // -------------------------------- IRsend My_Sender; int IRprot = 0; long IRcode = 0; int IRbit = 0; // -------------------------------- // Temperatur // http://milesburton.com/Main_Page?title=Dallas_Temperature_Control_Library // http://www.pjrc.com/teensy/td_libs_OneWire.html // -------------------------------- #define ONE_WIRE_BUS 33 OneWire oneWire(ONE_WIRE_BUS); #define TEMPERATURE_PRECISION 9 DallasTemperature sensors(&oneWire); DeviceAddress TEMPDeviceAddress; // Variable zum zwischenspeichern der Adresse eines Sensors unsigned long TEMPtimer; unsigned long TEMPendTimer = 300000; // Schleifendurchläufe bis neue Abfrage startet float TEMPSensor1 = 0; float TEMPSensor2 = 0; char TEMPChar[10]; // Hilsfvariable zu Konvertierung String TEMPAsString; // Ausgelesene Temperatur als String int TEMPDeviceCount = 0; //================================================================================================================ void setup() //================================================================================================================ { if (debug == 1) { Serial.begin(9600); Serial.println("Wohnzimmer 2.04"); } // -------------------------------- // LED Leiste // -------------------------------- // Setzen der PINS als Ausgang pinMode(LEDbluePIN, OUTPUT); pinMode(LEDredPIN, OUTPUT); pinMode(LEDgreenPIN, OUTPUT); // Bei start Farbe Blau setzen analogWrite(LEDredPIN, 0); analogWrite(LEDgreenPIN, 0); analogWrite(LEDbluePIN, 10); // -------------------------------- // Ethernet Server // -------------------------------- // Initialisierung des Ethernets if (Ethernet.begin(ethMac) == 0) { // Wenn DHCP fehlschlägt dann rot setzen und aufhören analogWrite(LEDredPIN, 100); analogWrite(LEDgreenPIN, 0); analogWrite(LEDbluePIN, 0); while (true); } else { // Wenn DHCP OK ist dann grün setzen LEDgreenValue = 10; if (debug == 1) { Serial.print("IP-Adresse:"); Serial.println(Ethernet.localIP()); } } // -------------------------------- // RC-Switch // -------------------------------- RCsender.enableTransmit(40); RCsender.setRepeatTransmit(15); // -------------------------------- // Temperatur // -------------------------------- sensors.begin(); TEMPDeviceCount = sensors.getDeviceCount(); TEMPtimer = TEMPendTimer + 1; for(int i=0 ; i < TEMPDeviceCount; i++) { if(sensors.getAddress(TEMPDeviceAddress, i)) { sensors.setResolution(TEMPDeviceAddress, TEMPERATURE_PRECISION); } } if (debug == 1) { Serial.print("Temperatur Sensoren: "); Serial.println(TEMPDeviceCount, DEC); } } // void setup() //================================================================================================================ void loop() //================================================================================================================ { // -------------------------------- // MQTT Client // -------------------------------- // Aufbau der Verbindung mit MQTT falls diese nicht offen ist. if (!MQTTClient.connected()) { MQTTClient.connect("arduinoWZVitrine"); // Abonieren von Nachrichten mit dem angegebenen Topics // MQTTClient.subscribe("/openHAB/wzVitrine/RED/#"); // MQTTClient.subscribe("/openHAB/wzVitrine/GREEN/#"); // MQTTClient.subscribe("/openHAB/wzVitrine/BLUE/#"); MQTTClient.subscribe("/openHAB/wzVitrine/#"); // RC Steckdosen Commands MQTTClient.subscribe("/openHAB/wzRC/#"); // IR Signale // http://192.168.2.21/ir&1&551494620&32 MQTTClient.subscribe("/openHAB/wzIR/NEC32/#"); } // -------------------------------- // LED Leiste // -------------------------------- if (LEDtimer <= LEDendTimer) LEDtimer++; else { LEDtimer = 0; if (LEDredValue < LEDredCurrent) LEDredCurrent--; else if (LEDredValue > LEDredCurrent) LEDredCurrent++; if (LEDgreenValue < LEDgreenCurrent) LEDgreenCurrent--; else if (LEDgreenValue > LEDgreenCurrent) LEDgreenCurrent++; if (LEDblueValue < LEDblueCurrent) LEDblueCurrent--; else if (LEDblueValue > LEDblueCurrent) LEDblueCurrent++; } analogWrite(LEDredPIN, LEDredCurrent); analogWrite(LEDgreenPIN, LEDgreenCurrent); analogWrite(LEDbluePIN, LEDblueCurrent); // -------------------------------- // RC Steckdosen // -------------------------------- if (rcID.length() == 10) { if (debug == 1) { Serial.println("ID : " + rcID); } rcID.toCharArray(rcID1,6); rcID = rcID.substring(5,10); rcID.toCharArray(rcID2,6); if (rcCommand == "ON") RCsender.switchOn(rcID1, rcID2); if (rcCommand == "OFF") RCsender.switchOff(rcID1, rcID2); rcID = ""; } // if (rcID.length() == 10) // -------------------------------- // Infrarot // -------------------------------- // IRprot = 1; IRbit = 32; IRcode = msgString.toInt(); if (IRprot > 0 && IRbit > 0 && IRcode > 0) { if (debug == 1) { Serial.println("IRpro: " + String(IRprot)); Serial.println("IRbit: " + String(IRbit)); Serial.println("IRcode: " + String(IRcode)); } My_Sender.send(IRprot, IRcode, IRbit); IRprot = 0; IRbit = 0; IRcode = 0; } // // -------------------------------- // Temperatur // -------------------------------- if (TEMPtimer <= TEMPendTimer) TEMPtimer++; else { TEMPtimer = 0; sensors.requestTemperatures(); if ( TEMPDeviceCount >= 1 ) { TEMPSensor1 = sensors.getTempCByIndex(0); dtostrf(TEMPSensor1,1,2,TEMPChar); MQTTClient.publish("/openHAB/wzGrad1",TEMPChar); if (debug == 1) { TEMPAsString = String(TEMPChar); Serial.println("Temp1: " + TEMPAsString); } } // TEMPSensor 1 if ( TEMPDeviceCount >= 2 ) { TEMPSensor2 = sensors.getTempCByIndex(1); dtostrf(TEMPSensor2,1,2,TEMPChar); MQTTClient.publish("/openHAB/wzGrad2",TEMPChar); if (debug == 1) { TEMPAsString = String(TEMPChar); Serial.println("Temp2: " + TEMPAsString); } } // TEMPSensor 2 } // else TEMPtimer // -------------------------------- // MQTT Client Loop // -------------------------------- 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) { TEMPtimer = 0; // Wenn eine Nachricht kommt wird der Timer // für die Temperatur auf 0 gesetzt um den Ablauf nicht zu Verzögern // 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); String topString = String(topic); if (debug == 1) { Serial.println("Topic: " + topString); Serial.println("Msg : " + msgString); } // -------------------------------- // LED Leiste // -------------------------------- // Überprüfung des Topics und setzen der Farbe je nach übermittelten Topic if (topString == "/openHAB/wzVitrine/RED") LEDredValue = round(msgString.toInt() * 2.55); if (topString == "/openHAB/wzVitrine/GREEN") LEDgreenValue = round(msgString.toInt() * 2.55); if (topString == "/openHAB/wzVitrine/BLUE") LEDblueValue = round(msgString.toInt() * 2.55); // -------------------------------- // RC Steckdose // -------------------------------- // Wenn das Topic mit "/openHAB/wzRC/" anfängt dann ID und Message ermitteln und schalten if (topString.startsWith("/openHAB/wzRC/")) { rcID = topString.substring(topString.lastIndexOf('/') + 1); rcCommand = msgString; } // if (topString.startsWith("/openHAB/wzRC/")) // -------------------------------- // Infrarot // -------------------------------- //Topic: /openHAB/wzIR/NEC32 //Msg : 551494620 if (topString.startsWith("/openHAB/wzIR/")) { if (topString.substring(topString.lastIndexOf('/') + 1) == "NEC32") { IRprot = 1; IRbit = 32; IRcode = msgString.toInt(); } } } // void callback(
Pingback: Mit HUZZAH(ESP8266) und MQTT eine 433MHz Steckdose schalten – Blue-PC