Swegon Casa Ventilation Unit with ESPHome

I’ve recently added my Swegon Casa W3 ventilation unit with heat recovery into Home Assistant using ESPHome and the Modbus integration. I believe the Modbus interface is the same for most Swegon Casa products.

I bought the Swegon Modbus module for my unit and connected that to my ESP8266 with a cheap RS485 module from Aliexpress. Here’s my ESPHome configuration file in case someone’s interested.

# Read data over ModBus from Swegon Casa Ventilation / Heat Recovery device
#
# Not all fields are implemented by all machines.
#
# See reference:
# https://www.swegon.com/siteassets/_product-documents/home-ventilation/control-equipment/_fi/smartmodbusregisterfull.pdf
# https://serviceportal.swegon.com/fi/docs/MB_REG_FI

esphome:
  name: swegon-ac-esp8266

esp8266:
  board: nodemcuv2

substitutions:
  device_name: Swegon W3

# Enable Home Assistant API
api:

ota:

wifi:
  ssid: !secret wifi_ssid 
  password: !secret wifi_password
  domain: !secret local_domain
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Swegon Fallback Hotspot"
    password: "password"

# Logging is disabled
logger:
  level: ERROR
  #level: DEBUG
  baud_rate: 0

uart:
  id: mod_bus
  tx_pin: D6
  rx_pin: D5
  baud_rate: 38400
  stop_bits: 1
  
modbus:
  id: modbus1
  
modbus_controller:
  - id: swegon
    ## the Modbus device address
    address: 0x10
    modbus_id: modbus1
    setup_priority: -10


sensor:

# ENVIRONMENTAL PARAMETERS, 6200-6299

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: fresh_air_temperature
    name: "${device_name} Fresh Air Temperature"
    address: 6200 # 6201-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: supply_air_before_reheater_temperature
    name: "${device_name} Supply Air Before Reheater Temperature"
    address: 6201 # 6202-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: supply_air_temperature
    name: "${device_name} Supply Air Temperature"
    address: 6202 # 6203-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: extract_air_temperature
    name: "${device_name} Extract Air Temperature"
    address: 6203 # 6204-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: waste_air_temperature
    name: "${device_name} Waste Air Temperature"
    address: 6204 # 6205-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: room_air_temperature
    name: "${device_name} Room Air Temperature"
    address: 6205 # 6206-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: user_panel_1_temperature
    name: "${device_name} User Panel Temperature"
    address: 6206 # 6207-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: user_panel_2_temperature
    name: "${device_name} User Panel 2 Temperature"
    address: 6207 # 6208-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: water_radiator_temperature
    name: "${device_name} Water Radiator Temperature"
    address: 6208 # 6209-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: preheater_temperature
    name: "${device_name} Pre-heater Temperature"
    address: 6209 # 6210-1
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: external_fresh_air_temperature
    name: "${device_name} External Fresh Air Temperature"
    address: 6210 
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "°C"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: co2_unfiltered
    name: "${device_name} CO2 Unfiltered"
    address: 6211 
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "ppm"

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: co2_filtered
    name: "${device_name} CO2 Filtered"
    address: 6212 
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "ppm"

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: relative_humidity
    name: "${device_name} Relative Humidity"
    address: 6213 
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "%"

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: absolute_humidity
    name: "${device_name} Absolute Humidity"
    address: 6214
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "g/m³"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: absolute_humidity_setpoint
    name: "${device_name} Absolute Humidity Setpoint"
    address: 6215
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "g/m³"
    accuracy_decimals: 1
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: voc
    name: "${device_name} VOC"
    address: 6216 
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "ppm"

# UNIT STATE 6300-6399

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: supply_fan_control
    name: "${device_name} Supply Fan Control"
    address: 6302
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "%"

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: exhaust_fan_control
    name: "${device_name} Exhaust Fan Control"
    address: 6303
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "%"

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: supply_fan_rpm
    name: "${device_name} Supply Fan RPM"
    address: 6304
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "R/min"
    filters:
      - multiply: 10

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: exhaust_fan_rpm
    name: "${device_name} Exhaust Fan RPM"
    address: 6305
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "R/min"
    filters:
      - multiply: 10

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: boost_time_left
    name: "${device_name} Boost Time Left"
    address: 6307
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "min"

  - platform: modbus_controller
    modbus_controller_id: swegon
    id: hours_to_service
    name: "${device_name} Hours to Next Service"
    address: 6342
    register_type: read
    value_type: U_WORD
    unit_of_measurement: "h"

binary_sensor:
- platform: modbus_controller
  modbus_controller_id: swegon
  id: travelling_function_active
  name: "${device_name} Travelling Function Active"
  register_type: read
  address: 6306
  bitmask: 0x01 #(bit 1)

- platform: modbus_controller
  modbus_controller_id: swegon
  id: defrost_active
  name: "${device_name} Defrost Active"
  register_type: read
  address: 6327
  lambda: !lambda |-
    uint16_t defrost = (data[item->offset] << 8) + data[item->offset+1];
    if (defrost > 0) {
      return true;
    } else {
      return false;
    }

- platform: modbus_controller
  modbus_controller_id: swegon
  id: preheater_active
  name: "${device_name} Preheater Active"
  register_type: read
  address: 6332
  bitmask: 0x01 #(bit 1)

- platform: modbus_controller
  modbus_controller_id: swegon
  id: fireplace_function_active
  name: "${device_name} Fireplace Function Active"
  register_type: read
  address: 6334
  bitmask: 0x01 #(bit 1)

- platform: modbus_controller
  modbus_controller_id: swegon
  id: heat_exchanger_bypass
  name: "${device_name} Heat Exchanger Bypass"
  register_type: read
  address: 6340
  bitmask: 0x01 #(bit 1)

      
text_sensor:
  - platform: modbus_controller
    modbus_controller_id: swegon
    name: "${device_name} Unit State"
    id: unit_state
    register_type: read
    address: 6300
    lambda: !lambda |-
      uint16_t int_mode = (data[item->offset] << 8) + data[item->offset+1];
      ESP_LOGD("main","Parsed unit state int : %d", int_mode);
      std::string mode_str;
      switch (int_mode) {
        case 0:  mode_str = "External stop"; break;
        case 1:  mode_str = "User stopped"; break;
        case 2:  mode_str = "Starting"; break;
        case 3:  mode_str = "Normal"; break;
        case 4:  mode_str = "Commissioning"; break;
        default: mode_str = "Unknown"; break;
      }
      return mode_str;
    
  - platform: modbus_controller
    modbus_controller_id: swegon
    name: "${device_name} Ventilation Speed State"
    id: ventilation_speed_state
    register_type: read
    address: 6301
    lambda: !lambda |-
      uint16_t int_mode = (data[item->offset] << 8) + data[item->offset+1];
      ESP_LOGD("main","Parsed ventilation speed state int : %d", int_mode);
      std::string mode_str;
      switch (int_mode) {
        case 0:  mode_str = "Stopped"; break;
        case 1:  mode_str = "Away"; break;
        case 2:  mode_str = "Home"; break;
        case 3:  mode_str = "Boost"; break;
        case 4:  mode_str = "Cooling"; break;
        default: mode_str = "Unknown"; break;
      }
      return mode_str;

  - platform: modbus_controller
    modbus_controller_id: swegon
    name: "${device_name} Firmware Version"
    id: device_firmware_version
    register_type: read
    address: 6000
    response_size: 6
    skip_updates: 60
    lambda: !lambda |-
      uint16_t fw_major = (data[item->offset] << 8) + data[item->offset+1];
      uint16_t fw_minor = (data[item->offset+2] << 8) + data[item->offset+3];
      uint16_t fw_build = (data[item->offset+4] << 8) + data[item->offset+5];
      return (esphome::to_string(fw_major) + "." + esphome::to_string(fw_minor) + "." + esphome::to_string(fw_build));
      
  - platform: modbus_controller
    modbus_controller_id: swegon
    name: "${device_name} Modbus GW Firmware Version"
    id: modbus_gw_firmware_version
    register_type: read
    address: 6005
    response_size: 4
    skip_updates: 60
    lambda: !lambda |-
      uint16_t fw_major = (data[item->offset] << 8) + data[item->offset+1];
      uint16_t fw_minor = (data[item->offset+2] << 8) + data[item->offset+3];
      return (esphome::to_string(fw_major) + "." + esphome::to_string(fw_minor));
      
  - platform: modbus_controller
    modbus_controller_id: swegon
    name: "${device_name} Model Name"
    id: model_name
    register_type: read
    address: 6007
    response_size: 16
    skip_updates: 60

    
switch:
- platform: modbus_controller
  modbus_controller_id: swegon
  name: "${device_name} Auto RH Control"
  id: auto_rh_control
  register_type: holding
  address: 5009
  bitmask: 1

- platform: modbus_controller
  modbus_controller_id: swegon
  name: "${device_name} Service Reminder"
  id: service_reminder
  register_type: holding
  address: 5140
  bitmask: 1

- platform: modbus_controller
  modbus_controller_id: swegon
  name: "${device_name} Fireplace Function"
  id: fireplace_function
  register_type: holding
  address: 5001
  bitmask: 1

select:
- platform: modbus_controller
  modbus_controller_id: swegon
  name: "${device_name} Fan Speed Mode"
  id: fan_speed_mode
#  register_type: holding
  address: 5000
  optionsmap:
      "Away": 1
      "Home": 2
      "Boost": 3

number:
  - platform: modbus_controller
    modbus_controller_id: swegon
    name: "${device_name} Service Reminder Interval"
    id: service_reminder_interval
    register_type: holding
    address: 5141
    min_value: 1
    max_value: 12
    step: 1
    mode: slider

  - platform: modbus_controller
    modbus_controller_id: swegon
    name: "${device_name} Temperature Setpoint"
    id: temperature_setpoint
    register_type: holding
    address: 5100
    min_value: 16
    max_value: 23
    step: 1
    mode: slider

output:
  - platform: modbus_controller
    modbus_controller_id: swegon
    id: reset_service_reminder
    write_lambda: |-
      ESP_LOGD("main","Modbus Output reset_service_reminder, value = %f",x);
      if (x) {
        return 0;
      } else {
        return 1;
      }
    address: 5140
    register_type: holding
    value_type: U_WORD
    
button:
  - platform: output
    name: "${device_name} Reset Service Reminder"
    output: reset_service_reminder
    duration: 1000ms

4 Likes

Thanks a lot for this.
We have installed a Swegon Casa W5, so this will help a lot with the modbus implementation.

I’m fairly new to the whole modbus configuration and especially the hardware part of it.
Do you think you can point me to some guide on how to get RS485 module talking to the ESP8266.
Or is it fine to use a USB one for this?

Hi,

I’m actually using ESP32 right now, but ESP8266 should work equally well, I did use that before. Just get that cheap RS485 module from AliExpress or other source. It has 4 wires: one to 5V (or 3.3V), one to ground and then in my above code one to D5 and D6. Then connect two Modbus wires to the Modbus GW of your Swegon Casa.

I have also read the values from the GW using a USB interface, but that was without ESPhome of course.

@trsqr Thank you very much.
Just got the ESP8266 cards and RS485 cards, just ordered the Swegon Modbus connection module, and with your instructions I actually think this is doable :slight_smile:.

I’ll report back with a status report once I’m starting.

Hi,

Did you pursue the modbus hook up?

I am thinking of doing the same and have a similar Swegon unit. I am wondering if I should connect directly to the modbus interface on the hvac or connect to the “smart modbus extension module”. I think the later however, also a novice, so would be grateful if you have done a successful connection and could share how you went about it.

/Rasmus

I’m using mine with the Swegon SMBG Modbus gateway, although I suspect that the communication is based on Modbus anyway even without the gateway…

I’m actually moving out of the house and can sell my Modbus GW for 50 eur plus shipping costs (something like 10 eur in EU), if anyone is interested.

Hello Everyone.

I have now been stuck for some days trying to get the script work against my own module to the modbus gateway, but i can’t get it work, i have tried to change output from the nodemcuv3 from D6, D5 to D8, D7. but nothing happens.

i have added a picture of my setup.

My ventilation equipment is a Swegon Premium 8bb and have a different modbus register as i also have added below here:

… now to my code.

esphome:
  name: nodemcu

esp8266:
  board: nodemcuv2

# # Enable logging
# logger:

# Enable Home Assistant API
api:
  encryption:

ota:

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

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

# Logging is disabled
logger:
  level: ERROR
  # level: DEBUG
  baud_rate: 0

modbus:
  id: modbus1

uart:
  id: mod_bus
  tx_pin: D8
  rx_pin: D7
  baud_rate: 38400
  stop_bits: 1
  parity: none
  data_bits: 8
    
modbus_controller:
  - id: swegon
    ## the Modbus device address
    address: 0x10
    modbus_id: modbus1
    setup_priority: -10

sensor:

# ENVIRONMENTAL PARAMETERS, 6200-6299
 

select:
- platform: modbus_controller
  modbus_controller_id: swegon
  name: "${device_name} Fan Speed Mode"
  id: fan_speed_mode
  #register_type:
  address: 5001
  optionsmap:
      "Away": 1
      "Home": 2
      "Boost": 3

hope that any one can help me here.
really need to know what im doing wrong.

/Mike

Did you get this work ?
i just posted below, my setup. but cant get it work.

I’ve just managed to get it working with my Swegon Casa W4 and esp32 (firebeetle32) thanks to this post.

@BoysenMike, do you still have trouble connecting to yours?

I’m also up and running with ESP32 (Lolin lite) and RS-485 TTL module. I have a newly installed Swegon Casa Smart R5 unit.

Currently in dialogue with Swegon support since the modbus register they have published on their website is not inline with what data I get from certain addresses. E.g. for address 6213 I get relative humidity is seems like where according to the documentation it should be the value for CO2. Anyone else having challenges with getting the right data from the addresses?

I will publish a complete guide on Github when everything is finalised and working.

Advice to not forget to connect the RE and DE pin on the RS-485 TTL module to a digital pin on the microcontroller and to define this in the config like below flow-control-pin

modbus:
  id: modbus1
  flow_control_pin: GPIO4

Thanks @trsqr for your initial post, helped me to get going!

1 Like

I have tried the same thing, but I get nothing going out on the modbus AB outputs from the Swegon R7 unit. @ola do you use the specific modbus adapter from Swegon or do you just connect directly to the modbus output? I am doing the latter as I’ve read somewhere else that the specific adapter does not convert anything so you can connect directly. But maybe I am misleaded…

I first tried with SEC connection, but then I also tried using the SEM module connected to the SEC/SEM port. But it was the same thing.

I’ve also connected the modbus output to a Moxa TCC-100 unit just to see if it would indicate any traffic by its led, but nothing. The plan was to connect it to an RS-485 to UDP/TCP wifi converter (USR-W610).

Maybe the main board of the unit is broken and needs to be replaced, but I hate to do that if it turns out to be a different problem…

Hi, is it possible to change/modify W3 ‘defrost’ settings’ with this solution?

I have a Swegon Gold, would anyone know if it would be possible to connect this to Home Assistant? I understand the need for swegon modbus

Hi @trsqr ,

I know this post is from quite a while ago - but if you still happen to have the Modbus GW available, I’d be interested in buying it. Swegon W4 Smart here, somewhat new to home assistant - looking currently into how to make the ventilation machine even smarter. :slight_smile:

Ola,

Did you go trough Swegon GW, or directly to the board?

Chris

Hi, I’m also interested in connecting HASS to a Swegon Casa via Modbus, and I would like to confirm if anyone here managed to do that successfully by connecting directly to the connector in the unit, without using any intermediary SEM/SEC gateway?

Judging by what I found in Swegon-aggregat i Home Assistant - Klimakontroll - Hjemmeautomasjon (Norwegian forum) it looks like the Swegon gateways are just a plain (and overpriced) adapter, and you can get by without them as the unit itself speaks Modbus. But it would be nice if anybody here could confirm if they managed to connect directly to the unit.

1 Like

I had the Swegon Casa W3 with the separate color display controller (that came as standard). The display was connected with an RJ12 connector to the main unit in the same way as the modbus GW was. I’m fairly sure Modbus is being used between the display and the unit as well and the Swegon Modbus Gateway indeed is an expensive adapter. It has some capabilities though as you can set the different Modbus parameters as well baud rate etc… on the gateway with dip swiches.

1 Like

I might be wrong but I think it’s an RJ9 and not a RJ12 connector.