Motivation / Projektidee
Vor Kurzem ist bei uns eine Photovoltaikanlage eingezogen. Damit alle im Haus einfach und schnell erkennen können, ob wir gerade Strom im Überfluss haben oder ob wir teuren Strom zukaufen müssen, sollte eine simple Anzeige her.
Ein zusätzliches Display nur für diesen Zweck wollte ich nicht extra aufstellen. Eine weitere Kachel in Home Assistant war mir hingegen nicht präsent genug.
Daraus entstand die Idee: Warum nicht einfach eine Ampel? Die drei Farben einer Ampel kennt jeder und man versteht sofort, was gemeint ist. Außerdem fand ich die Idee irgendwie originell.
Eine Ampel muss also her. Sie zeigt über ihre Farben den aktuellen Status unserer Energieversorgung an:
- GRÜN: Der Hausbedarf wird gerade voll über die PV-Anlage abgedeckt → Jetzt ist es Zeit, optionale Verbraucher zu nutzen.
- GELB: Der Hausbedarf wird gerade aus der Batterie gedeckt.
- ROT: Weder PV noch Batterie können den Hausbedarf gerade decken → Jetzt sollten Verbraucher nach Möglichkeit nur so wenig wie nötig genutzt werden.
Elektronik / ESPHome
Eine fertige Ampel, die ich direkt in Home Assistant integrieren kann, kannte ich leider nicht. Meine Elektronikkenntnisse sind zudem sehr begrenzt. Da ich durch Home Assistant schon öfter mit ESPHome in Kontakt gekommen bin, habe ich mich für diese Plattform entschieden. Dass die Elektronikkomponenten günstig zu haben sind und die ESPs im Betrieb nur minimal Strom benötigen, passt perfekt ins Konzept.
Bauteile
- Wemos D1 mini mit ESP8266
- 3 Standard 5 mm LEDs (Grün, Gelb, Rot)
- Ein paar Litzenreste
Schaltplan
Für den ersten Entwurf beschreibe ich den Aufbau hier nur als Text:
- Plus (langes Bein) rote LED → D1
- Plus (langes Bein) gelbe LED → D2
- Plus (langes Bein) grüne LED → D3
- Minus alle LEDs verbinden → G
ESPHome
Um die Ampel über Home Assistant schalten zu können, wird der ESP über den ESPHome-Builder geflasht. Anbei der YAML-Code. Bei der Erstellung habe ich mich von Gemini unterstützen lassen. Ich habe die Funktionen zur Ansteuerung der LEDs noch etwas erweitert, um mit verschiedenen Effekten spielen zu können.
esphome:
name: esphome-ampel-02
friendly_name: ESPHome Ampel 02
esp8266:
board: esp01_1m
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "c8ar3pT+Lxxxxxxxxxxxxxxxx=" # Diesen Key bitte selbst erstellen
ota:
- platform: esphome
password: "94xxxxxxxxxxa526"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esphome-Ampel-02"
password: "Fbdxxxxxxxx0Sx"
web_server:
port: 80
# Definition der Pins als Licht-Ausgänge
output:
- platform: esp8266_pwm
pin: GPIO5 # Entspricht D1
id: led_rot_out
- platform: esp8266_pwm
pin: GPIO4 # Entspricht D2
id: led_gelb_out
- platform: esp8266_pwm
pin: GPIO0 # Entspricht D3
id: led_gruen_out
# Erstellung der Entitäten für Home Assistant
light:
- platform: monochromatic
name: "Ampel Rot"
output: led_rot_out
id: ampel_rot
effects:
- pulse:
name: "Pulsieren"
transition_length: 1000ms
update_interval: 1000ms
- strobe:
name: "Blinken"
- flicker:
name: "Flackern"
alpha: 80%
intensity: 50%
- platform: monochromatic
name: "Ampel Gelb"
output: led_gelb_out
id: ampel_gelb
effects:
- pulse:
name: "Pulsieren"
transition_length: 1000ms
update_interval: 1000ms
- strobe:
name: "Blinken"
- flicker:
name: "Flackern"
alpha: 80%
intensity: 50%
- platform: monochromatic
name: "Ampel Gruen"
output: led_gruen_out
id: ampel_gruen
effects:
- pulse:
name: "Pulsieren"
transition_length: 1000ms
update_interval: 1000ms
- strobe:
name: "Blinken"
- flicker:
name: "Flackern"
alpha: 80%
intensity: 50%
Mit der zugehörigen ESPHome-Integration stehen dann folgende Entitäten zur Verfügung:
Automatisierung / Homeassistant
Die Umsetzung in Home Assistant teilt sich in zwei Bereiche auf. Hintergrund ist, dass als Übergabe zwischen beiden Teilen ein „Helfer“ erstellt wird, der wiederum auch für andere Automatisierungen als Input genutzt werden kann.
Helfer: PV-Ampel_Wert
Dieser Helfer soll immer die aktuelle Information enthalten, welchen Status unser Hausverbrauch gerade hat:
- 1: PV-Überschuss mit Abregelung
- 2: PV-Überschuss
- 3: Batteriebetrieb
- 4: Batterie- und Netzbezug
- 5: Voller Netzbezug
Dazu wird ein „Nummern-Eingabe“-Helfer (input_number) mit folgender Konfiguration angelegt:
Berechnung des PV-Ampel-Status
Für die Berechnung des Status erstelle ich eine Automatisierung und nutze im Wesentlichen drei Sensoren:
- Aktuelle Leistung des Stromzählers (in meinem Bespiel „sensor.stromzaehler_hausstr_curr_w“)
- Aktuelle PV-Leistung (in meinem Beispiel „sensor.one12_solar_production“)
- Aktuelle Batterieentladeleistung (in meinem Beispiel "sensor.one12_battery_discharge)
Diese Automatisierung schreibt nun den aktuellen Status als Wert in den zuvor erstellten Helfer „PV-Ampel-Wert“.
Zum Status 1 „PV-Überschuss mit Abregelung“ ist zu sagen, dass dieser Zustand nur für neuere PV-Anlagen relevant ist, deren Einspeiseleistung prozentual zur kWp-Leistung begrenzt ist. In meinem Fall kann ich maximal 6900 W ins Netz einspeisen, obwohl meine Anlage 11,5 kWp hat. Daher werte ich den Zeitpunkt, an dem mehr als 6800 W ins Netz eingespeist werden, als Abregelung.
alias: PV-Ampel Statusberechnung
description: ""
triggers:
- trigger: state
entity_id:
- sensor.stromzaehler_hausstr_curr_w
- trigger: numeric_state
entity_id:
- sensor.one12_battery_discharge
above: 0.1
below: 0.1
conditions: []
actions:
- choose:
- conditions:
- condition: numeric_state
entity_id: sensor.stromzaehler_hausstr_curr_w
below: -6800
sequence:
- action: input_number.set_value
metadata: {}
data:
value: 1
target:
entity_id: input_number.pv_ampel_wert
alias: 1 Überschuss und Abregelung
- conditions:
- condition: and
conditions:
- condition: numeric_state
entity_id: sensor.stromzaehler_hausstr_curr_w
below: 100
- condition: numeric_state
entity_id: sensor.one12_solar_production
above: 0.5
- condition: numeric_state
entity_id: sensor.one12_battery_discharge
below: 0.1
sequence:
- action: input_number.set_value
metadata: {}
data:
value: 2
target:
entity_id: input_number.pv_ampel_wert
alias: 2 Überschuss
- conditions:
- condition: numeric_state
entity_id: sensor.stromzaehler_hausstr_curr_w
below: 100
sequence:
- action: input_number.set_value
metadata: {}
data:
value: 3
target:
entity_id: input_number.pv_ampel_wert
alias: 3 Batteriebetrieb
- conditions:
- condition: and
conditions:
- condition: numeric_state
entity_id: sensor.stromzaehler_hausstr_curr_w
above: 100
- condition: numeric_state
entity_id: sensor.one12_battery_discharge
above: 0.1
sequence:
- action: input_number.set_value
metadata: {}
data:
value: 4
target:
entity_id: input_number.pv_ampel_wert
alias: 4 Batterie- und Netzbezug
- conditions:
- condition: and
conditions:
- condition: numeric_state
entity_id: sensor.stromzaehler_hausstr_curr_w
above: 100
- condition: numeric_state
entity_id: sensor.one12_battery_discharge
below: 0.1
sequence:
- action: input_number.set_value
metadata: {}
data:
value: 5
target:
entity_id: input_number.pv_ampel_wert
alias: 5 voller Netzbezug
mode: single
PV-Ampel Info und Aktionen
Der Wert des Helfers soll nun genutzt werden, um die Lichter der Ampel zu schalten:
- 1: PV-Überschuss mit Abregelung → LED Grün blinken
- 2: PV-Überschuss → LED Grün leuchten
- 3: Batteriebetrieb → LED Gelb leuchten
- 4: Batterie- und Netzbezug → LED Rot leuchten
- 5: Voller Netzbezug → LED Rot leuchten (Anmerkung: Ich dachte zuerst, dass rotes Blinken hier gut wäre. Aber im Winter, wenn Status 5 über viele Stunden ansteht, würde das ziemlich nerven.)
description: ""
mode: single
triggers:
- trigger: state
entity_id:
- input_number.pv_ampel_wert
- trigger: time_pattern
hours: /1
conditions: []
actions:
- choose:
- conditions:
- condition: template
value_template: "{{ is_state('input_number.pv_ampel_wert', '0.0') }}"
sequence:
- alias: ESPHome Ampel 02
sequence:
- action: light.turn_off
metadata: {}
data: {}
target:
entity_id:
- light.esphome_ampel_02_ampel_gelb
- light.esphome_ampel_02_ampel_gruen
- light.esphome_ampel_02_ampel_rot
alias: 0 - Init
- conditions:
- condition: template
value_template: "{{ is_state('input_number.pv_ampel_wert', '1.0') }}"
sequence:
- alias: ESPHome Ampel 02
sequence:
- action: light.turn_on
metadata: {}
target:
entity_id: light.esphome_ampel_02_ampel_gruen
data:
effect: Pulsieren
- action: light.turn_off
metadata: {}
target:
entity_id:
- light.esphome_ampel_02_ampel_gelb
- light.esphome_ampel_02_ampel_rot
data: {}
alias: 1 - Überschuss und Abregelung
- conditions:
- condition: template
value_template: "{{ is_state('input_number.pv_ampel_wert', '2.0') }}"
sequence:
- alias: ESPHome Ampel 02
sequence:
- action: light.turn_on
metadata: {}
target:
entity_id: light.esphome_ampel_02_ampel_gruen
data:
effect: None
- action: light.turn_off
metadata: {}
target:
entity_id:
- light.esphome_ampel_02_ampel_gelb
- light.esphome_ampel_02_ampel_rot
data: {}
alias: 2 - Überschuss
- conditions:
- condition: template
value_template: "{{ is_state('input_number.pv_ampel_wert', '3.0') }}"
sequence:
- alias: ESPHome Ampel 02
sequence:
- action: light.turn_on
metadata: {}
data: {}
target:
entity_id: light.esphome_ampel_02_ampel_gelb
- action: light.turn_off
metadata: {}
target:
entity_id:
- light.esphome_ampel_02_ampel_rot
- light.esphome_ampel_02_ampel_gruen
data: {}
alias: 3 - Batteriebetrieb
- conditions:
- condition: template
value_template: "{{ is_state('input_number.pv_ampel_wert', '4.0') }}"
sequence:
- alias: ESPHome Ampel 02
sequence:
- action: light.turn_on
metadata: {}
data:
effect: None
target:
entity_id: light.esphome_ampel_02_ampel_rot
- action: light.turn_off
metadata: {}
data: {}
target:
entity_id:
- light.esphome_ampel_02_ampel_gelb
- light.esphome_ampel_02_ampel_gruen
alias: 4 - Batterie- und Netzbezug
- conditions:
- condition: template
value_template: "{{ is_state('input_number.pv_ampel_wert', '5.0') }}"
sequence:
- alias: ESPHome Ampel 02
sequence:
- action: light.turn_off
metadata: {}
data: {}
target:
entity_id:
- light.esphome_ampel_02_ampel_gelb
- light.esphome_ampel_02_ampel_gruen
- action: light.turn_on
metadata: {}
data:
effect: None
target:
entity_id: light.esphome_ampel_02_ampel_rot
alias: 5 - voller Netzbezug
Gehäuse / 3D-Druck
Jetzt musste das Ganze nur noch in ein passendes Gehäuse. Dafür habe ich eine sehr gute Basis bei MakerWorld gefunden: Traffic Light auf MakerWorld
Damit die LEDs ordentlich hineinpassen, ist etwas manuelle Nachbearbeitung notwendig. Als Diffusor habe ich einfach ein Blatt Papier zwischengelegt. Wer transparentes Filament besitzt, kann es natürlich noch wertiger gestalten.
Den passenden Sockel habe ich selbst entworfen. Diesen stelle ich euch natürlich gerne zur Verfügung. Ich habe bisher leider keine Möglichkeit gefunden, die STL-Datei direkt anzuhängen, daher schickt mir bei Interesse einfach eine PN. Die Ampel kann einfach von oben in den Sockel gesetzt werden und klemmt dort fest. Der Platz im Inneren ist ausreichend für den D1 mini. Bei der Verkabelung muss man allerdings etwas sparsam sein, damit alles Platz findet.
Fazit
Bei diesem Projekt kommen viele Facetten der Bastler- und DIY-Welt zusammen: Home Assistant, Mikrocontroller, PV und 3D-Druck. Ich hoffe, dass ich euch damit inspirieren konnte, und freue mich auf den Austausch mit euch!





