Table of Contents

Solar Akku Lader

Der Quellcode zum Projekt ist auf GitHub verfügbar https://github.com/mschubi72/ESP32_Laderegler

Derzeitiger Aufbau:

Vorgedanken

Seit Anfang 2022 habe ich eine Balkonsolaranlage. Leider wird relativ viel Energie eingespeist, deshalb muss ein Zwischenspeicher her.

Fertige Lösungen sind zu teuer, so dass mein Solarlader ein reines DIY Projekt wird.

Folgende Anforderungen:

Komponenten

Funktionale Übersicht

Umsetzung

Ich habe angefangen die Software zu schreiben. Da ich nicht der geborene C/C++ Entwickler bin, sicher etwas Kraut und Rüben, aber es soll ja einfach nur funktionieren. Den Softwarestand checke ich ab und zu mal bei GitHub ein (https://github.com/mschubi72/ESP32_Laderegler).

Auch bei der Hardwareanschaffung und Verkabelung hat sich was getan. Die Hauptkomponenten sind verdrahtet.

Software

Zustände Laderegler am Tag

Am Tag muss der Laderegler entscheiden, wann und wie viel geladen wird. Ich nehme hier einfach Übergänge von Zuständen an.

Faktoren sind die Solarstromerzeugung, Solarstromüberschuß (Einspeisung ins öffentliche Netz), Ladeleistung zum Akku. Da der ganze Ladeprozess doch einige Verluste mit sich bringt, lege ich die Schwelle bei mehr als 20 Watt Überschuss an. Unabhängig vom State wird bei voller Batterie der Ladevorgang abgeschaltet (separate Prüfung).

Daraus ergeben sich folgende Zustände (states):

State # Solarstrom Einspeisung Ladeleistung Bemerkung
State-0 0 ⇐ 0 0 Wenn kein Solarstrom, dann alles andere egal
State-1 >0 ⇐ 0 0 Keine Einspeisung, Keine Ladeleistung
State-2 >0 >0 & < 20W 0 es wird unterhalb Schwelle eingespeist, keine Ladeleistung
State-3 >0 >20W 0 Einspeisung oberhalb Schwelle, aber noch keine Ladung
State-4 >0 ⇐ 0 >0 Keine Einspeisung, es wird aber noch geladen
State-5 >0 >0 & < 20W >0 Einspeisung unter Schwelle, wird geladen→Ideal Status
State-6 >0 >20W >0 Einspeisung oberhalb Schwelle, es wird geladen→Ladeleistung steigern

Folgende Übergänge sind möglich:

State old state new Bemerkung Action
State-0 State-0 keine Änderung
State-1 Solarstrom, aber kein Überschuss→keine Ladeleistung
State-2 Solarstrom, Überschuss unter Schwelle→keine Ladeleistung
State-3 Solarstrom, Überschuss über Schwelle→beginn mit laden, aber Ladeleistung ist noch null, da gerade eingeschalten Laden mit kleinster Leistung beginnen
State-1 State-0
State-1
State-2
State-3 Laden mit kleinster Leistung beginnen
State-2 State-0
State-1
State-2
State-3 Laden mit kleinster Leistung beginnen
State-3 State-0
State-1
State-2
State-3 Wenn genug Überschuss, dann Laden einschalten, sonst Fehler
State-4 Laden wurde begonnen, gibt keine Einspeisung mehr Laden abstellen
State-5 Laden wurde begonnen, Einspeisung unter Schwelle→ Ladeleistung OK
State-6 Laden wurde begonnen, Einspeisung über Schwelle Ladeleistung vergrößern
State-4 State-4 Es wird mit zu viel Power geladen Ladeleistung verringern
State-5 Laden OK
State-6 noch Überschuss Ladeleistung erhöhen
State-0 bis 3 Ladeleistung kann nicht weiter verringert werden Laden beenden
State-5 State-4 Es wird mit zu viel Power geladen Ladeleistung verringern
State-5 Laden OK
State-6 Gibt zu viel Überschuss Ladeleistung vergrößern
State-6 State-4 Es wird mit zu viel Power geladen Ladeleistung verringern
State-5 Laden OK
State-6 Ladeleistung erhöhen Ladeleistung erhöhen

Oder als mehr oder weniger sinnvolles Diagramm:

Sonoff Dual R3

Zum Erfassen der Ladeleistung und Einspeisleistung und dem entsprechenden Schaltvorgängen nutze ich einen Sonoff Dual R3, der mit ESPHome umgeflashed wurde. Der Webserver ist auch enabled. Somit Schalte ich die Ausgänge einfach per REST API POST Kommandos. Die Leistungsübermittlung etc. aber weiterhin über die ESP32 API direkt zum Homeassistant.

Wichtig ist die Leiterplattenversion. Ab Version 2.0 des Dual R3 (wie bei mir) wird der BL0939 Chip zum Erfassen von Strom/Spannung/Leistung genutzt. Vorherige Revisionen den CSE7761. (siehe https://esphome.io/devices/sonoff.html#sonoff-dual-r3-v1-x-v2-x)

Folgendes YAML File für ESPHome:

substitutions:
  devicename: lader-power
  long_devicename: Sonoff DualR3 Lader
 
#
# Dual r3 V2.0
#

esphome:
  name: $devicename

esp32:
  board: esp32dev
  framework:
    type: arduino
 
# Enable logging
logger:
#  level: VERY_VERBOSE 
 
# Enable Home Assistant API
api:

ota:
  password: "0a46d9b044d9acb408d44bf02d620ffb"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
 
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Lader-Power Fallback Hotspot"
    password: "7jnCyGWRuDsb"

captive_portal:
    
web_server:
  port: 80
  
uart:
  tx_pin: GPIO25
  rx_pin: GPIO26
  baud_rate: 4800
  parity: NONE
  stop_bits: 2
  
sensor:
  - platform: wifi_signal
    name: "$long_devicename WiFi Signal"
    update_interval: 60s
  - platform: bl0939
    update_interval: 5s
    voltage:
      name: "$devicename Voltage"
    current_1:
      name: "$devicename Current OUT"
    current_2:
      name: "$devicename Current IN"
    active_power_1:
      name: "$devicename Power OUT"
    active_power_2:
      name: "$devicename Power IN"
output:
  - platform: gpio
    pin: GPIO27
    id: relay1
  - platform: gpio
    pin: GPIO14
    id: relay2
switch:
  - platform: output
    name: "$devicename relay OUT"
    output: relay1
    id: sw1
  - platform: output
    name: "$devicename relay IN"
    output: relay2
    id: sw2
status_led:
  pin:
    number: GPIO13
    inverted: yes
binary_sensor:
  - platform: gpio
    pin:
      number: GPIO0
      mode: INPUT_PULLUP
      inverted: True
    name: "$devicename button"
    on_press:
      - logger.log: "$devicename button"
      - switch.toggle: sw2
  - platform: gpio
    pin:
      number: GPIO32
      mode: INPUT_PULLUP
      inverted: True
    name: "$devicename switch OUT"
    on_press:
      - logger.log: "$devicename switch OUT"
      - switch.toggle: sw1
  - platform: gpio
    pin:
      number: GPIO33
      mode: INPUT_PULLUP
      inverted: True
    name: "$devicename switch IN"
    on_press:
      - logger.log: "$devicename switch IN"
      - switch.toggle: sw2

Die Abfrage der zwei Relais erfolgt über REST API GET

http://<ip/fqdn>/switch/lader-power_relay_in

Es wird einfach der Componenten Name genommen und alle Leerzeichen durch Unterstriche ersetzt werden. Deshalb “Lader-Power Relay In” zu “lade-power_relay_in”. Der JSON Returnwert sieht dann so aus:

{
    "id": "switch-lader-power_relay_in",
    "value": false,
    "state": "OFF"
}

Geschaltet wird mit einem Postrequest:

http://<ip/fqdn>/switch/lader-power_relay_in/turn_on
http://<ip/fqdn>/switch/lader-power_relay_in/turn_off
http://<ip/fqdn>/switch/lader-power_relay_in/toggle

Hardware

"Schaltkasten"

Derzeitige Ansicht:

Nicht wundern, dass die Akkus noch in Folie sind. Durch die Tüten lassen sie sich sehr gut rausheben. War übrigens selber über das Gewicht der LiPOFe positiv überrascht.

ESP32

Meine ESP32 “Testumgebung” zum Entwickeln…

Links oben das Modul zur RS485 Kommunikation, in der Mitte oben der ADS1115 AD Wandler. Das Display ist noch “raw” - aktuell erzeugte Solarleistung, aktueller Verbrauch laut Zähler, Icon Ladezustand Akku, Spannung Akku (auf dem Foto eine Testfakewert), am Ende das Symbol, wenn geladen wird.