Unser Grundstück ist - wie häufig hier in Thailand - von einer zwei Meter hohen Mauer eingerahmt. Die hält Tiere wie streunende Strassenhunde aber auch Schlangen oder ähnliches ab. Von innen kann man diese Wand natürlich üppig begrünen.
Ein schicker Augenschmauss wäre eine indirekte Beleuchtung mit dimmbaren LED Spotlights hinter den Pflanzen. Dabei geht es um eine Länge von ca. 40m die mit Licht versorgt werden will. Eine Lösung muss her…
Im Garten liegt bei uns eine 230V Versorgung, die aber nicht schaltbar oder dimmbar ist, da andere Verbraucher wie Aussensteckdosen und das Bodenlicht daran angeschlossen sind. Eine Zusatzverdrahtung zum Haus habe ich ausgeschlossen, nachdem ich erfolglos versucht habe den Verlauf der unterirdischen Rohre zu erfassen. Also muss etwas drahtloses her, das (wie immer) auch in Home Assistant einbindbar ist.
Vorab habe ich schon die LED Spots nach Aussehen, Leistung, Preis und Größe ausgewählt. Dabei fiel die Wahl auf einen 5W/600lm Strahler mit 12V AC/DC Versorgung im IP65 Gehäuse vom thailändischen Amazon: LAZADA.
Bei einem Preis von unter 4€ pro Stück kommt das ganze wirklich in einem wasserfesten Alugehäuse mit einer internen Steuerplatine und funktioniert! Lichtgeber ist eine 3mm LED die mit 21.5V bei einem Konstantstrom von 266mA betrieben wird. Die höhere Spannung wird durch einen Boost Regler (BP1808) erreicht, der auch einen ungenutzten DIM Eingang hat. Dieser kann analog oder über ein PWM Signal angesteuert werden. Ein erster Test mit einer 500Hz PWM zeigt das gewünschte Dimmverhalten.
Jetzt brauchen wir nur ein Idee wie wir die im Home Assistant ausgewählte Dimmung für jedes Spotlight als PWM Signal bereitstellen. Das Gehäuse der LED erlaubt dabei keine voluminöse Lösung. DMX512 erscheint hier etwas überdimensioniert. Also warum nicht auch mal einen proprietären Ansatz wagen.
Erste Versuche mit einer Kommunikation über Niedrigvoltleitungen schlugen aus Zuverlässigkeits- und Skalierungsgründen fehl. Dazu gibt es durchaus einen pfiffigen Ansatz: Simple Circuit Communicates Over Low-Voltage Power Lines. Das ganze mit einem ATTINY85 implementiert hat grundsätzlich mit zwei Transceiver über 10m bei 2400 Baud funktioniert, ist für den hiesigen Anwendungsfall out-of-the-box aber nicht geeignet.
Für Datenübertragungen über mehrere zehn Meter kommt einem immer auch RS485 in den Sinn. Passende Treiber-IC sind zuhauf verfügbar und eine Standard-UART reicht aus als Kommunikationsschnittstelle. Um es vorweg zunehmen, diese Idee hat dann auch zum Erfolg geführt. Hier die Beschreibung …
Der LED Boost Driver mit dem BP1808 muss um eine Schaltung für den Empfang von seriellen Daten über RS485 erweitert werden und das ganze möglichst klein. Der Innenraum des Lampengehäuses fasst nur ca. 40mm x 20mm. Als Steuer-CPU fiel die Wahl auf einen ATTINY85 von MicroChip den es im kleinen 8-pin SOIC Gehäuse gibt. Zudem verfügt er über ein EEPROM (z.B. für die Lampen ID), Oszillator on Chip und eine debugWIRE Schnittstelle. Die erlaubt in-place Debugging und vereinfacht so die Softwareentwicklung. Den RX485 Driver gibt es z.B. von MAXIM auch im SOIC8 Gehäuse.
Alles zusammengefasst sieht der Schaltplan dann so aus:
Der LED Boot Driver ist identisch zur Originalversion und nur durch die PWM-Ansteuerung ergänzt. Da ich bei den ersten Versuchen ein paar Hardwareausfälle (ATTINY85 + BP1808) wegen Überspannung hatte, wird das PWM Signal galvanisch mit einem Optokoppler (OC1) getrennt. An der RS485 Schnittstelle sind auch optional die Abschlusswiderstände vorgesehen (R1,R3,R4). Der MAXIM Baustein arbeitet im Halb-Duplex, daher steuern wir die Richtung (Empfangen oder Senden) zusätzlich über den ATTINY85. Der letzte freie Ausgang an der CPU steuert eine Status-LED (LED1). Die hilft beim Debuggen und der Inbetriebnahme, vor allem wenn man die POWER-LED abgeklemmt lässt.
Bei den geometrischen Vorgaben kommen wir um eine beidseitige Bestückung nicht herum. Aber auf der zweiten Seite befinden sich nur die vier SS14 Dioden (D3-D6) des Brückengleichrichters und der große Thru-hole Kondensator C8. Diese Komponenten müssen dann handgelötet werden aber der Rest kann vorab im Reflow-Ofen (bei mir T-962) 'garen'.
Das Platinenmaß geht mit 39.3mm x 19mm schon an die mechanische Grenze aber es passt. In Realität sieht die Platine auf der Vorderseite doch schon ordentlich gepackt aus. Die handgeschriebene 4 auf der CPU ist die progammierte ID der LED. Über diese Nummer läßt sich das Spotlight einzeln ansprechen. Doch dazu später mehr.
Um die Platine elektrisch isoliert in das Gehäuse einzubauen, drucke ich aus flexiblem TPU ein zweiteiliges Cover. An beiden Enden über die Platine geschoben bleibt dann alles vor ungewollten Kurzschlüssen geschützt. Das STL File ist im Downloadbereich zu finden.
Den physikalischen Layer haben wir mit RS485 festgelegt aber wir brauchen noch einen Data Link Layer, der die Fehlerfreiheit der Übertragung erhöht, schließlich sollen die Spotlights nicht flackern nur weil auf dem Bus gerade eine unerwünschte Signalparty stattfindet. Im Netz fand ich eine schlanke Lösung, die auch eine Python Version für den PC beinhaltet. Sie heißt MIN (Microcontroller Interconnect Network ). Der Payload läßt sich frei definieren und der Inhalt ist über eine 32-bit CRC abgesichert.
In meiner Implementierung besteht ein Frame aus 13 Bytes:
der je nach Funktion vom angesprochenen Spotlight beantwortet wird. Bei Broadcastbefehlen erfolgt keine Antwort von der Gegenseite. Hier die kurze Befehlsübersicht:
// min_id (8-bit): // 0x00-0x0f ID LED lamp 1 - 16 -> function + value // 0x10-0x1F Response ID LED lamp 1 - 16 // 0x3E all LED -> function + value (no response) // 0X3F - // // Payload / Response: // Byte 1 Function // 0x00 LED Off // 0x01 LED Off (stored delay) // 0x02 LED On // 0x03 LED On (stored value/delay) // 0x04 Set stored value/delay // 0x05 Get stored value/delay // 0x06 Status // 0x07 Status LED on/off // Byte 2 Value 0..255 LED brightness // Byte 3 Delay 0..255 LED fade up/down delay // Payload Response Error: // Byte 1 0xFF // Byte 2 Error code // 0x00 Payload size wrong (byte 3 = wrong size value)) // 0x01 Unknown Function // Byte 3 <not used>
In den Spotlights lassen sich auch individuelle Helligkeits- und Fadewerte abspeichern, die dann bei Broadcast Befehlen unterschiedliche Helligkeiten ermöglichen. Im Module min.c
ist das Protokoll implementiert. Zusätzlich benötigen wir noch eine Software UART Emulation, da der ATTINY85 keine H/W Variante besitzt. Die Baudrate ist auf 9600 Baud festgelegt damit keiner ins Schwitzen kommt, die Framelänge liegt so bei ca. 14ms. Mit Hilfe der kostenlosen IDE MPLAB und der kostenfreien Variante des XC8 C-Compilers von MicroChip läßt sich die S/W kompilieren und auf den Chip bannen.
In der Werkseinstellung des ATTINY85 ist das debugWIRE Interface ausgeschaltet und eine Programmierung nur über ISP möglich. Das bindet mehrere Pins des Prozessors und geht nicht on-board. Daher sollte man sich einen kleinen Programmieradapter (Sockel) für das Package SOIC8 (200mil) zulegen und die Fuses vor dem Bestücken damit programmieren. Danach läßt sich die Software auch über das 1-pin Interface dWire programmieren.
Das Debug- und Programmingtool der ersten Wahl ist und bleibt der SNAP (PG164100). Alle diese Tools sind im Online Markt oder der Bucht einfach und für den DIY-Geldbeutel erschwinglich zu finden.
Hat man die Spotlights wie oben beschrieben programmiert, können die LEDs schon über einen USB-RS485 Wandler mit dem PC angesprochen werden. Für das MIN Protokoll steht auch eine Pythonvariante zur Verfügung.
Mein Ziel ist es aber die Spotlights in Home Assistant (HA) zu integrieren. Dazu brauchen wir ein Gateway, das die Spotlights als Lights in HA abbildet und zusätzlich einen UART Server beinhaltet, damit wir auch beliebige Befehle an die LEDs senden können. Klingt kompliziert ist es aber mit ESPHome nicht.
Für den UART Server gibt es schon hier eine schicke Lösung. Den Code müssen wir nur leicht anpassen, in dem wir vor und nach dem Senden die Richtung des RS485 Driver anpassen. Die Zeilen mit ### wurden in die Senderoutine zusätzlich eingebaut. Der gesamte veränderte Code ist im Downloadbereich zu finden.
void StreamServerComponent::write() { digitalWrite(DIR_PORT, HIGH); // ### set direction to receive #if ESPHOME_VERSION_CODE >= VERSION_CODE(2021, 10, 0) this->stream_->write_array(this->recv_buf_); this->recv_buf_.clear(); #else size_t len; while ((len = this->recv_buf_.size()) > 0) { this->stream_->write(this->recv_buf_.data(), len); this->recv_buf_.erase(this->recv_buf_.begin(), this->recv_buf_.begin() + len); } #endif this->stream_->flush(); // ### Added by DIRB digitalWrite(DIR_PORT, LOW); // ### set direction to receive }
Für die Einbindung der LEDs als Lights schreiben wir wieder ein custom component. Das folgende C-Program garden-leds.h
stellt einen Float Output für Home Assistant zur Verfügung und beinhaltet eine schlanke Codierung des MIN Protokolls.
Nun legen wir wieder ein neues Device in ESPHome an und verweisen auf die beiden Custom Codes stream-server
und garden-leds.h
.
Den ersten Part haben wir vorher in config/esphome/my_components/stream-server
und das zweite File in config/esphome
kopiert.
esphome: name: garden-leds includes: - garden-leds.h external_components: - source: type: local path: my_components components: [stream_server]
Zu guter Letzt das Setup des Light und des Servers:
uart: id: uart_min tx_pin: GPIO1 rx_pin: GPIO3 baud_rate: 9600 stream_server: uart_id: uart_min port: 6638 output: - platform: custom type: float lambda: |- auto min_led_pwm = new Min_Led(); App.register_component(min_led_pwm); return{min_led_pwm}; outputs: id: led_pwm light: - platform: monochromatic name: "Garden Wall" output: led_pwm
Gegebenenfalls müssen die Pins tx_pin, rx_pin
für die serielle Schnittstelle und der Richtungspin DIR_PORT
in garden-leds.h
für die eigene Hardware angepasst werden.
Für die H/W brauchen wir neben dem ESP Modul der Wahl, einen AC/DC Step-Down Regler von ~12VAC auf +5VDC, level shifter 5V↔3V und ein RS485 Driver Modul. Das gibt es auch wieder fertig in der Bucht. Die Verdrahtung ist einfach, hier meine Version:
ESP8266 | RS485 Driver |
---|---|
GPIO1 | DI |
GPIO3 | RO |
GPIO13 | RE+DE |
+5V | VCC |
GND | GND |
Das Ganze dann auf einer Lochrasterplatine aufgelötet und in einem wasserfesten Gehäuse verpackt sieht dann so aus:
Zwischen den Spotlights und dem Gateway wird ein 4-adriges Kabel benötigt. Da ich Aussen in einem wasserdichten Rohr verlege, reicht mir eine PVC-Schlauchleitung H03VV-F4G0,75. Bei der Verdrahtung einfach die 12VAC und die beiden Signale A + B untereinander verbinden:
Gateway | Spot 1 | Spot 2 | … | Spot n |
---|---|---|---|---|
~12V | ~12V | ~12V | … | ~12V |
~12V | ~12V | ~12V | … | ~12V |
A | A | A | … | A |
B | B | B | … | B |
Je nach Anzahl der Spots brauchen wir noch einen leistungsfähigen Trafo für ~230V auf ~12V. Hier kann man z.B. einen gebrauchten Halogentrafo wiederverwenden. Die finden sich zuhauf in Gebrauchtwarenmärkten. Meinen 200W Trafo von ABB inkl. Sicherungen gab es dort für 8,-€.
Schliessen wir nun das fertig verdrahtete Konqlumerat an, steht uns das Licht mit DImmfunktion in Home Assistant zur Verfügung. Die Fadezeit kann auch dort festgelegt werden und steht standardmässig auf 1s. Durch den Stream-Server können wir aber auch mit z.B. einem PC auf die LEDs zugreifen. Dazu habe ich ein kleines Pythonprogramm geschrieben (Source Code im Downloadbereich).
Damit lassen sich alle Funktionen auf alle oder einzelne LEDs ausführen. Mit CHK wird nach angeschlossen LEDs gesucht und im unteren Bereich steht ein einfacher Skript Editor zur Verfügung der die Programmierung von Abläufen erlaubt, bei einer Stepzeit von 100ms also 10Hz. Ein Gimmick für Silvester oder andere Parties.
Im Moment gibt es nur einen Testaufbau mit zwei Spotlights der sehr gut funktioniert. Die vollständige Installation im Aussenbereich erfolgt erst 2023. Ich werde berichten…
Wenn ihr meine Arbeit unterstützen wollt, so könnt ihr mir gerne einen Cappuccino oder so spenden: .