Mein neuestes Projekt ist ein SmartHome-Gateway auf Basis des ESP8266, welches ich euch natürlich hier gerne vorstellen möchte. Momentan implementiert sind ein 433MHz-Sender für Funksteckdosen aller Art, eine IR-Diode sowie ein Temperatur-/Luftfeuchtigkeitssensor. Das Setup lässt sich natürlich beliebig erweitern und den eigenen Bedürfnissen anpassen.
Vorteile zu Lösungen mit Einplatinencomputer wie Raspberry / Banana Pi sind die Robustheit bei Stromausfällen (Stichwort(e) kaputtes Dateisystem) und natürlich auch der sehr günstige Preis.
1. Hardware
Als Board setze ich hier mein NodeMCU-Entwicklungsboard ein, da es praktischerweise über einen USB-Anschluss verfügt und Breadboard-tauglich ist. Außerdem bietet es im Gegensatz zu den kleineren ESP8266-Modellen wie dem ESP-01 wesentlich mehr GPIOs.
Meine (von einer alten Fernbedienung ausgelötete) IR-Sendediode steuere ich über einen Transistor (NPN mit CBE-Reihenfolge [momentan ein BC547]) an, die Basis habe ich mit einem Widerstand von ca. 600Ω mit einem digitalen Pin des Boards verbunden.
Als Temperatur-/Luftfeuchtigkeitssensor nutze ich einen DHT11. Dieser ist nicht sehr genau, aber für meine Bedürfnisse soweit ausreichend. Wer es genauer haben möchte, kann zu dem etwas teureren Modell DHT22 greifen, das sich analog einsetzen lässt.
Für die Funksteckdosen nutze ich schließlich noch einen billigen FS1000A-Transmitter mit externer Antenne. Diesen hatte ich von anderen Projekten noch über. Wer neukauft, sollte lieber einen Superheterodyne-Transmitter einsetzen, den es in China auch bereits für wenige Cent gibt. Dieser hat erfahrungsgemäß eine wesentlich höhere Reichweite und lässt sich ebenso einfach einstecken.
Eine kleine Steckplatinenansicht seht ihr hier:
Und so schaut es bei mir aktuell in der Realität aus:
2. Software
Dieses Projekt mit dem ESP8266 habe ich wieder mit Hilfe der Arduino IDE umgesetzt. Dort gibt es für die Ansteuerung der eingesetzten Sensoren und Aktoren bereits fertige Bibliotheken, sodass die Umsetzung damit sehr simpel ist.
Mein aktueller Sketch sieht insgesamt so aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #include <RCSwitch.h> #include <IRremoteESP8266.h> #include <DHT.h> // WLAN data const char* ssid = "xxx"; const char* password = "xxx"; // static IP IPAddress ip(192,168,11,60); IPAddress gateway(192,168,11,1); IPAddress subnet(255,255,255,0); MDNSResponder mdns; ESP8266WebServer server(80); // set your pin for ir led here IRsend irsend(14); // initialize RCSwitch RCSwitch mySwitch = RCSwitch(); // initialize DHT sensor DHT dht(13,DHT11,15); float humidity, temperature; void handleRoot() { server.send(200, "text/html", "Please specify command!</br>Form IR: /ir?code=xxx&bits=xx&protocol=x</br>Form RC: /rc?group=xxxx&switch=xxxx&action=x</br>Form DHT: /dht?type=x"); } void handleIr(){ String codestring=server.arg("code"); String protocol=server.arg("protocol"); String bitsstring=server.arg("bits"); String webOutput = "Protocol: "+protocol+"; Code: "+codestring+"; Bits: "+bitsstring; if ((codestring != "")&&(bitsstring != "")){ unsigned long code = codestring.toInt(); int bits = bitsstring.toInt(); if (protocol == "NEC"){ irsend.sendNEC(code, bits); server.send(200, "text/html", webOutput); } else if (protocol == "Sony"){ irsend.sendSony(code, bits); server.send(200, "text/html", webOutput); } else if (protocol == "Whynter"){ irsend.sendWhynter(code, bits); server.send(200, "text/html", webOutput); } else if (protocol == "LG"){ irsend.sendLG(code, bits); server.send(200, "text/html", webOutput); } else if (protocol == "RC5"){ irsend.sendRC5(code, bits); server.send(200, "text/html", webOutput); } else if (protocol == "RC6"){ irsend.sendRC6(code, bits); server.send(200, "text/html", webOutput); } else if (protocol == "DISH"){ irsend.sendDISH(code, bits); server.send(200, "text/html", webOutput); } else if (protocol == "SharpRaw"){ irsend.sendSharpRaw(code, bits); server.send(200, "text/html", webOutput); } else if (protocol == "Samsung"){ irsend.sendSAMSUNG(code, bits); server.send(200, "text/html", webOutput); } else { server.send(200, "text/html", "Protocol not implemented!"); } } else { server.send(200, "text/html", "Missing code or bits!"); } } void handleRc(){ String groupstring=server.arg("group"); String switchstring=server.arg("switch"); String actionstring=server.arg("action"); String webOutput = "Group: "+groupstring+"; Switch: "+switchstring+"; Action: "+actionstring; char groupchar[groupstring.length()+1]; groupstring.toCharArray(groupchar, groupstring.length()+1); char switchchar[switchstring.length()+1]; switchstring.toCharArray(switchchar, switchstring.length()+1); if(actionstring=="1"){ mySwitch.switchOn(groupchar, switchchar); server.send(200, "text/html", webOutput); } else if(actionstring=="0"){ mySwitch.switchOff(groupchar, switchchar); server.send(200, "text/html", webOutput); } else{ server.send(200, "text/html", "Wrong action code!"); } } void handleDHT(){ getDHT(); String typestring=server.arg("type"); String temp_str = String((int)temperature); String hum_str = String((int)humidity); if(typestring=="temp"){ server.send(200, "text/html", temp_str); } else if(typestring=="hum"){ server.send(200, "text/html", hum_str); } else{ String webOutput = temp_str+";"+hum_str; server.send(200, "text/html", webOutput); } } void handleNotFound(){ server.send(404, "text/plain", "404"); } void getDHT(){ humidity = dht.readHumidity(); temperature = dht.readTemperature(false); if (isnan(humidity) || isnan(temperature)) { Serial.println("Failed to read from DHT sensor!"); return; } } void setup(void){ mySwitch.enableTransmit(12); irsend.begin(); dht.begin(); Serial.begin(9600); WiFi.begin(ssid, password); WiFi.config(ip, gateway, subnet); Serial.println(""); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); if (mdns.begin("esp8266", WiFi.localIP())) { Serial.println("MDNS responder started"); } server.on("/", handleRoot); server.on("/ir", handleIr); server.on("/rc", handleRc); server.on("/dht", handleDHT); server.onNotFound(handleNotFound); server.begin(); Serial.println("HTTP server started"); } void loop(void){ server.handleClient(); } |
Alles wird also über einfache HTTP-Requests angesteuert. Zwar wäre auch eine Umsetzung z.B. über MQTT denkbar, allerdings braucht man dann noch einen Broker (bzw. nutzt einen im Internet) und die App-Auswahl zur Steuerung ist stark eingeschränkt (ich nutze hier NetIO für die Steuerung über eine GUI auf Android/iOS sowie AIVC zur Sprachsteuerung).
Die verwendeten Bibliotheken sind konkret:
- rc-switch für die Funksteckdosen (siehe dazu ausführlichen Artikel hier)
- IRremote für die IR-Diode (mehr dazu siehe hier)
- DHT-sensor-library zum Auslesen des DHT11 in einer älteren Version (mit der neueren hatte ich massive Verbindungsprobleme zum Sensor)
Das HTTP-Interface habe ich dabei wie folgt gestaltet:
- Für die Funksteckdosen: [IP]/rc?group=xxxx&switch=xxxx&action=x (wobei „group“ und „switch“ den DIP-Einstellungen der Steckdosen entsprechen und bei „action“ eine „1“ an entspricht und eine „0“ aus)
- Für IR-Geräte: [IP]/ir?code=xxx&bits=xx&protocol=x („code“ entspricht hier der mit der Bibliothek ausgelesenem Code in Dezimal, „bits“ der ausgelesenen Länge und „protocol“ dem Protokoll [z.B. NEC oder Sony])
- Für DHT-Sensor: [IP]/dht?type=x (dieser Befehl kann auch ohne „type“ aufgerufen werden, dann erhält man „[Temperatur];[Luftfeuchtigkeit]“, ansonsten lassen sich Temperatur und Luftfeuchtigkeit auch einzeln über „temp“ bzw. „hum“ auslesen/anzeigen)
3. Nutzung und Erweiterung
Wie bereits erwähnt nutze ich NetIO bzw. AIVC zur Steuerung. Das klappt mit beiden Apps vollkommen problemlos. Hier noch 2 Screenshots von meinen Ansichten in der NetIO-App (lassen sich bequem über einen Editor am PC anlegen):
Der Code lässt sich im Übrigen beliebig erweitern, sodass auch andere Sensoren oder Aktoren eingebunden werden können. Eventuell ergänze ich mein Setup demnächst noch um ein Barometer oder ähnliche Spielereien.
Momentan ist das Projekt ausgelegt auf eine permanente Stromversorgung über den Micro-USB-Anschluss, solltet ihr das Projekt (oder Teile davon) batteriebetrieben verwenden wollen, solltet ihr euch noch Gedanken um die Schlafzustände es ESP8266 machen.
Wenn ihr euer Setup in unterschiedlichen Umgebungen einsetzen möchtet, ist ein Blick auf das Projekt „WiFiManager“ für den ESP8266 sinnvoll, der es auch erlaubt, die WLAN-Daten schnell über ein Webinterface zu konfigurieren.
Bei Fragen zu dem Projekt oder Anregungen könnt ihr wie immer gerne das Kommentarfeld unten verwenden.
Hallo,
dein Projekt und der Ansatz mit dem ESP8266 gefällt mir sehr gut! Gegenüber dem Raspberry Pi ist der ESP8266 hier eine sinnvolle Alternative. Denkbar wäre noch – gerade beim Ausbau des Projekts – auf dem PiZero umzusteigen um softwareseitig ein paar mehr Möglichkieten zu haben.
Ich habe auch gerade eine kleine Platine mit einem ähnlichen Projekt in der Fertigung. Gibt es schon pläne was bei deinem Projekt noch hinzu kommt?
Gruß
Hi Tony,
ja – der Zero ist ein sehr interessantes Gerät. Sobald es diesen mal günstig in D gibt, werde ich zuschlagen. Damit könnte man das vorhandene Setup auch sehr günstig HomeKit-fähig machen.
Das mit der Platine klingt interessant! Nutzt du auch den ESP oder ein anderes Bauteil? Es soll ja auch bald der ESP32 rauskommen, der kann auch Bluetooth und SSL. Das wäre auch ein spannender Baustein für Projekte, die direkt im Internet erreichbar sind.
Momentan habe ich keine großartigen weitere Ideen, evtl noch ein Barometer und den DHT11 mit dem DHT22 ersetzen – das sind aber eher Kleinigkeiten. Softwaretechnisch bin ich noch am Überlegen, wie man eine Statusspeicherung für die Funksteckdosen implementieren kann.
Leider weiß ich nicht, wie es die nächsten Monate zeittechnisch bei mir aussieht, daher habe ich keine größeren Projekte geplant.
Werde aber auf jeden Fall deinen Blog (weiter) im Auge behalten bzgl. deiner Projekte – gerade wenn du auch mit dem ESP basteln anfängst ;)
Hallo Alex,
nein für mein Projekt nutze ich kein ESP. Das ist mit einem WLAN-Adapter am Pi gedacht. Insgesamt ist die Zugriff auf den Pi dem Nutzer überlassen. Die Platine soll wirklich nur dazu da sein um Sensoren auf einfache Weise zu installieren und das 433 Mhz FUnkmodul zu nutzen.
Gruß,
Tony
Hey Tony,
ah – verstehe. Klingt nach einer guten Alternative für GrovePi ?
Danke mal für deine Mühe. Ich nutze für die Steckdosen die App homeremote und bin vollauf zufrieden. Deinen Tipp mit netio werde ich demnächst mal umsetzen,
Hi Alex! Do you plan to write your articles in English too? I don`t speak German but like your projects a lot ?
This would for sure help you getting a much larger audience. Would be really great! Google translator is quite bad.
Thanks a lot!
Hello Aurélien,
thinking about it – at the moment I don´t spare time for (re)writing articles in English but perhaps I´ll manage to do so in future.
> Momentan habe ich keine großartigen weitere Ideen
Eine wäre ein per Port 8765 mit dem WLAN sprechender LIRC für 38kHz & 433 MHz & 868 MHz & 2,4 GHz (alles empfangend, so daß PCs/VDRs per -c andocken können; Sender schaltbar à la http://aron.ws/projects/lirc_rpi/ ).
Hi TEN,
danke für die Anregung!
Ich werde mir die Sache mal genauer anschauen.
Die Sache mit 868MHz würde mich auch interessieren!
Klasse Projekt! Jetzt bräuchte ich daran nur noch Bluetooth LE und ich könnte damit so gut wie alles steuern. Weißt du zufällig ob man ein Bluetooth 4 Modul daran betreiben kann?
Hallo Timo,
für BT 4 würde ich auf den ESP32 warten. Dieser ist ähnlich dem ESP8266, nur hat der gleich BT 4 an Board und kann auch SSL. Dürfte in den nächsten Monaten erscheinen.
Vielen Dank für den Tipp mit NetIO! Das scheint wirklich eine brauchbare App zu sein ☺
Hallo Alex,
wäre es möglich, dass Du auch Deine NetIO-Config zur Verfügung stellst? Mich interessiert vor allem der Teil mit der Temperatur und der Luftfeuchtigkeit: Welche Parameter hast Du bei parseRespone und formatResponse eingetragen?
Danke
Hallo Thomas,
parseResponse: \d+
formatResponse: Temperatur: {0}°C Luftfeuchtigkeit: {1}%
Hallo Alex,
vielen Dank!
Manches kann so einfach sein… :-)
Ich arbeite mich gerade in diese „regular expressions“ ein.
Hallo Alex,
hast du schon mal überlegt das Ganze als fertige Platine erstellen zu lassen? Also mit ESP8266 und Peripherie bzw. Schnittstellen dafür?
Nur so eine Idee ?
Hi Mark,
von der Idee her sicher interessant, für mich allerdings weniger was, da ich bewusst Breadboards einsetze für meine Bastellösungen. Auch fehlen mir die Kenntnisse für sauberes Platinendesign.
Hallo Alex,
ich hätte noch eine bitte. Besteht die Möglichkeit dass du in das Script die Möglichkeit vom senden des TriState mit einbaust?
Serial.print(„Send ON“);
mySwitch.sendTriState(„00FFFFFF0101“);
delay(20000);
Serial.print(„Send OFF“);
mySwitch.sendTriState(„00FFFFFF0110“);
delay(20000);
Funktioniert bei meinen Schaltern wunderbar, ich hab aber keinen Weg gefunden diese mit deinem Script zu schalten.
Vielen Dank
Hallo Marcel,
woran scheitert´s denn?
Hi. Kannst du bitte noch die .json Datei hochladen, ich bin hier am verzweifeln, nichts klappt!
Hallo Alex,
was wäre denn zu beachten, wenn ich hiermit auch meine IR-Sender auslesen möchte?
Beste Grüße und ein schönes Wochenende.
Hallo Alex, super Anleitung. Danke schon mal dafür.
Kannst du für Anfänger (wie ich einer bin) nochmal erläutern welchen Transistor (es gibt unterschiedliche BC547) ich genau brauche und wie du auf den Vorwiderstand von 600Ohm kommst? Würde mich interessieren, da ich an den IR Emitter noch ein ca. 1 Meter langes Kabel anbringen möchte mit entsprechendem Leitungswiderstand.
Hallo,
super Projekt, bin auch gerade dabei sowas zu bauen, aber ich würde es gerne über FHEM ansteuern und auslesen.
Weiß jemand wie man das in Alex´s implementiert und auf der FHEM Seite einrichtet ?
VG Stefan
Hallo,
tolles Projekt! Im Steckplatinenbild ist ein Fehler: die Masse (GND) vom 433-Funkchip ist mit Plus verbunden. – Im Foto ist es richtig gesteckt.
salü
Hallo Andreas,
danke für deinen Kommentar! Du hast völlig recht – da hat sich ein dummer Fehler eingschlichen. Habe das Bild ersetzt :)
Wirklich ein gelungenes Projekt. Ich schau mich gerade um für neue Projekte und da hol ich mir doch gerne einige Ideen bei Dir!
Ich bin der Meinung, dass du die IR Diode nicht ohne Vorwiderstand ansteuern solltest.
Können sie mir sagen welche version sie Arduino und esp8266 verwenden
Ich habe das Modull Lolino v3 und nodemcu v0.9
Kriege es beim beiden nicht zum laufen .
Danke.
Hi aki,
was genau funktioniert denn bei dir nicht?
schon beim Überprüfen/Kompilieren
kommen diese probleme auf. Sorry
Arduino: 1.8.5 (Windows 10), Board: „NodeMCU 1.0 (ESP-12E Module), 80 MHz, 115200, 4M (3M SPIFFS)“
alex_gat:18: error: ‚IRsend‘ does not name a type
IRsend irsend(14);
^
C:\Users\Documents\Arduino\alex_gat\alex_gat.ino: In function ‚void handleIr()‘:
alex_gat:36: error: ‚irsend‘ was not declared in this scope
irsend.sendNEC(code, bits);
^
alex_gat:40: error: ‚irsend‘ was not declared in this scope
irsend.sendSony(code, bits);
^
alex_gat:44: error: ‚irsend‘ was not declared in this scope
irsend.sendWhynter(code, bits);
^
alex_gat:48: error: ‚irsend‘ was not declared in this scope
irsend.sendLG(code, bits);
^
alex_gat:52: error: ‚irsend‘ was not declared in this scope
irsend.sendRC5(code, bits);
^
alex_gat:56: error: ‚irsend‘ was not declared in this scope
irsend.sendRC6(code, bits);
^
alex_gat:60: error: ‚irsend‘ was not declared in this scope
irsend.sendDISH(code, bits);
^
alex_gat:64: error: ‚irsend‘ was not declared in this scope
irsend.sendSharpRaw(code, bits);
^
alex_gat:68: error: ‚irsend‘ was not declared in this scope
irsend.sendSAMSUNG(code, bits);
^
C:\Users\Documents\Arduino\alex_gat\alex_gat.ino: In function ‚void setup()‘:
alex_gat:129: error: ‚irsend‘ was not declared in this scope
irsend.begin();
^
exit status 1
‚IRsend‘ does not name a type
Danke Alexander
Hey,
scheint, als ob sich an der Bibliothek was geändert hat. Die einfachste Lösung ist wohl, eine ältere Version von irsend einzusetzen :)
Bei mir hat es ein einfaches:
#include
ganz oben getan.
Oh.. hier wurde alles hinter dem #include abgeschnitten.
Dahinter gehört noch: (kleiner)IRsend.h(größer)
Hmm … Jetzt habe ich auch eine Frage:
Egal wie und was ich eingebe ich bekomme immer:
Protocol not implemented!
Meine URL wäre z.B.: http://192.118.11.11/ir?code=0012&bits=120&protokol=RC5
Das sollte den Fernseher ausschalten.
Könntest du mir ein funktionierendes Beispiel geben?
bits auf 12 umschreiben….jetzt hast du 120 stehen. Den Fehler habe ich auch gemacht.
dann noch „protokol“ auf „protocol“ umschreiben und die Dezimalzahl ohne Nullen vor der 12, dann sollte es passen.
Habe eine farbige LED mit entsprechendem Widerstand eingesetzt um eine visuelle Bestätigung zu haben. Im Browser solltest du die Bestätigung bekommen:
Protocol: RC5; Code: 12; Bits: 12
Alexander, tolles Projekt. Besonders weil es nicht abhängig von der Aussenwelt ist und wegen Updates auf der Seit von Brokern wohl möglich nicht mehr funktioniert…
Ich konnte den Code auch ohne Kompilierfehler hochladen nachdem ich die IRsend.h eingebunden habe.
http://192.168.178.48/ir?code=2704&bits=120&protocol=Sony
Ich bekomme aber auch nur „Protocol not implemented!“
Vielleicht ist die Einbindung von IRsend.h doch nicht die Lösung zu dem Library IRsend Problem?
Hoffentlich finden wir die Lösung :)
LG Stahlhelm
also, ich habe meine NetIO App in Kombination mit dem NodeMCU 8266 ESP 12E am laufen. Hatte die Formatierung von der Nachricht nicht 100%…
Ich würde gern was ähnliches bauen. Hättest du ein einfaches Beispiel für 2 Buttons in Netio welche per http request einen Ausgang am Arduino mit esp8266 oder einem Wemos schalten?
Ich blicke einfach nicht durch.
Hi Alex,
Could you tell me what brand and type of RC switches you used for this project..
Because i’m trying to find out what kind of data is placed in ‚ groupstring ‚