[Projekt] PV-Ampel

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:

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!

14 „Gefällt mir“

Bin ja auch Fan der „alles im grünen Bereich“ Logik! :+1:

Schönes Projekt.

Ich hoffe mal das der ESP nicht zu warm wird im Sommer,
in seinem kleinen Gehäuse oder
hast du irgendwo für Lüftung gesorgt?

Einige meiner früheren Gehäuse waren auch in der Art wie deines und
nach dem „ESP Hitze Tod“ habe ich alle zu kleinen Gehäuse verändert.

1 „Gefällt mir“

Gefällt mir auch dein Projekt und auch die Umsetzung der Ampel sieht echt schick aus. :+1:

Das ist für viele im Haushalt wohl leichter abzulesen, als irgendeine Zahl zu interpretieren. Wäre für meine Frauen auch etwas, obwohl ich sie inzwischen schon gut zur Nutzung der HA App bewegen konnte. :wink:

2 „Gefällt mir“

Da fehlt mir bislang noch die Erfahrung. Aktuell gibt’s noch keine Probleme und der Esp hält noch durch

Könntest ja auch noch einen Sensor zB. DS18B20 mit ins gehäuse packen und dann in Home Assistant per Automation überwachen!? Das sind 10 Zeilen Code mehr und ne halbe Stunde basteln! :wink:

1 „Gefällt mir“

Es kommt auch darauf an, was der ESP leisten muss,
vielleicht passt es auch bei dir so.

Man kann das Gehäuse hinten (unten) auch etwas auf lassen so das
das Metallgehäuse des D1 mini dort frei liegt.

Ich habe mir das so angewöhnt die Gehäuse immer ja nach Aufstellung,
oben und unten „etwas offen“ zu lassen.

1 „Gefällt mir“

Moin
Eine wirklich schöne Umsetzung deiner Idee.
:+1:

Ich habe bei mir 2x Ulanzi TC001 stehen, die mir einige Werte anzeigt.
Unteranderem wie viel Leistung gerade von der PV kommt, auch wieviel Leistung in bzw. aus dem Akku gezogen wird.
Zusätzlich habe ich die Indikatoren der Ulanzi (an der rechten Seite kann man „Balken“ einblenden, oben mitte und unten) so angesteuert, das der Obere blau blinkt wenn was in den Akku gespeißt wird und der Untere rot blinkt wenn was aus dem Akku gezogen wird.
Also auch eine kleine „Ampel“ :wink:
awtrix
PS. der grüne Indikator in der Mitte signalisiert mir, das irgendwo ein Fenster auf ist.

3 „Gefällt mir“