Etrel Inch Modbus TCP communication

Hey @ThomasMidgley. Great job!
How does this convert to 2kW?

value:
  - 16656
  - 0

I can’t seem to work it out from the floattohex link you provided.

@gisa, hi,

When you save a value to the lovelance card in the form of “value: [x,y]” it is saved in a different form:
value:
- a
- b

I never tried to figure out why and how this is working.

You don’t set the kW as such in charger, but the maximum aperage:
since I have only a 1phase 230V power supply: 2kW / 230V =~ 8A
8A = 0x41000000 = [0x4100, 0x0000]
in a lovelance card it is stored as:

value:
  - 16656
  - 0
Summary

image

other example:
32A = 0x42000000 = [0x4200, 0x0000]
or

value:
- 16640
- 0

in automations the original values are kept:

###################################
#                                 #
# Instellen laadsnelheid laadpaal #
#                                 #
###################################

# Floating Point to Hex Converter
# https://gregstoll.com/~gregstoll/floattohex/

# 23h00 - 07h30: 32A
# 07h30 - 13h00: 0A
# 13h00 - 17h00: 32A
# 17h00 - 22h00: 0A
# 21h15 - 23h00: 8A

- alias: "Laadsnelheid 00h00"
  trigger:
  - platform: time
    at: "23:00:00" 
  condition:
    - condition: state
      entity_id: input_boolean.auto_charge
      state: "on"
  action:
  - service: modbus.write_register
    data:
      address: 8
      slave: 255
      value: [0x4200, 0x0000] # 32A
      hub: etrel_inch

- alias: "Laadsnelheid 07h30"
  trigger:
  - platform: time
    at: "07:30:00" 
  condition:
    - condition: state
      entity_id: input_boolean.auto_charge
      state: "on"
  action:
  - service: modbus.write_register
    data:
      address: 8
      slave: 255
      value: [0x0000, 0x0000] # 0A
      hub: etrel_inch

- alias: "Laadsnelheid 13h00"
  trigger:
  - platform: time
    at: "13:00:00" 
  condition:
    - condition: state
      entity_id: input_boolean.auto_charge
      state: "on"
  action:
  - service: modbus.write_register
    data:
      address: 8
      slave: 255
      value: [0x4200, 0x0000] # 32A
      hub: etrel_inch

- alias: "Laadsnelheid 17h00"
  trigger:
  - platform: time
    at: "17:00:00" 
  condition:
    - condition: state
      entity_id: input_boolean.auto_charge
      state: "on"
  action:
  - service: modbus.write_register
    data:
      address: 8
      slave: 255
      value: [0x0000, 0x0000] # 0A
      hub: etrel_inch

- alias: "Laadsnelheid 21h15"
  trigger:
  - platform: time
    at: "21:15:00" 
  condition:
    - condition: state
      entity_id: input_boolean.auto_charge
      state: "on"
  action:
  - service: modbus.write_register
    data:
      address: 8
      slave: 255
      value: [0x4100, 0x0000] # 8A
      hub: etrel_inch
  - delay:
      minutes: 1
  - service: automation.trigger
    data:
      skip_condition: true
    target:
      entity_id: automation.notificatie_vermogen_laadpaal

hope this helps.

Great info @ThomasMidgley. It looks like it got things working!
The ultimate goal would be to use any excess solar pv production, but let’s see how this goes first :wink:

Hi Thomas, I like your code, I have the same ev charger. I would like to max the phase instead of max power. How did you know which variable is which in the modbus.

I would like to make a dynamic load balancing based on current available A in the house at that moment of charging.

Another question, I have two Etrel chargers, how can I control them both ? Add another modbus section ? but how to deal with the names and ids? I tried, but it gives errors.

Hi, in the first post there’s a link to the wiki of Etrel, containing an overview of the registers. Here’s a direct link to the excel

https://etrelchargingsolutions.atlassian.net/wiki/download/attachments/820707329/Etrel%20INCH%20(Duo)%20SmartHome%20Modbus%20TCPRegisters.xlsx?api=v2

I don’t understand what you mean with “max the phase”. Nevertheless, I’m afraid HA will not be fast enough to react to momentarily surges in power use. Your fuse will pop faster than HA will update the set point for the maximum current.

I use an Etrel load guard for this purpose:
https://etrel.com/charging-solutions/load-guard/

according to the documentation you should setup multiple connections
https://www.home-assistant.io/integrations/modbus/#configuring-multiple-connections

# Example yaml: multiple tcp connections
modbus:
  - name: modbus_hub
    type: tcp
    host: IP_ADDRESS_1
    port: 2020

  - name: modbus_hub2
    type: tcp
    host: IP_ADDRESS_2
    port: 502

make sure they don’t use the same ports.

Hi Thomas, thanks for the info, yes I have also load guard installed. Dont know if there are settings for that as well, I have also heatpump and batteries who are heavy consumers. Would love to use the load guard for all these devices. I kind of want to build that in HA.

Not sure how I can change the port on the etrel, since I don’t have login / pwd…

I found a way in, but in the web interface of etrel you cannot change the port 501 to something else. Is there another way ?

The default login and password can be found on the inside of the maintenance door of the charger.

the charger uses port 502, where as the load balancer uses port 503. see the excel of Etrel

It might be easier if you use evcc.io as a controller for your Etrel box (setting all the price rules and plans for charging there) and then integrate evcc into HA.

Dear,
Could you share the modbus map table for the Etrel Inch, I can’t seem to find it anywhere…

Sorry, I was just a bit too fast in replying (although I already searched), I found the tabel.
I found it here

For future reference and for anyone who may find it usefull, this is how I got it implemented:
In configuration.yaml:

modbus: !include_dir_merge_list modbus/

In modbus/EVSE.yaml:

- name: modbus_etrel
  type: tcp
  host: 192.168.1.145
  port: 502
  delay: 2
  timeout: 5
  sensors:
    - name: Etrel_Connnector_status
      unique_id: "Etrel_Connnector_status"
      scan_interval: 10
      address: 0
      input_type: input
      data_type: int16
    - name: Etrel_Measured_vehicle_number_of_phases
      unique_id: "Etrel_Measured_vehicle_number_of_phases"
      scan_interval: 10
      address: 1
      input_type: input
      data_type: int16
    - name: Etrel_EV_max_phase_current
      unique_id: "Etrel_EV_max_phase_current"
      scan_interval: 10
      address: 2
      input_type: input
      data_type: float32
    - name: Etrel_Target_current_from_power_mgm_or_modbus
      unique_id: "Etrel_Target_current_from_power_mgm_or_modbus"
      scan_interval: 10
      address: 4
      input_type: input
      data_type: float32
    - name: Etrel_Frequency
      unique_id: "Etrel_Frequency"
      scan_interval: 10
      address: 6
      input_type: input
      data_type: float32
    - name: Etrel_L-N_voltage_(L1)
      unique_id: "Etrel_L-N_voltage_(L1)"
      scan_interval: 10
      address: 8
      input_type: input
      data_type: float32
    - name: Etrel_L-N_voltage_(L2)
      unique_id: "Etrel_L-N_voltage_(L2)"
      scan_interval: 10
      address: 10
      input_type: input
      data_type: float32
    - name: Etrel_L-N_voltage_(L3)
      unique_id: "Etrel_L-N_voltage_(L3)"
      scan_interval: 10
      address: 12
      input_type: input
      data_type: float32
    - name: Etrel_Curent_(L1)
      unique_id: "Etrel_Curent_(L1)"
      scan_interval: 10
      address: 14
      input_type: input
      data_type: float32
    - name: Etrel_Curent_(L2)
      unique_id: "Etrel_Curent_(L2)"
      scan_interval: 10
      address: 16
      input_type: input
      data_type: float32
    - name: Etrel_Curent_(L3)
      unique_id: "Etrel_Curent_(L3)"
      scan_interval: 10
      address: 18
      input_type: input
      data_type: float32
    - name: Etrel_Active_power_(L1)
      unique_id: "Etrel_Active_power_(L1)"
      scan_interval: 10
      address: 20
      input_type: input
      data_type: float32
    - name: Etrel_Active_power_(L2)
      unique_id: "Etrel_Active_power_(L2)"
      scan_interval: 10
      address: 22
      input_type: input
      data_type: float32
    - name: Etrel_Active_power_(L3)
      unique_id: "Etrel_Active_power_(L3)"
      scan_interval: 10
      address: 24
      input_type: input
      data_type: float32
    - name: Etrel_Active_power_(total)
      unique_id: "Etrel_Active_power_(total)"
      scan_interval: 10
      address: 26
      input_type: input
      data_type: float32
    - name: Etrel_Power_factor
      unique_id: "Etrel_Power_factor"
      scan_interval: 10
      address: 28
      input_type: input
      data_type: float32
    - name: Etrel_Total_imported_active_energy_in_running_session
      unique_id: "Etrel_Total_imported_active_energy_in_running_session"
      scan_interval: 10
      address: 30
      input_type: input
      data_type: float32
    - name: Etrel_Running_session_duration
      unique_id: "Etrel_Running_session_duration"
      scan_interval: 10
      address: 32
      input_type: input
      data_type: int64
    - name: Etrel_Running_session_departure_time
      unique_id: "Etrel_Running_session_departure_time"
      scan_interval: 10
      address: 36
      input_type: input
      data_type: int64
    - name: Etrel_Running_session_ID
      unique_id: "Etrel_Running_session_ID"
      scan_interval: 10
      address: 40
      input_type: input
      data_type: int64
    - name: Etrel_EV_max_power
      unique_id: "Etrel_EV_max_power"
      scan_interval: 10
      address: 44
      input_type: input
      data_type: float32
    - name: Etrel_EV_planned_energy
      unique_id: "Etrel_EV_planned_energy"
      scan_interval: 10
      address: 46
      input_type: input
      data_type: float32
    - name: Etrel_Connector_type
      unique_id: "Etrel_Connector_type"
      scan_interval: 10
      address: 1022
      input_type: input
      data_type: int16
    - name: Etrel_Number_phases
      unique_id: "Etrel_Number_phases"
      scan_interval: 10
      address: 1023
      input_type: input
      data_type: int16
    - name: Etrel_L1_connected_to_phase
      unique_id: "Etrel_L1_connected_to_phase"
      scan_interval: 10
      address: 1024
      input_type: input
      data_type: int16
    - name: Etrel_L2_connected_to_phase
      unique_id: "Etrel_L2_connected_to_phase"
      scan_interval: 10
      address: 1025
      input_type: input
      data_type: int16
    - name: Etrel_L3_connected_to_phase
      unique_id: "Etrel_L3_connected_to_phase"
      scan_interval: 10
      address: 1026
      input_type: input
      data_type: int16
    - name: Etrel_Custom_max_current
      unique_id: "Etrel_Custom_max_current"
      scan_interval: 10
      address: 1028
      input_type: input
      data_type: float32
    - name: Etrel__Set_current_setpoint
      unique_id: "Etrel__Set_current_setpoint"
      scan_interval: 10
      address: 8
      input_type: holding
      data_type: float32
      unit_of_measurement: 'A'
      scale: 1
      precision: 1
  switches:
    - name: Etrel__Stop_charging
      unique_id: "Etrel__Stop_charging"
      scan_interval: 10
      address: 1
      write_type: holding
      command_on: 1
      command_off: 0

I don’t really use the switch.

I have an automation that monitors the ‘Etrel_Connnector_status’ and starts half a minute charge when connected, then monitors the grid interaction to adjust according to presets. For me it is keep the grid interaction close to zero if possible (adjusting the set current), and draw a maximum of 500W from the grid. So for now, basically only charge when the sun is shining.

I also have a pyscript to convert the decimal value of the setpoint to 2 registers and sends this to the charger:

import struct

@service
def send_current_setpoint(value=10.0):


    # Float naar big-endian Float32 bytes
    float_bytes = struct.pack(">f", value)

    # Verdeel in 2 registers (16-bit woorden)
    word1 = int.from_bytes(float_bytes[0:2], byteorder="big")
    word2 = int.from_bytes(float_bytes[2:4], byteorder="big")

    log.info(f"Setpoint {value} A wordt verstuurd als [{word1}, {word2}]")

    # Modbus-register schrijven
    service.call(
        "modbus", "write_register",
        hub="modbus_etrel",      # Naam van je Modbus hub
        unit=1,                  # Modbus unit ID
        address=8,               # Adres voor stroominstelling
        value=[word1, word2]     # Float32 in 2 woorden
    )

Sorry for the dutch language, I asked chatGPT for help in dutch.

hi, how to use an automation to run this pyscript? I have pyscript installed on my instance.

edit: found it, forgot to add the “@service