Heidelberg Energy Control Modbus RTU

Hallo liebe Community,

ich besitze eine Wallbox die Heidelberg Energy Control in Verbindung mit einem Rasberry PI und dem Home Assistant.
Da ich jetzt auch ein Elektrofahrzeug bestitze, würde ich meine Wallbox in den Home Assistant einbinden, und mit den Daten “arbeiten”. Ich habe die Anbindung mit einer Cat 7 Leitung S/FTP und einen RS485 RTU Adapter auf den HA realisiert.
Den Abschlusswiderstand von 120 Ohm auf meinen Adapter geklemmt, die DIP Schalter entsprechend Anleitung eingestellt.
Jetzt probiere ich seit Wochen mit der Integration “Modbus Adapter” Daten aus der Heidelberg abzufragen, leider ist die Frustration akutell groß, bis riesig. Ich kann machen was ich will, habe jetzt die Verkabelung kontrolliert, auf Paarität, auf Klemmfehler etc. alles richtig. Die Entität zum abfragen der Spannung L1-N will einfach nicht funktionieren, probiere aktuell auch nur input register, da ich mit meinem Halbwissen nichts schreiben möchten.
Hat jemand von euch vielleicht eine Lösung oder Erfahrungen? Ich schreibe meine Konfiguration mal unten dazu.

Liebe Grüße

Vinzent

modbus:
  - name: Modbus_Wallbox
    type: serial
    port: /dev/ttyUSB0
    baudrate: 19200
    bytesize: 8
    method: rtu
    parity: E
    stopbits: 1

    delay: 0
    message_wait_milliseconds: 30
    timeout: 5

    sensors:
    - name: SpannungL1N
      slave: 1
      address: 10
      input_type: input
      unit_of_measurement: V
      state_class: measurement
      scale: 0.01
      data_type: uint16

Hallo Vinzent,
ich kann dir zwar nicht mit dem Modbus helfen, aber vielleicht hilft dir meine Lösung. Ich habe die Ladeleistung an der Heidelberger fest auf 4 KW eingestellt (passt so am Besten zu meiner Solaranlage von 10 KW). Dann hab ich statt der Brücke für den Schlüsselschalter einen potentialfreien Shelly-Kontakt dazwischen gehängt (Anleitung Wallbox Seite A.1.6 Abb 6). Nun schalte ich mit HA die Wallbox über das Shelly-Relais an und aus entsprechend meinem Stromüberschuss. Das funktioniert super, ist einfach und ob das Auto nun 2 oder 6 Stunden lädt ist mir egal.
Grüsse
Jochen

1 „Gefällt mir“

Hallo,

ich habe eine Heidelberg Amperfied connect.home Wallbox mit Modbus/tcp.
Nach Anleitung habe ich den Modbus Part in eine modbus.yml Datei ausgelagert.
Der Teil mit Spannung_L1N sieht bei mir genauso aus:

  - name: wallbox010    # Voltage 01 
    address: 10
    input_type: input
    state_class: measurement
    unit_of_measurement: V
    slave: 1
    data_type: uint16

ich habe keine Probleme beim Auslesen der Sensoren. Evtl. kannst du mal “scale: 0.01” weglassen. Es hat etwas gedauert bis ich heraus gefunden habe, das nur eine Modbus Verbindung zur WB geht. Ich hatte noch ein Test Tool “ModbusTcpClient” zum Testen. Der hat die Verbindung immer dicht gemacht.
Evtl. hilft das ja …

Wenn du eine Idee hast, wie man Register schreiben kann. Wäre ich für einen Tip dankbar. Ich kämpfe gerade damit mein Auto automatisch via Modbus zu laden … leider bisher ohne Erfolg, ggf. mach ich dazu noch einen Thread auf.
Viel Erfolg.

1 „Gefällt mir“

Benutz doch einfach EVCC damit kannst dann alles steuern

https://github.com/evcc-io/hassio-addon

@didzo
wenn’s noch aktuell ist,
Hier meine ESP32 Datei, mit der ich die Daten der Wallbox abrufen, und den Ladestrom einstellen kann.

esphome:
  name: esp32-21
  friendly_name: Wallbox1

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxxxxxxxxxxxxxxxx"

ota:
  - platform: esphome
    password: "xxxxxxxxxxxxxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp32-21 Fallback Hotspot"
    password: "xxxxxxxxxxxxxxxx"

captive_portal:

uart:
  id: mod_bus
  rx_pin: GPIO16
  tx_pin: GPIO17
  baud_rate: 19200
  stop_bits: 1
  parity: even

modbus:
  id: modbus_heidelberg_wallbox
  flow_control_pin: 32
  uart_id: mod_bus
  send_wait_time: 200ms
  
modbus_controller:
  - id: heidelberg_wallbox_id01
    address: 0x1
    modbus_id: modbus_heidelberg_wallbox
    command_throttle: 200ms
    setup_priority: -10
    update_interval: 3s

sensor:
# WIFI Signal
  - platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
    name: "WiFi Signal dB"
    id: wifi_signal_db
    update_interval: 600s
    entity_category: "diagnostic"
  - platform: copy # Reports the WiFi signal strength in %
    source_id: wifi_signal_db
    name: "WiFi Signal Percent"
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "%"
    entity_category: "diagnostic"

#Ladestatus
  - platform: modbus_controller
    modbus_controller_id: heidelberg_wallbox_id01  
    id: charg_state
    name: "charging state"
    address: 0x0005
    register_type: read
    value_type: U_WORD
    skip_updates: 0

  - platform: modbus_controller
    modbus_controller_id: heidelberg_wallbox_id01  
    id: pcb_temp
    name: "PCB-Temperatur"
    address: 0x0009
    unit_of_measurement: "°C"
    register_type: read
    value_type: U_WORD
    skip_updates: 30
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: heidelberg_wallbox_id01  
    id: l1_l2_l3_power
    name: "L1 L2 L3 Power"
    address: 0x000E
    unit_of_measurement: "W"
    register_type: read
    value_type: U_WORD
    accuracy_decimals: 0

  - platform: modbus_controller
    modbus_controller_id: heidelberg_wallbox_id01  
    id: kwh_total_energie
    name: "KWH Total Energie"
    address: 0x0011
    unit_of_measurement: "kWh"
    register_type: read
    value_type: U_DWORD
    accuracy_decimals: 3
    filters:
      - multiply: 0.001

  - platform: modbus_controller
    modbus_controller_id: heidelberg_wallbox_id01  
    id: remote_lock
    name: "remote_lock"
    address: 0x0103
    register_type: holding
    value_type: U_WORD
    skip_updates: 0

  - platform: modbus_controller
    modbus_controller_id: heidelberg_wallbox_id01  
    id: max_current
    name: "max current"
    address: 0x0105
    unit_of_measurement: "A"
    register_type: holding
    value_type: U_WORD
    skip_updates: 0
    accuracy_decimals: 1
    filters:
      - multiply: 0.1
  

  - platform: homeassistant
    entity_id: input_number.wb_max_current #Slider from HASS, create as Helper
    id: wb_max_current
    internal: true
    on_value:
      then:
        - lambda: |-
            uint16_t payload = id(wb_max_current).state * 10;
            ESP_LOGI("main", "set max current %d", payload);
            // Create a modbus command item with the max current value as the payload
            esphome::modbus_controller::ModbusCommandItem set_payload_command = esphome::modbus_controller::ModbusCommandItem::create_write_single_command(heidelberg_wallbox_id01, 0x0105, payload);
            // Submit the command to the send queue
            heidelberg_wallbox_id01->queue_command(set_payload_command);



text_sensor:
  - platform: modbus_controller
    modbus_controller_id: heidelberg_wallbox_id01  
    id: ladezustand
    name: "ladezustand"
    address: 0x0005
    bitmask: 0
    raw_encode: HEXBYTES
    register_type: read
    lambda: |-
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      switch (value) {   
        case 2: return std::string("nein");
        case 3: return std::string("ja");
        case 4: return std::string("nein");
        case 5: return std::string("ja");
        case 6: return std::string("nein");
        case 7: return std::string("ja");
        case 8: return std::string("reduziert");
        case 9: return std::string("Fehler");
        case 10: return std::string("gesperrt");
        default: return std::string("Fehler");
      }
      return x;

#        case 0: return std::string("0verboten");

  - platform: modbus_controller
    modbus_controller_id: heidelberg_wallbox_id01  
    id: Fahrzeug
    name: "fahrzeug"
    address: 0x0005
    bitmask: 0
    raw_encode: HEXBYTES
    register_type: read
    lambda: |-
      uint16_t value = modbus_controller::word_from_hex_str(x, 0);
      switch (value) {   
        case 2: return std::string("nicht angesteckt");
        case 3: return std::string("nicht angesteckt");
        case 4: return std::string("angesteckt");
        case 5: return std::string("angesteckt");
        case 6: return std::string("angesteckt");
        case 7: return std::string("angesteckt");
        case 8: return std::string("-");
        case 9: return std::string("Fehler");
        case 10: return std::string("-");
        default: return std::string("Fehler");
      }
      return x;

#binary_sensor:
#  - platform: homeassistant
#    entity_id: input_boolean.wb_remote_lock
#    id: wb_remote_lock
#    internal: true
#    on_state:
#      then:
#        - lambda: |-
#            uint16_t payload = 1;
#            if ( id(wb_remote_lock).state == true ) {
#              payload = 0;
#            }
#            ESP_LOGI("main", "set remote lock %d", payload);
#            esphome::modbus_controller::ModbusCommandItem set_payload_command = esphome::modbus_controller::ModbusCommandItem::create_write_single_command(heidelberg_wallbox_id01, 0x0103, payload);
#            heidelberg_wallbox_id01->queue_command(set_payload_command);
3 „Gefällt mir“

Hi zusammen,

falls das noch für jemanden relevant ist, ich habe es heute zum Laufen bekommen.
Ich verwende einen JZK USB auf RS485 Konverter Adapter mit CH340 Chip
von Amazon (mein Setup ist ein unsupported supervised HA auf Raspberry OS) und habe diesen direkt per USB und mit zwei Drähten eines CAT-Kabels mit der Heidelberg Wallbox verbunden - ohne zusätzliche Widerstände.
Vorher hatte ich einen selbstgebastelten ESP mit wbec (mit D1 Mini) dazwischen geschaltet (wenn wbec, dann würde ich mir heute vermutlich einen fertigen kaufen). Daher weiß ich zumindest, dass meine Verkabelung zur Wallbox hin funktioniert.

Bei mir ist aktuell es ein simples Ein/Aus Szenario für den dynamischen Stromtarif, das ich über Automations in HA steuere und ansonsten optional ein paar Infos sehen will.

Ich habe alle Details hier aus dem Thread zusammen genommen, mit der Register-Doku von Amperfied und GitHub Copilot ein paar Runden gedreht und bin mit meinem Halbwissen zu HomeAssistant und Modbus zur folgenden extrem simplen Lösung gekommen:

modbus:
  - name: heidelberg_wallbox
    type: serial
    method: rtu
    port: /dev/serial/by-id/$put_your_own_port_id  # Path to your RS485 adapter
    baudrate: 19200
    stopbits: 1
    bytesize: 8
    parity: E
    delay: 0
    message_wait_milliseconds: 30
    timeout: 5
    sensors:
      # Read the raw charging status
      - name: Wallbox_Charging_Status_Raw
        address: 5  # Register for charging status
        input_type: input
        data_type: uint16

      # Read the power of L1, L2, and L3 combined (in watts)
      - name: Wallbox_L1_L2_L3_Power
        address: 14  # Register for L1 L2 L3 Power
        input_type: input
        unit_of_measurement: W
        data_type: uint16
        precision: 0  # No decimals

      # Read the total energy consumption (in kWh)
      - name: Wallbox_KWH_Total_Energie
        address: 17  # Register for total energy
        input_type: input
        unit_of_measurement: kWh
        data_type: uint32
        scale: 0.001  # Multiply by 0.001 to convert to kWh
        precision: 3  # 3 decimal places

    switches:
      # Optional switch to turn charging on/off
      - name: Wallbox_Enable_Charging
        address: 261  # Register for enabling/disabling charging
        write_type: holding
        command_on: 160  # Maximum current to enable charging (16 A)
        command_off: 0  # 0 A to disable charging

# Add a template sensor to map the raw charging status to human-readable values
template:
  - sensor:
      - name: Wallbox_Charging_Status
        state: >
          {% set status_map = {
            2: "Nicht verbunden, Laden verboten",
            3: "Nicht verbunden, Laden erlaubt",
            4: "Keine Ladeanfrage, Laden verboten",
            5: "Keine Ladeanfrage, Laden erlaubt",
            6: "Ladeanfrage, Laden verboten",
            7: "Ladeanfrage, Laden erlaubt",
            8: "-",
            9: "Fehler",
            10: "Wallbox gesperrt"
          } %}
          {{ status_map.get(states('sensor.wallbox_charging_status_raw') | int, "Fehler") }}

Viele Grüße
manuskript

1 „Gefällt mir“

Sehr cool, verstehe ich das richtig das du nur diesen Adapter verbaut hast und keinen zusätzlichen Esp? Könnte man es damit auch in Evcc integrieren und PV Überschuss realisieren oder brauch es zwingend einen esp dazu?

Hallo Mave84,
ich tippe auf ja - in HA hängt bei mir jetzt eine Kaskade an Helper-Variablen, Automations und Scripts.
Ich habe EVCC testweise via REST commands an meinen HA angeschlossen - und damit funktioniert das alles auch ohne zusätzlichen ESP - habe aber noch nicht genug Zeit investiert, um meine manuelle Ladesteuerung via Automations damit abzulösen. Musste in HA ein wenig die Logiken zwischen Automations, Scripts und Helpers ändern, um flexibler zu werden.
Die folgende Config funktioniert nicht vollständig für schreibende Befehle, aber als grobe Referenz:

chargers:
  - name: charger_1
    type: custom
    status:
      source: http
      uri: http://myobscurehostname:801337/api/states/sensor.wallbox_charging_status_raw
      method: GET
      jq: |
        if .state == "2" or .state == "3" then "A"        # Disconnected
        elif .state == "4" or .state == "5" then "B1"    # Connected, not charging
        elif .state == "6" or .state == "7" then "C"     # Charging
        elif .state == "9" then "F"                      # Fault
        elif .state == "10" then "A"                    # Wallbox locked (treated as disconnected)
        else "A"                                         # Default to disconnected
        end
      headers:
        - content-type: application/json
        - Authorization: Bearer xxx
    enabled:
      source: http
      uri: http://myobscurehostname:801337/api/states/input_boolean.charging_enabled
      method: GET
      jq: |
        if .state == "on" then true
        else false
        end
      headers:
        - content-type: application/json
        - Authorization: Bearer xxx
    enable:
      source: http
      uri: http://myobscurehostname:801337/api/services/input_boolean/turn_on
      method: POST
      body: '{"entity_id": "input_boolean.charging_enabled"}'
      headers:
        - content-type: application/json
        - Authorization: Bearer xxx
    maxcurrent:
      source: http
      uri: http://myobscurehostname:801337/api/services/input_number/set_value
      method: POST
      body: '{"entity_id": "input_number.charging_amps", "value": {{ .maxcurrent }}}' #Helper Variable in HA with possible values from 6-16
      headers:
        - content-type: application/json
        - Authorization: Bearer xxx

Vielen Dank für die Mühe und Rückmeldung! Ich habe mittlerweile das Heidelbridge Konzept umgesetzt und bin auch bis dato sehr zufrieden damit. Denke config wird sicher den einen oder andern helfen.

Moin manuskript,

deine Konfiguration ist “Goldwert”! Vielen Dank für deine Antwort. Bei mir soll es genauso funktionieren, ich will die Gesamt Energie sehen, die ich geladen habe. Sowie den flexiblen Stromtarif.
Allerdings bin ich einfach zu blöd, ich bekomme dieses Ding einfach nicht zum laufen.
Du hast oben den “port” definiert, ich hatte jetzt via SSH probiert mein USB Gerät zufinden. Werde aber aus dem Port nicht schlau! Wie definiere ich den richtig?

LG Vinzent

Kurzes Update:

hab den Punkt mit dem Pfad soweit gefunden. Aber weiterhin zickt die Wallbox. Ich bekomme die Register nicht ausgelesen.

Welche Dipschalter hast du bei dir gesetzt?

Ich glaube das nächste Thema wird: "Wieviel TNT brauche ich um eine Wallbox von der Wand zu holen? :smiley:

LG Vinzent

:crayon:by HarryP: Zusammenführung Doppelpost (bei Änderungen oder hinzufügen von Inhalten bitte die „Bearbeitungsfunktion“ anstatt „Antworten“ zu nutzen)

Hallo manuskript,
bist du schon weiter mit den sendenden Befehlen?
was verwendest du für enabled und enable?
Das hat die Energy control von Haus aus nicht oder?
Danke

Hallo Jochen,

ich bin gerade auch auf der Suche nach einer Möglichkeit, meine Heidelberg-Eco-Wallbox smart zu machen. Du hast vor einem Jahr von einem potentialfreien Shelly-Kontakt geschrieben, daher möchte ich sichergehen: würde dieser hier so funktionieren, wie Du es eingerichtet hast?

Link

Herzlichen Dank im Voraus!

Gruß, Gerrit[quote=“dago, post:2, topic:24212, full:true”]
Hallo Vinzent,
ich kann dir zwar nicht mit dem Modbus helfen, aber vielleicht hilft dir meine Lösung. Ich habe die Ladeleistung an der Heidelberger fest auf 4 KW eingestellt (passt so am Besten zu meiner Solaranlage von 10 KW). Dann hab ich statt der Brücke für den Schlüsselschalter einen potentialfreien Shelly-Kontakt dazwischen gehängt (Anleitung Wallbox Seite A.1.6 Abb 6). Nun schalte ich mit HA die Wallbox über das Shelly-Relais an und aus entsprechend meinem Stromüberschuss. Das funktioniert super, ist einfach und ob das Auto nun 2 oder 6 Stunden lädt ist mir egal.
Grüsse
Jochen
[/quote]