Heating integration Danfoss ECL310

Hi,

I do have an Danfoss ECL 310 controller which is using TCP/IP Modbus.
I do have version V1.30 (4572) with Application A247_1 V01.

I search a lot around but I could not find so far any customer component in order to control my heating system deliver sensor data and so on.

What I was able to perform myself was to read out some register from the modbus plattform which is ok but I would like to be able to change even some temp setting on that heating which is not working for me so far.

Does anyone have here some more knowledge in that.

I used the ECL Tool in order to connect and read out the register from the modbus which is in HA then always one register less than in the ECL tool, anyway I get the values in read.
But on some I’m not able to write some changes values back.


modbus.yaml
  - name: ecl310
    type: tcp
    host: xxx.xxx.xxx.xxx
    port: 502
    delay: 5
    timeout: 10
    climates:
      - name: ECL310_Soll_Temp
        slave: 254
        scan_interval: 600
        address: 11179
        input_type: holding
        # count: 1
        data_type: int16
        max_temp: 30
        min_temp: 10
        offset: 0
        precision: 1
        scale: 0.1
        target_temp_register: 11179
        temp_step: 0.5
        temperature_unit: C
      - name: ECL310_absenk_Temp
        slave: 254
        scan_interval: 600
        address: 11180
        input_type: holding
       # count: 1
        data_type: int16
        max_temp: 30
        min_temp: 10
        offset: 0
        precision: 1
        scale: 0.1
        target_temp_register: 11180
        temp_step: 0.5
        temperature_unit: C
    sensors:
      - name: ECL310_S1
        slave: 254
        scan_interval: 300
        address: 10200
        input_type: input
        unit_of_measurement: °C
        device_class: temperature
        # count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16
      - name: ECL310_S2
        slave: 254
        scan_interval: 300
        address: 10201
        input_type: input
        unit_of_measurement: °C
        device_class: temperature
        # count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16
      - name: ECL310_S3
        slave: 254
        scan_interval: 300
        address: 10202
        input_type: input
        unit_of_measurement: °C
        device_class: temperature
        # count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16
      - name: ECL310_S4
        slave: 254
        scan_interval: 300
        address: 10203
        input_type: input
        unit_of_measurement: °C
        device_class: temperature
        # count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16
      - name: ECL310_S5
        slave: 254
        scan_interval: 300
        address: 10204
        input_type: input
        unit_of_measurement: °C
        device_class: temperature
        # count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16
      - name: ECL310_S6
        slave: 254
        scan_interval: 300
        address: 10205
        input_type: input
        unit_of_measurement: °C
        device_class: temperature
        # count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16
      - name: ECL310_min_Outdoor_temp
        unit_of_measurement: °C
        address: 10499
        input_type: input
        slave: 254
        data_type: int16
        scale: 0.01
        offset: 0
        precision: 1
        scan_interval: 600
      - name: ECL310_max_Outdoor_temp
        unit_of_measurement: °C
        address: 10504
        input_type: input
        slave: 254
        data_type: int16
        scale: 0.01
        offset: 0
        precision: 1
        scan_interval: 600
      - name: ECL310_normal_wasser
        unit_of_measurement: °C
        address: 12189
        input_type: input
        data_type: int16
        slave: 254
        scale: 0.1
        offset: 0
        precision: 1
        scan_interval: 600
      - name: ECL310_absenkung_wasser
        unit_of_measurement: °C
        address: 12190
        input_type: input
        data_type: int16
        slave: 254
        scale: 0.1
        offset: 0
        precision: 1
        scan_interval: 600
      - name: ECL310_vorlauf_min_temp
        unit_of_measurement: °C
        address: 11176
        input_type: input
        data_type: int16
        slave: 254
        precision: 1
        scale: 1
        offset: 0
        scan_interval: 600
      - name: ECL310_vorlauf_max_temp
        unit_of_measurement: °C
        address: 11177
        scale: 1
        offset: 0
        precision: 1
        input_type: input
        data_type: int16
        slave: 254
        scan_interval: 600
      - name: ECL310_komfort_soll
        unit_of_measurement: °C
        address: 11179
        input_type: input
        data_type: int16
        slave: 254
        scale: 0.1
        offset: 0
        precision: 1
        scan_interval: 600
      - name: ECL310_absenkung_soll
        unit_of_measurement: °C
        address: 11180
        input_type: input
        data_type: int16
        slave: 254
        scale: 0.1
        offset: 0
        precision: 1
        scan_interval: 600
      - name: ECL310_frostschutz
        unit_of_measurement: °C
        address: 12092
        input_type: input
        data_type: int16
        slave: 254
        scan_interval: 600
      - name: ECL310_betriebsartww
        address: 4201
        input_type: input
        data_type: int16
        slave: 254
        scan_interval: 60
      - name: ECL310_betriebsartheizung
        address: 4200
        input_type: input
        data_type: int16
        slave: 254
        scan_interval: 60
      - name: Pumpe 1
        slave: 254
        address: 4005
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: Pumpe 2
        slave: 254
        address: 4006
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: Pumpe 3
        slave: 254
        address: 4007
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: m1_oeffnen
        slave: 254
        address: 3999
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: m1_schliessen
        slave: 254
        address: 4000
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: m2_oeffnen
        slave: 254
        address: 4001
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: m2_schliessen
        slave: 254
        address: 4002
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: manual_triac_m1
        slave: 254
        address: 4059
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: manual_triac_m2
        slave: 254
        address: 4060
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: manual_triac_m3
        slave: 254
        address: 4061
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: manual_pumpe1
        slave: 254
        address: 4065
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: manual_pumpe2
        slave: 254
        address: 4066
        input_type: input
        data_type: int16
        scan_interval: 60
      - name: manual_pumpe3
        slave: 254
        address: 4067
        input_type: input
        data_type: int16
        scan_interval: 60
sensor.yaml

  - platform: template
    sensors:
      ventilmodus_m1:
        friendly_name: "M1 Modus"
        value_template: >-
          {% if is_state('sensor.manual_triac_m1', '0') %}
            AUTO
          {% elif is_state('sensor.manual_triac_m1', '1') %}
            STOP
          {% elif is_state('sensor.manual_triac_m1', '2') %}
            SCHLIE?EN
          {% elif is_state('sensor.manual_triac_m1', '3') %}
            ÖFFNEN
          {% else %}
          {% endif %}
      ventilmodus_m2:
        friendly_name: "M2 Modus"
        value_template: >-
          {% if is_state('sensor.manual_triac_m2', '0') %}
            AUTO
          {% elif is_state('sensor.manual_triac_m2', '1') %}
            STOP
          {% elif is_state('sensor.manual_triac_m2', '2') %}
            SCHLIE?EN
          {% elif is_state('sensor.manual_triac_m2', '3') %}
            ÖFFNEN
          {% else %}
          {% endif %}
      pumpenmodus_p1:
        friendly_name: "P1 Modus"
        value_template: >-
          {% if is_state('sensor.manual_pumpe1', '0') %}
            AUTO
          {% elif is_state('sensor.manual_pumpe1', '1') %}
            OFF
          {% elif is_state('sensor.mmanual_pumpe1', '2') %}
            ON
          {% else %}
          {% endif %}
      pumpenmodus_p3:
        friendly_name: "P3 Modus"
        value_template: >-
          {% if is_state('sensor.manual_pumpe3', '0') %}
            AUTO
          {% elif is_state('sensor.manual_pumpe3', '1') %}
            OFF
          {% elif is_state('sensor.mmanual_pumpe3', '2') %}
            ON
          {% else %}
          {% endif %}
      bewegung_m1:
        friendly_name: "M1 Bewegungsmodus"
        value_template: >-
          {% if is_state('sensor.m1_oeffnen', '1') %}
            oeffnen
          {% elif is_state('sensor.m1_schliessen', '1') %}
            schließen
          {% else %}
            stop
          {% endif %}
      bewegung_m2:
        friendly_name: "M2 Bewegungsmodus"
        value_template: >-
          {% if is_state('sensor.m2_oeffnen', '1') %}
            Öffnen
          {% elif is_state('sensor.m2_schliessen', '1') %}
            schließen
          {% else %}
            stop
          {% endif %}
      p1:
        friendly_name: "Heizungspumpe"
        value_template: >-
          {% if is_state('sensor.pumpe_1', '1') %}
            Ein
          {% else %}
            Aus
          {% endif %}
      p3:
        friendly_name: "Zirkulationspumpe"
        value_template: >-
          {% if is_state('sensor.pumpe_3', '1') %}
            Ein
          {% else %}
            Aus
          {% endif %}
      m1:
        friendly_name: "Heizungsventil"
        value_template: >-
          {% if is_state('sensor.pumpe_4', '1') %}
            Auf
          {% else %}
            Zu
          {% endif %}
      m2:
        friendly_name: "Wasserventil"
        value_template: >-
          {% if is_state('sensor.pumpe_5', '1') %}
            Auf
          {% else %}
            Zu
          {% endif %}
      wasserbetriebsmodus:
        friendly_name: "WW Betriebsmodus"
        value_template: >-
          {% if is_state('sensor.ecl310_betriebsartww', '0') %}
            Manual
          {% elif is_state('sensor.ecl310_betriebsartww', '1') %}
            Schedule
          {% elif is_state('sensor.ecl310_betriebsartww', '2') %}
            Comfort
          {% elif is_state('sensor.ecl310_betriebsartww', '3') %}
            Constant setback
          {% elif is_state('sensor.ecl310_betriebsartww', '4') %}
            Constant comfort
          {% else %}
            failed
          {% endif %}
      heizungsbetriebsmodus:
        friendly_name: "Betriebsmodus Heizung"
        value_template: >-
          {% if is_state('sensor.ecl310_betriebsartheizung', '0') %}
            Manual
          {% elif is_state('sensor.ecl310_betriebsartheizung', '1') %}
            Schedule
          {% elif is_state('sensor.ecl310_betriebsartheizung', '2') %}
            Comfort
          {% elif is_state('sensor.ecl310_betriebsartheizung', '3') %}
            Constant setback
          {% elif is_state('sensor.ecl310_betriebsartheizung', '4') %}
            Constant comfort
          {% else %}
            failed
          {% endif %}

outcome of that in lovelace is:

4 Likes

I can’t get even one single value. I tried ECL Tool and it works. Can you help start with that thing?

How do you access your ecl310 controller with the ecl Tool? IP and port that one is the main access path.

Of course the modbus.yaml must be included in the configuration.yaml or you add that into there as section. Have you just copied die sensors and modbus.yaml file? What does the log say?

Actually I was able to connect and I can read some values - for example water temperature and other things from the sensors. However I am unable so far to read some values. Things that I can set in the ECL310 like heating curve or maximum heating temp - this I cannot read.

That are not part of the sensors as I do not need them… If you need to add then then use the ECL tools check out the register where the vaules are and add it simply into. I added some more useful for me. That is the Pump1 and Pump3 as well as the two valves… and convert the mode settings into a readable value.

Head curve is register 11175 in the ECL Tool e.g
The different temps for heating … register 11400 - 11405 ( Y1-Y6)

I tried to read 11175 in HA but it can’t read the value. In ECL Tool it works.

be aware that there is always a difference from ECL tool to HA modbus 11175 is ECL tools and 11174 is HA I do not know why maybe some counting bug… Check all other values that I have in the sensor.yaml file all are -1 to ECL tool. hth

thanks for sharing your configuration! I used your’s to generate mine. Here is what I’ve configured so far:

  - name: "Nahwärmestation"
    type: tcp
    host: 192.168.1.100
    port: 502
    timeout: 10
    climates:
      - name: Komforttemperatur
        address: 11179
        input_type: holding
        count: 1
        data_type: int16
        max_temp: 35
        min_temp: 15
        offset: 0
        precision: 1
        scale: 0.1
          #structure: "!i"
        target_temp_register: 11179
        temp_step: 1
        temperature_unit: C

    sensors:
      - name: Außentemperaturfühler (S1)
        address: 10200
        input_type: holding
        unit_of_measurement: °C
        device_class: temperature
        count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16

      - name: Vorlauftemperatur (S3)
        address: 10202
        input_type: holding
        unit_of_measurement: °C
        device_class: temperature
        count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16

      - name: Rücklauftemperatur (S5)
        address: 10204
        input_type: holding
        unit_of_measurement: °C
        device_class: temperature
        count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16

      - name: Warmwasser Speichertemperatur (S6)
        address: 10205
        input_type: holding
        unit_of_measurement: °C
        device_class: temperature
        count: 1
        scale: 0.01
        offset: 0
        precision: 1
        data_type: int16

With some changes to the modbus integration, I’m now able to change climate sensor values.

2 Likes

@acdcnow Can you share the code/config for the Lovelace Dashboard? Thx in advance

What you need first are from HACS Frontend UI Cards.

that are for this cases:
→ Plotly Graph Card
→ fold-entity-row
→ multiple-entity-row

and then just copy the below coding into new cards and if needed adjust you entities…

type: custom:plotly-graph
entities:
  - entity: sensor.ecl310_s1
    name: EingangTemp
  - entity: sensor.ecl310_min_outdoor_temp
    name: min Temp
  - entity: sensor.ecl310_max_outdoor_temp
    name: max Temp
hours_to_show: 168
type: custom:plotly-graph
entities:
  - entity: sensor.ecl310_s6
    name: WW Temp
  - entity: sensor.ecl310_s2
    name: WW RLTemp
  - entity: sensor.ecl310_s3
    name: Heizung VLTemp
hours_to_show: 168

type: entities
entities:
  - type: custom:fold-entity-row
    head:
      type: section
      label: Pumpen und Ventilstellung
    entities:
      - entity: sensor.heizungsbetriebsmodus
        type: custom:multiple-entity-row
        name: Fußbodentemperatur
        toggle: false
        state_header: Modus
        icon: mdi:home-thermometer
        secondary_info: last-changed
        entities:
          - entity: sensor.ecl310_s3
            name: Vorlauf
          - entity: sensor.ecl310_s5
            name: Rücklauf
      - entity: sensor.p1
        name: P1 Fußbodenheizungspumpe
        secondary_info: last-changed
        icon: mdi:pump
      - entity: sensor.pumpenmodus_p1
        secondary_info: last-changed
        icon: mdi:pump
      - entity: sensor.ventilmodus_m2
        secondary_info: last-changed
        icon: mdi:valve
      - entity: sensor.bewegung_m2
        secondary_info: last-changed
        name: M2 Fußbodenheizungsventil
        icon: mdi:valve

type: entities
entities:
  - type: custom:fold-entity-row
    head:
      type: section
      label: Pumpen und Ventilstellung
    entities:
      - entity: sensor.wasserbetriebsmodus
        type: custom:multiple-entity-row
        name: Warmwassertemperatur
        secondary_info: last-changed
        toggle: flase
        state_header: Modus
        icon: mdi:coolant-temperature
        entities:
          - entity: sensor.ecl310_s2
            name: Rücklauf
          - entity: sensor.ecl310_s4
            name: Speicher
      - entity: sensor.p3
        name: P3 Zirkulationspumpe
        secondary_info: last-changed
        icon: mdi:pump
      - entity: sensor.pumpenmodus_p3
        secondary_info: last-changed
        icon: mdi:pump
      - entity: sensor.ventilmodus_m1
        secondary_info: last-changed
        icon: mdi:valve
      - entity: sensor.bewegung_m1
        secondary_info: last-changed
        name: M1 Warmwasserventil
        icon: mdi:valve

type: entities
entities:
  - entity: sensor.ecl310_s6
    type: custom:multiple-entity-row
    name: Warmwasser
    secondary_info: last-changed
    state_header: Current
    icon: mdi:coolant-temperature
    entities:
      - entity: sensor.ecl310_absenkung_wasser
        name: Absenkung
      - entity: sensor.ecl310_normal_wasser
        name: Normal
  - entity: climate.fussbodenheizung_wohnzimmer
    type: custom:multiple-entity-row
    name: Heizung
    secondary_info: last-changed
    state_header: Modus
    entities:
      - entity: sensor.ecl310_absenkung_soll
        name: Absenkung
      - entity: sensor.ecl310_komfort_soll
        name: Normal
  - entity: sensor.ecl310_frostschutz
    name: Frostschutz
    icon: mdi:weather-night
  - entity: sensor.ecl310_s3
    type: custom:multiple-entity-row
    name: Fußboden Vorlauftemp
    state_header: Current
    secondary_info: last-changed
    entities:
      - entity: sensor.ecl310_vorlauf_min_temp
        name: min
      - entity: sensor.ecl310_vorlauf_max_temp
        name: max

type: entities
entities:
  - entity: climate.ecl310_soll_temp
    name: Komforttemperatur
  - entity: climate.ecl310_absenk_temp
    name: Absenktemperatur
  - entity: sensor.ecl310_s1
    type: custom:multiple-entity-row
    name: Außentemperatur Eingang
    icon: mdi:home-thermometer-outline
    secondary_info: last-changed
    state_header: Current
    entities:
      - entity: sensor.ecl310_min_outdoor_temp
        name: min.
      - entity: sensor.ecl310_max_outdoor_temp
        name: max.
show_header_toggle: false

1 Like

Hey all, i went through above posts but did not manage at all to connect to my ECL.
The ECL is connected via Ethernet and can be accessed via the ECL web portal, no direct cable link towards my raspy with homeassistant.
I tried to add above good in either modbus.yaml (doubt this is correct due to no direct cable connection) and into the config.yaml - what just creates error.

So do i need to first install a direct link from raspy to ECL?
Can’t this be done via the Webinterface?

Many thanks already!

For sure you need an own IP addres on the ECL, check the dhcp or static once in order to access the modbus.
If you have an IP addres then you need to use it in the config in order to access the registers.

In case you run HA 2023.10.x then you need to remove the counter the config …

  • name: ecl310
    type: tcp
    host: 10.0.0.20 –>> you need to enter your own one here.
    port: 502
    delay: 5
    timeout: 10
    climates:
    - name: ECL310_Soll_Temp
    slave: 254
    scan_interval: 600
    address: 11179
    input_type: holding
    # count: 1
    data_type: int16
    max_temp: 30
    min_temp: 10