Brink Flair 325 Heat recovery unit ESPhome modbus integration (~$5)

Is there someone who have also an option to manage the zone (co2) valve for the brink flair?

Hi,

Can I ask you a question? Which exact hardware do i need to buy to have it working with your solution?

Hi, I’m a beginner with Home Assistant and would like to add my Flair 200 to HA. I have an ESP32S3 Lilygo T7 and run HA on a Pi5 with ESPHome Builder installed. So far, everything is going well, but when I try to flash the ESP via ESPHome, I get the following error message:

In file included from /data/cache/platformio/packages/framework-arduinoespressif32/cores/esp32/Arduino.h:202,
from /data/cache/platformio/packages/framework-arduinoespressif32/cores/esp32/chip-debug-report.cpp:17:
/data/cache/platformio/packages/framework-arduinoespressif32/cores/esp32/chip-debug-report.cpp: In function ā€˜void printBeforeSetupInfo()’:
/data/cache/platformio/packages/framework-arduinoespressif32/cores/esp32/HardwareSerial.h:416:16: error: ā€˜USBSerial’ was not declared in this scope; did you mean ā€˜Serial’?
416 | #define Serial USBSerial
| ^~~~~~~~~
/data/cache/platformio/packages/framework-arduinoespressif32/cores/esp32/chip-debug-report.cpp:294:3: note: in expansion of macro ā€˜Serial’
294 | Serial.begin(0);
| ^~~~~~

Does anyone know how to fix this? That would be a huge relief.

The ESP32S3 Lilygo T7 doesnt have a rs485 interface connection, so how do you want to communicate with the brink flair?

I will use a (isolated) RS485 to TTL convertor.

Depending on the rs485 model it might needs a flow_control_pin in the esphome code (or not)

My code is the following:

esphome:
  name: brink_flair_wtw
  friendly_name: Brink Flair WTW

esp32:
  board: esp32dev
  framework:
    type: arduino

api:

ota:
  - platform: esphome

logger:

web_server:
  port: 80

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

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

modbus:
  id: modbus1
  uart_id: mod_bus
  send_wait_time: 1000ms

modbus_controller:
  - id: brink
    address: 0x14
    modbus_id: modbus1
    setup_priority: -10
    update_interval: 10s

##############################
# TEMPERATURE SENSORS
##############################

sensor:
  - platform: modbus_controller
    modbus_controller_id: brink
    name: "Brink Supply Temperature"
    address: 4036
    register_type: read
    value_type: S_WORD
    unit_of_measurement: "°C"
    filters:
      - multiply: 0.1

  - platform: modbus_controller
    modbus_controller_id: brink
    name: "Brink Exhaust Temperature"
    address: 4046
    register_type: read
    value_type: S_WORD
    unit_of_measurement: "°C"
    filters:
      - multiply: 0.1

  ###############################################
  # RAW VENTILATION STATE FROM WTW (REGISTER 4022)
  ###############################################
  - platform: modbus_controller
    modbus_controller_id: brink
    id: brink_ventilation_raw_4022
    name: "Brink Ventilation Raw (4022)"
    address: 4022
    register_type: read
    value_type: S_WORD

##############################
# CONTROL MODE
##############################

select:
  - platform: modbus_controller
    modbus_controller_id: brink
    id: brink_control_mode
    name: "Brink Control Mode"
    address: 8000
    value_type: S_WORD
    optionsmap:
      "LCD": 0
      "Modbus Step": 1

##############################
# HIDDEN WRITE REGISTER (8001)
##############################

  - platform: modbus_controller
    modbus_controller_id: brink
    id: brink_ventilation_write
    internal: true
    address: 8001
    value_type: S_WORD
    optionsmap:
      "Holiday": 0
      "Low": 1
      "Normal": 2
      "High": 3

##############################
# TEMPLATE SELECT (VISIBLE IN HA)
##############################

  - platform: template
    id: brink_ventilation_mode
    name: "Brink Ventilation Mode"
    optimistic: true
    options:
      - "Holiday"
      - "Low"
      - "Normal"
      - "High"

    set_action:
      - if:
          condition:
            lambda: 'return id(brink_control_mode).current_option() == "Modbus Step";'
          then:
            - select.set:
                id: brink_ventilation_write
                option: !lambda 'return x;'
          else:
            - logger.log: "WTW staat in LCD mode — schrijven niet toegestaan"

##############################
# SYNC LOGIC (FOLLOW 4022 IN LCD MODE)
##############################

interval:
  - interval: 5s
    then:
      - if:
          condition:
            lambda: 'return id(brink_control_mode).current_option() == "LCD";'
          then:
            - lambda: |-
                int raw = id(brink_ventilation_raw_4022).state;
                std::string option;
                if (raw == 0) option = "Holiday";
                else if (raw == 1) option = "Low";
                else if (raw == 2) option = "Normal";
                else if (raw == 3) option = "High";
                id(brink_ventilation_mode).publish_state(option);

To automate:

  • change control mode to ā€œmodbus stepā€
  • wait a few seconds (i do 10 sec)
  • set the select to the desired mode

To go back to LCD/manual control:

  • change control mode to ā€œLCDā€
    it automatically changes to the setting on the LCD/manual control

Hello everyone,

First of all, thanks a lot to @Fonske for the great work on this project!

I’m quite new to ESPHome/Modbus and I’m struggling to take control of my Brink Flair 400. I can read all metrics fine, but I can’t seem to write/control anything.

Initially there’s an RF controller connected via RJ11. Whether I disconnect it or leave it connected doesn’t change anything. After a reboot I briefly see register 4020 = 12, but it quickly switches back to 4. If I try to set anything during that short window, it still has no effect.

Hardware: M5Stack Atom S3 Lite + Tail RS485. I’m using @Fonske’s code (Atom S3 file + the GPIO patch for the Tail). I tried both modbus and internalbus flair configs, same behavior.

Any help would be really appreciated.

In the logs I can see this:

23:08:09 [D] [main:386] Parsed operation mode int : 4
23:08:38 [D] [main:441] Parsed operation mode int : 2
23:08:38 [D] [main:476] Parsed operation mode int : 0

Here is my config (trimmed to the relevant parts):

substitutions:
  name: brink_flair
  friendly_name: Brink Flair 400
  timezone: Europe/Brussels
  modbusaddress: "20"

packages:
  remote_package:
    url: https://github.com/fonske/Brink-flair-modbus
    ref: main
    refresh: 0s
    files:
      - esphome/type/brink-400.yaml
      - esphome/labels/.brink-labels-en.yaml
      - esphome/.brink.base.yaml

esp32:
  board: esp32-s3-devkitc-1
  flash_size: 8MB
  framework:
    type: esp-idf
    version: recommended
    sdkconfig_options:
      COMPILER_OPTIMIZATION_SIZE: y
      CONFIG_BT_ENABLED: n

uart:
  id: mod_bus
  baud_rate: 19200
  stop_bits: 1
  parity: even
  tx_pin: GPIO2
  rx_pin: GPIO1

logger:
  logs:
    light: ERROR
    modbus: DEBUG
    modbus_controller.sensor: WARN
    modbus_controller.output: DEBUG
    modbus.number: WARN
    esp32.preferences: WARN
    sensor: WARN
    text_sensor: WARN
    dht.sensor: WARN
    switch: WARN
    button: WARN
    number: WARN
    component: ERROR

api:
  encryption:
    key: "xxx"

ota:
  - platform: esphome
    password: "xxx"

wifi:
  reboot_timeout: 0s
  fast_connect: true
  power_save_mode: high
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "Brink-Flair Fallback Hotspot"
    password: "xxx"

# --- Readbacks (what the Brink actually returns) ---
sensor:
  - platform: modbus_controller
    modbus_controller_id: brink_flair
    name: "Brink 7990 Interface type (raw)"
    register_type: holding
    address: 7990
    value_type: U_WORD
    entity_category: diagnostic

  - platform: modbus_controller
    modbus_controller_id: brink_flair
    name: "Brink 8000 Control mode (raw)"
    register_type: holding
    address: 8000
    value_type: U_WORD
    entity_category: diagnostic

  - platform: modbus_controller
    modbus_controller_id: brink_flair
    name: "Brink 8001 Step (raw)"
    register_type: holding
    address: 8001
    value_type: U_WORD
    entity_category: diagnostic

  - platform: modbus_controller
    modbus_controller_id: brink_flair
    name: "Brink 8002 Flow (raw)"
    register_type: holding
    address: 8002
    value_type: U_WORD
    entity_category: diagnostic

  - platform: modbus_controller
    modbus_controller_id: brink_flair
    name: "Brink 4020 Active Function (raw)"
    register_type: read
    address: 4020
    value_type: U_WORD
    entity_category: diagnostic

  - platform: modbus_controller
    modbus_controller_id: brink_flair
    name: "Brink 4031 Setpoint Inlet (raw)"
    register_type: read
    address: 4031
    value_type: U_WORD
    entity_category: diagnostic

  - platform: modbus_controller
    modbus_controller_id: brink_flair
    name: "Brink 4041 Setpoint Exhaust (raw)"
    register_type: read
    address: 4041
    value_type: U_WORD
    entity_category: diagnostic

# --- Writers (to change values from HA) ---
number:
  - platform: modbus_controller
    modbus_controller_id: brink_flair
    id: brink_7990_interface_type
    name: "Brink 7990 Interface type (set)"
    register_type: holding
    address: 7990
    value_type: U_WORD
    min_value: 0
    max_value: 2
    step: 1
    mode: box
    entity_category: config

  - platform: modbus_controller
    modbus_controller_id: brink_flair
    id: brink_8000_mode
    name: "Brink 8000 Control Mode (set)"
    register_type: holding
    address: 8000
    value_type: U_WORD
    min_value: 0
    max_value: 2
    step: 1
    mode: box
    entity_category: config

  - platform: modbus_controller
    modbus_controller_id: brink_flair
    id: brink_8001_step
    name: "Brink 8001 Step (set)"
    register_type: holding
    address: 8001
    value_type: U_WORD
    min_value: 0
    max_value: 3
    step: 1
    mode: box
    entity_category: config

  - platform: modbus_controller
    modbus_controller_id: brink_flair
    id: brink_8002_flow
    name: "Brink 8002 Flow (set)"
    register_type: holding
    address: 8002
    value_type: U_WORD
    min_value: 0
    max_value: 400
    step: 1
    mode: box
    entity_category: config

If there’s any specific register/log output I should add (or a known ā€œunlock/control takeoverā€ step I’m missing), tell me and I’ll provide it.

Just installed the unit bought from tweakers on my 2019 Flair 300. As a noob I had a lot of help and now it is running in HA.

Just a bit confused on how to control the fan speed.
Modbus control mode has three options: Device LCD, Modbus Step or Modbus Flow - I have no device LCD (just one led) so unsure how to set this - I tried all three

My Flair is now on Flow 0 - I can manually drag the slider and hear the fan speed increase. Also confirmed by the fan speed increasing in HA

I assumed the ā€œModbus presetā€ switches between Flow 0,1,2 and 3 - but that does not seem to do anything (In all three Modbus control modes). How do I use Home assistant to switch between Flow 0,1,2 and 3?

Some pictures to explain:
When Modbus is set to flow (1) I can change the fan speed for Flow 0m either using a button I made (2) or the slider from the included dashboard (3). In this case I selected 50 M3 and I can see it is running at 50m3 (4,5,6 and 7)

However I was hoping to switch between my 4 presets - which I understand to be labelled Flow0-Flow3. For this I set Modbus mode (1) to step (also tried LCD and flow), select button with fan speed 2 (2) and nothing seems to happen. Not 100% sure about flow numbering (starts with 0) but bith flow 1 and flow 2 are set at 100 and 150 now (3) yet the Flair keeps running at 50 M3 (4) and (5) - which is flow 0 speed

Should I be able to switch between these presets/flows and if so how? I can change the fan speed for flow0 so Assume everything is technically set up correct - or am I missing a setting in my Flair perhaps?

Greatest respect for everyone who made this possible. Feel like I am almost there!

@Jaspov Do you have a wired switch (for speed) connected to the brink?
This could block the speed position to be changed through modbus,
If you go to the webserver http://brink.local you could see the modbus failures if there are any in the logging window

Thanks Fonske. I actually do have two remotes that are connected to a receiver that is wired in. Could that be the issue?
Those remotes switch between three speed settings or timer.

Local interface seems to mostly report on lights/led. I just changed the step and then I see some references to that change.