Ich habe lange Zeit Artikel über Hausautomationssysteme auf Habré gelesen und wollte beschreiben, woran ich seit mehr als zwei Jahren arbeite. Zum besseren Verständnis meiner Situation müssen Sie eine kleine Einführung machen.Vor drei Jahren zogen meine Familie und ich in eine neue Dreizimmerwohnung (67,5 m²), obwohl die Wohnung technisch gesehen natürlich alt ist - Stalin, ein Haus aus dem Jahr 1946. Aluminium-Zweidrahtverdrahtung mit Kupferlitzen an einigen Stellen 1 m². Die Überholung stand vor der Tür, ich beschloss, alles selbst zu tun, und begann mit einem vollständigen Austausch der Verkabelung. 700 m Netzkabel für Beleuchtung und Steckdosen 1,5 und 2,5 m², ein Twisted-Pair-Schacht, ein kleines Koaxialkabel für Fernsehantennen wurden gekauft (nur für den Fall). Warum so viel und was daraus wurde - ich bitte um eine Katze.Ich habe mich entschlossen, die Verkabelung sofort vorzunehmen, nämlich: Ohne Verteilerkästen führt das Kabel von jedem Punkt zur Abschirmung (mit Ausnahme der Steckdosen, die in einer Gruppe von 2-3 Punkten liegen können, geht das Kabel von der Spitze zur Abschirmung, der Rest ist durch eine Schleife verbunden) - t. e. Von jedem Schalter sein eigenes Kabel zur Abschirmung, von jedem Beleuchtungspunkt sein eigenes Kabel zur Abschirmung, in der Nähe von Buchsen entlang eines Paares von rj-45-Punkten, nur für den Fall. Natürlich gibt es viele Kabel. Irgendwo wird es nach allen Regeln des PUE auf den Boden gelegt, wie zum Beispiel im Kinderzimmer:
Irgendwo - an der Decke zum Beispiel Blick auf die Schlafzimmertür:
Infolgedessen erhalten wir alle Kabel im Korridor an einem Ort, an dem sich die Abschirmung befindet, und sie können nach Belieben zwischen ihnen ausgetauscht werden. Selbst wenn Sie das Verbindungsschema in Zukunft ändern müssen, wird es nicht viel Zeit in Anspruch nehmen und Sie müssen die Reparatur nicht verderben. Und natürlich wurden viele Steckdosen für alle Gelegenheiten hergestellt - insgesamt etwa 90 Punkte für die gesamte Wohnung.So sah der temporäre „Schild“ während der Experimente aus: Ein
schrecklicher Anblick, aber alles funktionierte und in dieser Form lebte dieses Monster mehrere Monate. Eines schönen Tages wurden die Sterne erfolgreich geformt und der Schild durch vorsätzliche Entscheidung erneuert. Es dauerte 3 Tage auf einer klapprigen Treppe unter der Decke (und die Decken im Stalin 3m), aber es hat sich gelohnt. So sah das Dashboard danach aus:
Und die allgemeine Ansicht:
Dies ist weit entfernt von der endgültigen Form der Abschirmung, es gibt immer noch nicht genügend FI-Schutzschalter, es gibt dreimal weniger Leistungsschalter als erforderlich, es gibt keine Impulsrelais - aber es gibt keine Trennleitungen, alle Kabel sind an die Klemmen angeschlossen, es gibt zumindest eine Art Leistungsschalter-Selektivität.Nachdem Sie eine ungefähre Vorstellung davon haben, womit ich genau arbeiten musste, können Sie beginnen, die „Gehirne“ des Systems zu beschreiben. Ohne weiteres nahm ich Arduino als Basis, zumal ich bereits 2 Freeduino-Boards, 2 Ethernet-Shields und einen Motor Shield hatte, die ich lange zuvor gekauft hatte. Ebenfalls bei den Chinesen bestellt mehrere Relaismodule zu je 4 Stück. Auf Anraten eines Artikels über Habré in Ob fand ich auch Schalter, in die spezielle Federn eingesetzt werden konnten, und die sich ohne Befestigung in Schalter verwandelten. Es ist Zeit, Code zu schreiben.Im Allgemeinen bin ich eng mit Computern im Leben verbunden. Er hat die Pelzmatte fertiggestellt, auf die er gerade nicht geschrieben hat - Pascal, C #, C ++, 1c, PHP, Javascript - Sie können immer noch viel auflisten. Das letzte Mal, wenn ich im Bereich Webentwicklung arbeite, beschäftige ich mich auch mit IP-Telefonie. Daher ist es einfach, einen Algorithmus zu entwickeln, aber mit Elektronik „für Sie“ kenne und kenne ich einfache Dinge, und wenn es um etwas Komplizierteres geht - Mikrocontroller, Sicherungen, Kontaktsprung - ist es schwieriger. Aber es sind nicht die Götter, die die Töpfe verbrennen, die Augen haben Angst, sondern die Hände. Ich beschloss, alles einfach zu machen. Ich speise die Erde vom Arduino zum Eingang des Schalters, ich verbinde die Ausgänge des Schalters mit den analogen Pins des Arduino (obwohl es möglich ist, digital zu sein, ist es nicht wichtig). Ich verbinde die Pins des Arduino mit den Pins des Relaismoduls. Technisch ist alles bereit. Wenn Sie den Schalter drücken, sieht das Arduino den LOW-Wert am gewünschten Pin und setzt den LOW-Wert an dem mit dem Relaismodul verbundenen Pin.Da alle Kabel von den Punkten in der Wohnung zu den Terminals kommen, dauerte die Verbindung nicht lange.Um das Abprallen von Kontakten zu bekämpfen, wurde nach dem Studium des Themas im Internet die Bounce2-Bibliothek ausgewählt. Im Allgemeinen wollte ich zunächst einen universellen Code schreiben, damit er mit mindestens 2 Schaltern verwendet werden kann, mindestens 22. Diese Aufgabe bildete die Grundlage des gesamten Algorithmus. Nun, von den Wörtern zum Code. Ich werde nicht den gesamten Code hochladen, Links zum Github befinden sich am Ende des Artikels. Ich werde aus meiner Sicht nur wichtige Momente zeigen.Deklarieren von Bibliotheken und Variablen:
const byte cnt = 8;
const byte pin_cnt = 19;
int pins[] = {11,12,13,13,14,15,16,17};
int leds[] = {6, 3, 4, 5, 3, 4, 5, 3};
byte init_leds[cnt] ;
byte init_buttons[cnt];
int button_states[cnt];
Bounce debouncers[cnt];
unsigned long buttonPressTimeStamps[cnt];
boolean changed[cnt];
Der Punkt ist: Es reicht aus, die Konstante mit der Anzahl der Lampen / Schalter zu erhöhen und neue Assoziationen in den Arrays zu registrieren - und das ist alles, eine neue Lampe oder ein neuer Schalter wird hinzugefügt. Gleichzeitig ermöglicht die Codestruktur, dass ein Switch mehrere Geräte gleichzeitig steuert. Oder mehrere Schalter, um sofort eine Lampe zu steuern. Außerdem wird für jeden Switch eine eigene Instanz des Bounce-Objekts für Anti-Bounce erstellt.In der Setup-Funktion werden alle Arrays initialisiert, während der Status der Leuchten im nichtflüchtigen Speicher gespeichert wird, sodass bei einem Stromausfall oder Neustart alles auf die gleiche Weise wie vor dem Ausfall eingeschaltet wird. for(byte i=0; i<cnt; i=i+1) {
EEPROM.write(pins[i], 10);
}
for(byte i=0; i<cnt; i=i+1) {
button_states[i] = 0;
byte value = EEPROM.read(leds[i]);
if(value==11) {
init_leds[i] = LOW ;
}else{
init_leds[i] = HIGH ;
}
init_buttons[i] = HIGH;
buttonPressTimeStamps[i] = 0;
changed[i] = false;
debouncers[i] = Bounce();
pinMode(pins[i], INPUT);
pinMode(leds[i], OUTPUT);
digitalWrite(pins[i], init_buttons[i]);
digitalWrite(leds[i], init_leds[i]);
debouncers[i].attach( pins[i] );
debouncers[i].interval(5);
}
Ich werde nichts über den ersten Zyklus sagen, wir werden etwas später darauf zurückkommen. Und das Interessanteste beginnt im Hauptzyklus.void loop(){
for(byte i=0; i<cnt; i=i+1){
byte dvalue = EEPROM.read(pins[i]);
if(dvalue!=11) {
changed[i] = debouncers[i].update();
if ( changed[i] ) {
int value = debouncers[i].read();
if ( value == HIGH) {
button_states[i] = 0;
} else {
if (i > 0 and pins[i] == pins[i-1]) {
byte prev_value = EEPROM.read(leds[i-1]);
if(prev_value == 11) {
digitalWrite(leds[i], LOW );
EEPROM.write(leds[i], 11);
}else{
digitalWrite(leds[i], HIGH);
EEPROM.write(leds[i], 10);
}
} else {
byte value = EEPROM.read(leds[i]);
if(value==11) {
digitalWrite(leds[i], HIGH );
EEPROM.write(leds[i], 10);
}else{
digitalWrite(leds[i], LOW);
EEPROM.write(leds[i], 11);
}
}
button_states[i] = 1;
buttonPressTimeStamps[i] = millis();
}
}
if ( button_states[i] == 1 ) {
if ( millis() - buttonPressTimeStamps[i] >= 200 ) {
button_states[i] = 2;
}
}
}
}
delay( 10 );
}
Bei Tests der ersten Versionen des Algorithmus wurde festgestellt, dass die Kinder (und ich habe drei von ihnen, Jungen) sehr gerne auf die Schalter klickten. Daher war es notwendig, einige Schalter ausschalten zu können, damit der Controller nicht darauf reagierte. Die naheliegendste Möglichkeit besteht darin, einfach die erforderlichen Stifte von der Platine zu entfernen. Dies ist jedoch falsch und uninteressant. Daher werden Flags auch in den nichtflüchtigen Speicher geschrieben, um anzuzeigen, ob der Schalter geöffnet ist oder nicht. Dies wird mit dieser Schleife initialisiert: for(byte i=0; i<cnt; i=i+1) {
EEPROM.write(pins[i], 10);
}
...
Und hier überprüft: for(byte i=0
byte dvalue = EEPROM.read(pins[i])
if(dvalue!=11) {
...
Bereits zu diesem Zeitpunkt begannen lokale Schalter an den Wänden zu funktionieren. Aber ein Smart Home wäre ohne eine Schnittstelle nicht intelligent. Da ich mich mit Webentwicklung beschäftige, wurde beschlossen, ein Webinterface zu erstellen. Hier haben sich Ethernet-Schilde als nützlich erwiesen. Leider konnte ich die Quellen der ersten Versionen von Programmen nicht finden, die Ethernet-Schutzschilde für die Fernsteuerung verwenden. Ich werde versuchen, in Backups zu suchen, vielleicht sind sie da. Aber die Bedeutung war primitiv für die Schande. Jeder Controller hat seine eigene IP-Adresse. Auf dem Arduino stieg ein Webserver an, der GET-Anforderungen analysierte und die entsprechende Lampe je nach Portnummer ein- oder ausschaltete. Es gibt viele Beispiele dieser Art im Internet. Für die Weboberfläche wurde auf dem Motherboard ein Server mit integriertem Intel Atom erstellt, Ubuntu Server 14.02 wurde installiert, das Standard-LAMP-Set wurde installiert,Dort ist eine einfache Schnittstelle geschrieben. Alle Quellen finden Sie auch am Ende des Artikels. Im Moment sieht es so aus:
Wie Sie sehen, ist eine Lampe in der Küche eingeschaltet und der dafür verantwortliche Schalter verriegelt. Die Verwaltung ist mega einfach - klicken Sie einfach auf das gewünschte Element und dessen Status ändert sich.Und alles wäre großartig, wenn nicht ein "aber". Ethernet-Abschirmungen hingen ständig. Nein, die lokale Steuerung über die Schalter funktionierte immer wie eine Uhr. Die Fernbedienung über das Webinterface fiel jedoch ständig aus. Wenn das Management einen Tag lang arbeitete, war es ausgezeichnet. Aber öfter hing der Schild nur wenige Stunden nach dem Neustart. Was ich einfach nicht getan habe, war zu versuchen, mit Wachhunden umzugehen, aber meine Boards haben es nicht unterstützt. Ich bestellte in China und ersetzte die Schilde durch andere - auf en28j60 - es wurde besser, aber sie legten immer noch regelmäßig auf. Ich fügte dem Controller ein Relaismodul hinzu, versorgte die Arduino-Karten über normalerweise geschlossene Kontakte mit Strom, und eine der Arduino-Karten zog das Relais mit einer bestimmten Frequenz und die Stromversorgung wurde abgeschaltet, und dann wurde es wiederhergestellt - dies funktionierte jedoch auch nicht immer und blinkte zum Zeitpunkt des Neustarts Licht an,sogar für ein paar Sekunden, aber trotzdem. So sah der Controller zu diesem Zeitpunkt aus:
Und dann wurde beschlossen, die Ethernet-Schilde vollständig aufzugeben. Ich suchte nach anderen Remoteverwaltungsfunktionen. Ich habe versucht, Arduins direkt mit dem Server zu verbinden und Befehle über Serial.read () / Serial.print () zu senden - es funktionierte jedes Mal, Stabilität wurde nicht erreicht, da die Karte bei jedem Zugriff über ein Skript neu gestartet wurde auf dem Server. Ich habe viel über solche Fehler gelesen, ich habe nur festgestellt, dass es mit dem DTR verbunden ist, irgendwo haben sie geschrieben, dass man den Port mit anderen Flags initialisieren kann, und Beispiele gegeben, die für mich nicht funktionierten. Nach einer Weile stieß ich auf einen Artikel über die Herstellung eines USB-I2C-Adapters aus einem USBAsp-Programmierer. Ich entschied - warum nicht? Ich bestellte ein paar solcher Programmierer bei den Chinesen - und wartete.Und vor einer Woche ist mein Paket angekommen. Ein Programmierer wurde mit der winzigen USB-Firmware von i2c geflasht, und ich setzte mich erneut hin, um den Code neu zu schreiben. Hier begannen die Protokollmerkmale zu erscheinen. Natürlich war der Server der Master und alle Arduino-Boards waren Slaves.Der Code sollte die folgenden Aufgaben lösen:- den Status des angeforderten Ports melden;- den Status des angeforderten Ports ändern;- Alle Lichter aus- oder einschalten.Und ich bin auf ein Problem gestoßen. Ich kann die Standardbefehle aus der i2c-tools-Suite verwenden, um mit Arduino-Boards zu kommunizieren. Das ist ein Teami2cget -y < > <>
undi2cset -y < > <> 0x00 <byte >
Nach dem Mann zu urteilen, könnte man den Wortwert übergeben, aber es hat bei mir nicht funktioniert, oder ich habe mich irgendwo geirrt.Das Problem ist, dass ich, wenn ich den Status eines bestimmten Ports ändern muss, zuerst die Nummer des für diesen Vorgang verantwortlichen Befehls und dann die Portnummer übergeben muss. Ich habe sogar versucht, dies zu tun, 2 Befehle zu senden und sie im Code zu sammeln - aber es war hässlich und irrational.Problem Nummer zwei - Arduino kann im Moment, in dem sie die Daten empfängt, nichts beantworten. Es gibt zwei Methoden der Wire-Bibliothek: onReceive (), wenn Daten vom Master empfangen werden, und onRequest (), wenn Daten vom Master angefordert werden.Also habe ich folgendes gemacht: Der Webserver hat 6 Befehle:- Befehl "1" - Ermittelt den Status aller Lichter
- Befehl "2" - Ermittelt den Sperrstatus aller Schalter
- Befehl "5" - Schalte die ganze Welt ein
- Befehl "6" - Schalte die ganze Welt aus
ein Befehl, der wie folgt gebildet wird: eine Dezimalzahl der folgenden Form <Hunderte (1 oder 2) - Lampe oder Schaltersperre schalten> <Portnummer (von 0 auf 99)>; Zum Beispiel 105 - Switch 5 Port, 213 - Switch 13 Port Lock. Dieser Befehl wird in hex übersetzt und an das Arduino übergeben, das die inversen Transformationen ausführt und versteht, was zu tun ist.So sieht es auf der Serverseite aus: ...
if ($action == 3)
$val_hex = dechex(intval($port) + 100);
else
$val_hex = dechex(intval($port) + 200);
exec("sudo i2cset -y 7 $addr 0x00 0x$val_hex", $output);
...
Und von der Seite des Arduino:void receiveEvent(int howMany) {
byte bytes = Wire.available();
int x = 0;
for (byte i=1; i <= bytes; i=i+1) {
x = Wire.read();
}
if (x == 1 or x == 2 or x == 5 or x == 6) {
do_action(x, 0);
} else {
if ( x > 200) {
do_action (4, x - 200);
} else {
do_action (3, x - 100);
}
}
}
Es sieht ziemlich primitiv aus, aber es funktioniert. Das zweite Problem wird wie folgt gelöst. Hier ist die Funktion do_action:void do_action(byte command, byte port) {
byte value = 0;
byte dvalue = 0;
switch (command) {
case 1:
start_request = true;
request_type = 1;
current_port = 0;
break;
case 2:
start_request = true;
request_type = 2;
current_port = 0;
break;
case 3:
value = EEPROM.read(port);
if(value==11) {
digitalWrite(port, HIGH);
EEPROM.write(port, 10);
} else {
digitalWrite(port, LOW);
EEPROM.write(port, 11);
}
break;
case 4:
dvalue = EEPROM.read(port);
if(dvalue==11) {
EEPROM.write(port, 10);
} else {
EEPROM.write(port, 11);
}
break;
case 5:
for (byte i=0; i<cnt; i = i + 1) {
digitalWrite(leds[i], LOW);
EEPROM.write(leds[i], 11);
}
break;
case 6:
for (byte i=0; i<cnt; i = i + 1) {
digitalWrite(leds[i], HIGH);
EEPROM.write(leds[i], 10);
}
break;
default:
break;
}
}
Bei den Teams 3-6 ist alles klar, aber die Teams 1 oder 2 können detaillierter beschrieben werden. Der Server sendet zuerst den gewünschten Befehl, und wenn der Arduino den Befehl 1 oder 2 empfängt, werden die Flags initialisiert: start_request = true;
request_type = 1;
current_port = 0;
Und dann beginnt der Server, Anfragen so oft an das Arduino zu senden, wie die Ports, die er abfragen möchte. Auf der Serverseite:function get_data($address, $action, $cnt) {
exec("sudo i2cset -y 7 $address 0x00 0x0$action", $output);
$tmp = @$output[0];
while (strpos($tmp,"rror")!==false) {
exec("sudo i2cset -y 7 $address 0x00 0x0$action", $output);
$tmp = @$output[0];
}
$str = "";
for ($i = 1; $i <= $cnt; $i++) {
exec("sudo i2cget -y 7 $address", $output);
$tmp = @$output[0];
while (strpos($tmp,"rror")!==false) {
exec("sudo i2cget -y 7 $address", $output);
$tmp = @$output[0];
}
if ($tmp) {
if (strpos($tmp,"1")!==false)
$str .= "1";
else
$str .= "0";
}
unset($output);
unset($tmp);
}
return $str;
}
$str = array();
$c = 1;
while ($c <= $tryes) {
$tmp = get_data($addr, $action, $cnt);
if (strlen($tmp) == $cnt)
$str[] = $tmp;
$c++;
}
$new_array = array_count_values($str);
asort($new_array);
$res = "";
$max = 0;
foreach ($new_array AS $key=>$val) {
if ($val >= $max) {
$res = $key;
$max = $val;
}
}
return preg_split('//', $res, -1, PREG_SPLIT_NO_EMPTY);
Kurz gesagt - wir machen mehrere ($ tryes> 3) Versuche, das Arduino abzufragen. Wir erhalten eine Zeile bestehend aus 0 oder 1. Überall, wo wir mit einem Befehl die Antwort sehen, wenn das Wort Fehler vorhanden ist, bedeutet dies, dass während der Übertragung Fehler aufgetreten sind und Sie die Übertragung wiederholen müssen . Es wurden mehrere Versuche unternommen, um die Richtigkeit der übertragenen Zeichenfolge sicherzustellen. Das Array wird mithilfe der Methode array_count_values ($ str) durch eine Zeichenfolge reduziert. und am Ende erhalten wir ein Array mit der Anzahl der Vorkommen derselben Zeilen. Wir geben die Zeile aus, die wir am meisten von Arduino erhalten haben.Von der Seite des Arduino ist alles einfacher:void requestEvent() {
if (request_type == 1) {
byte value = EEPROM.read(leds[current_port]);
if(value==11) {
Wire.write(1);
} else {
Wire.write(0);
}
current_port = current_port + 1;
} else if (request_type == 2) {
byte dvalue = EEPROM.read(pins[current_port]);
if(dvalue==11) {
Wire.write(1);
} else {
Wire.write(0);
}
current_port = current_port + 1;
}
}
Der Code der Webseite enthält die Steuerelemente:<a class="lamp living_room" id="lamp0x4d3" rel='0x4d' onclick="lamp_click('0x4d',this.id, 3);" ></a>
<a class="lamp kitchen" id="lamp0x4d4" rel='0x4d' onclick="lamp_click('0x4d',this.id, 4);" ></a>
<a class="lamp children_main" id="lamp0x4d5" rel='0x4d' onclick="lamp_click('0x4d',this.id, 5);" ></a>
<a class="lamp children_second" id="lamp0x4d6" rel='0x4d' onclick="lamp_click('0x4d',this.id, 6);" ></a>
<a class="lamp sleeproom_main" id="lamp0x423" rel='0x42' onclick="lamp_click('0x42',this.id, 3);" ></a>
<a class="lamp sleeproom_lyuda" id="lamp0x424" rel='0x42' onclick="lamp_click('0x42',this.id, 4);" ></a>
<a class="lamp sleeproom_anton" id="lamp0x425" rel='0x42' onclick="lamp_click('0x42',this.id, 5);" ></a>
<a class="button button_living_room" id="button0x4d15" onclick="button_click('0x4d',this.id, 15);" ></a>
<a class="button button_kitchen" id="button0x4d14" onclick="button_click('0x4d',this.id, 14);" ></a>
<a class="button button_children_main" id="button0x4d16" onclick="button_click('0x4d',this.id, 16);" ></a>
<a class="button button_children_second" id="button0x4d17" onclick="button_click('0x4d',this.id, 17);" ></a>
<a class="button button_sleeproom_door1" id="button0x4212" onclick="button_click('0x42',this.id, 12);" ></a>
<a class="button button_sleeproom_door2" id="button0x4213" onclick="button_click('0x42',this.id, 13);" ></a>
<a class="button button_sleeproom_lyuda1" id="button0x4214" onclick="button_click('0x42',this.id, 14);" ></a>
<a class="button button_sleeproom_lyuda2" id="button0x4215" onclick="button_click('0x42',this.id, 15);" ></a>
<a class="button button_sleeproom_anton1" id="button0x4216" onclick="button_click('0x42',this.id, 16);" ></a>
<a class="button button_sleeproom_anton2" id="button0x4217" onclick="button_click('0x42',this.id, 17);" ></a>
Eigentlich gebe ich explizit die Adresse der Karte an, auf die ich zugreifen muss, und die Portnummer.Oh ja, der Controller sieht jetzt so aus:
Nachdem alles installiert war, wurde alles beim ersten Mal gestartet. Und am nächsten Tag trat ein unverständlicher Effekt auf - wenn Sie alle Lichter im Schlafzimmer einschalten, beginnt das gesamte Licht im Schlafzimmer alle 2 bis 3 Sekunden zu blinken. Ich habe die ganze Nacht damit verbracht, den Code auszuwählen. Auf dem Prüfstand befand sich kein solcher Pfosten. Das Problem liegt also nicht im Code. Ich kramte in einer Reihe von Foren, fand in einer Toga in einem von ihnen eine Beschreibung eines ähnlichen Symptoms, überprüfte meine Vermutung - und das Problem verschwand. Und die Sache war, dass ich alle drei Arduins von einem Computer-Netzteil, 12 V, speiste und der alte Freeduino leise aß und nicht summte, und Arduino uno v3 konnte nicht, und als alle Relais eingeschaltet waren, wurde der Leistungsregler so erwärmt, dass Es war unmöglich zu berühren. Reduzierte die Versorgungsspannung auf 5V 2A - und es funktionierte wie es sollte.Es gibt viele Pläne, wir müssen die Reparatur in der Wohnung abschließen, der Korridor und das Badezimmer mit der Toilette sind in einer Linie, in meinen Träumen möchte ich den Warmwasserbereiter und jede Steckdose steuern, da ich jetzt jede Menge Arduin an den I2C-Bus hängen kann und jeder sein eigenes Ding machen wird. Es ist auch geplant, der Din-Schiene Impulsrelais hinzuzufügen, damit die Relaismodule nur diese Impulsrelais steuern und bereits die gesamte Last durch diese geht. Weil es ernsthafte Zweifel an der Zuverlässigkeit chinesischer Relaismodule gibt. Aber das ist alles in der Zukunft.Wie versprochen, Links zu github: SketchyWebinterfacefür Arduino