Glad it worked for you. No beer needed. Seeing that my little documentation helped others is more than enough.
I could also need some help unfortunately.
Im using a ESP32 and a RS485 adapter
and I have used your yaml code from GitHub @rstcologne
ESP32 boots up correctly, web interface works - but I don’t get any data from the Fairland pump and I can’t communicate with it.
I have tried to first flip the RX/TX cables between the RS485 and the ESP32 but I got a massive amount of modbus errors that then disappeared when I moved them back to the original RX/TX ports.
I have also tried to change position of the A and B cabled from the RS485 to the fairland pump but that doesn’t make any difference… I still get the same loggs in the web interface.
This is how it looks like. I don’t get any good readings of temperature as an example. I have tried to flip power switch on and off and I can see in the log that the ESP32 is trying to send the command OFF/ON - but nothing is happening.
Any suggestions on how I should move on with troubleshooting?
ok so in my attempts to get this working I suspected that maybe the fairland pump don’t use the modbus address 0001 so I took some help with ChatGPT and built another ESP32 to a modbus scanner and scanned the pump on all modbus addresses.
I got no respons on any channel, which is very strange. So I plugged in the original wifi unit and that works - so the pump works as it should.
could anyone be kind to test the modbus scanner config so I can make sure that it works?
esphome:
name: modbus-scanner
friendly_name: Modbus Scanner
on_boot:
priority: -10
then:
- script.execute: scan_addresses
esp32:
board: esp32dev
framework:
type: esp-idf
# Enable logging
logger:
level: DEBUG
# Enable Home Assistant API
api:
encryption:
key: "***********"
ota:
- platform: esphome
password: "*********"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Modbus-Scanner Fallback Hotspot"
password: "**************"
captive_portal:
uart:
id: mod_bus
tx_pin: TX
rx_pin: RX
baud_rate: 9600
stop_bits: 1
parity: NONE
modbus:
id: modbus1
#flow_control_pin: GPIO4 # Change to your wiring
modbus_controller:
- id: scanner_device
address: 1
modbus_id: modbus1
update_interval: never # we'll trigger updates manually
# A simple test register to read. Change to an input register if needed.
sensor:
- platform: modbus_controller
modbus_controller_id: scanner_device
name: "Scanner Test Register"
id: test_reg
register_type: holding # try 'input' if your device exposes only input regs
address: 0x0000 # change to a known-good register if you have one
value_type: U_WORD
accuracy_decimals: 0
on_value:
then:
- lambda: |-
ESP_LOGI("scanner", "✅ Found responding device at address %d", id(current_addr));
globals:
- id: scan_index
type: int
restore_value: no
initial_value: '1' # start at address 1
- id: current_addr
type: int
restore_value: no
initial_value: '1'
script:
- id: scan_addresses
then:
- logger.log: "🔍 Starting Modbus address scan (1..247)..."
- while:
condition:
lambda: 'return id(scan_index) <= 247;'
then:
- lambda: |-
id(current_addr) = id(scan_index); // remember for logging
id(scanner_device).set_address(id(current_addr));
- component.update: scanner_device # poll controller (reads test_reg)
- delay: 300ms
- lambda: 'id(scan_index) += 1;'
- logger.log: "✅ Scan finished."
I guess that next step is to try a different 485 board to see if that solves it…
anyone know if there is a way to test and verify it?
thanks
Hi Everyone,
I am a solar installer and Sigenergy Inverters can switch on SG Ready heat pumps using their DO port as described here: https://drive.google.com/file/d/1PLkny0YojKDxslZx-K8HUSDfTHJV6z7v/view?usp=sharing. Can anyone advise which port on the heat pump control board the DO1 and DO2 wires should connect to? I am guessing the BAG +12V port and specifically the DO1 would go to A and the DO2 would go to B but I wonder if anyone has any experience with this? Or should they be going to a different port altogether - perhaps what is labelled as remote controller on this wiring diagram
Hallo Alex ,
ich heiße Roman, bin auch aus Deutschland und habe auch die selbe Wärmepumpe wie du. Ich heize auch den Haus mit der Pumpe nur die Wärmepumpe hat zu viel Leistung und schaltet nach zu oft aus , meine Idee ist Leistung von der Pumpe zu regeln anhand Kompressor Frequenz . Hast du vielleicht eine Idee wie ich das realisieren kann?
Hallo, das Problem habe ich auch regel das zurzeit über den Modbus mit Super Silence (max 28% )oder Silence (Max 80%).
Läuft gut aber schöner wäre das direkt die Kompressorfrequenz zu steuern.
Ich war eine Zeitlang bei den China Anbietern unterwegs um informationen zu bekommen.
Bin aber aus familiären zeitlichen Gründen noch nicht weiter gekommen.
Ich habe noch ein paar Modbus Register bekommen direkt für den DC Inverter. Bringt aber nicht viel den Kompressor zu regeln wenn das EEV von der Hauptplatine bei mir MWH 298 geregelt wird.
Aber sobald ich mehr zeit habe, werde ich mich hier auch wieder melden.
LG
Ich habe zwar für ein Leistungstärkeres Board diese Modbus Informationen bekommen.
Aber es sollten die gleichen sein.
So könnte man ja den Kompressor direkt ansteuern wenn man sich zwischen Hauptplatine und DC board klemmt. Den Modbussteckplatz sieht man ja in der PDF.
I did receive these Modbus details for a more powerful board,
but they should be identical.
This would allow the compressor to be controlled directly if you tap in between the main board and the DC board.
The Modbus connector can be seen in the PDF.
Thanks for the info in this topic!
I have a Fairland Inver-X Vertical heatpump and added a m5stack atom lite + tail485. Imo this is a really easy solution as you only need 1 cable to connect everything.
This is what I used:
- m5stack atom lite: ATOM Lite ESP32 IoT Development Kit– m5stack-store
- m5stack tail485: ATOM Tail485 - RS485 Converter for ATOM– m5stack-store
- JST-XH 3S 4-pins cable: https://www.amazon.com.be/dp/B07JF651PG?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1
I followed this guide to configure the atom using home assistant ESPHome Builder: https://docs.m5stack.com/en/homeassistant/light/atom_lite_light
Then I installed this Yaml on the esp32. This one is giving all relevant sensor data. Temperatures are in Celsius. Edit the HIDDEN strings to correspond with your data.
esphome:
name: warmtepomp-fairland
friendly_name: Fairland Inver-X
esp32:
board: m5stack-atom
flash_size: 4MB
framework:
type: esp-idf
logger:
baud_rate: 0 # Disabled — UART needed for Modbus
api:
encryption:
key: "HIDDEN"
ota:
- platform: esphome
password: "*****************"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Fairland Fallback Hotspot"
password: "HIDDEN"
captive_portal:
# --- UART for RS485 (Tail485 pins) ---
uart:
id: mod_bus
tx_pin: GPIO26
rx_pin: GPIO32
baud_rate: 9600
stop_bits: 1
parity: NONE
data_bits: 8
modbus:
id: modbus1
uart_id: mod_bus
modbus_controller:
- id: fairland
address: 0x01
modbus_id: modbus1
update_interval: 10s
command_throttle: 100ms # 100ms between requests, well above 60ms minimum
# ============================================================
# BINARY SENSORS
# ============================================================
binary_sensor:
# --- Atom Lite Button ---
- platform: gpio
pin:
number: GPIO39
mode: INPUT
inverted: true
name: "Atom Button"
id: atom_button
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_multi_click:
- timing:
- ON for at most 0.8s
- OFF for at most 0.5s
- ON for at most 0.8s
- OFF for at least 0.2s
then:
- logger.log: "Double Clicked"
- light.turn_on:
id: atom_light
red: 100%
blue: 50%
green: 20%
brightness: 50%
- timing:
- ON for at least 0.8s
then:
- logger.log: "Single Long Clicked"
- light.turn_on:
id: atom_light
green: 100%
blue: 50%
red: 30%
brightness: 100%
# --- Warmtepomp status ---
- platform: modbus_controller
modbus_controller_id: fairland
name: "Status ON/OFF"
register_type: discrete_input
address: 0
force_new_range: true
- platform: modbus_controller
modbus_controller_id: fairland
name: "Ontdooien Actief"
register_type: discrete_input
address: 1
force_new_range: true
- platform: modbus_controller
modbus_controller_id: fairland
name: "Storing / Beveiliging"
register_type: discrete_input
address: 16
force_new_range: true
# ============================================================
# LED
# ============================================================
light:
- platform: esp32_rmt_led_strip
rgb_order: GRB
pin: GPIO27
num_leds: 1
chipset: SK6812
name: "Atom RGB Light"
id: atom_light
restore_mode: RESTORE_DEFAULT_OFF
effects:
- random:
name: "Random"
transition_length: 1s
update_interval: 1s
# ============================================================
# SENSORS (Input Registers FC04)
# Temperature type 1: °C = (raw - 60) / 2 → filters: multiply 0.5, offset -30
# Temperature type 2: °C = raw / 2 → filters: multiply 0.5 only
# All values arrive in HA already converted to °C
# ============================================================
sensor:
- platform: modbus_controller
modbus_controller_id: fairland
name: "Compressor Snelheid"
register_type: read
address: 0
force_new_range: true
unit_of_measurement: "%"
state_class: measurement
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: fairland
name: "PFC Spanning"
register_type: read
address: 2
force_new_range: true
unit_of_measurement: "V"
device_class: voltage
state_class: measurement
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: fairland
name: "Inlaatwater Temperatuur"
id: pwp_inlet_water_temperature
register_type: read
address: 3
force_new_range: true
unit_of_measurement: "°C"
device_class: temperature
state_class: measurement
accuracy_decimals: 1
value_type: U_WORD
filters:
- multiply: 0.5
- offset: -30
- platform: modbus_controller
modbus_controller_id: fairland
name: "Uitlaatwater Temperatuur"
register_type: read
address: 4
force_new_range: true
unit_of_measurement: "°C"
device_class: temperature
state_class: measurement
accuracy_decimals: 1
value_type: U_WORD
filters:
- multiply: 0.5
- offset: -30
- platform: modbus_controller
modbus_controller_id: fairland
name: "Buitentemperatuur"
register_type: read
address: 5
force_new_range: true
unit_of_measurement: "°C"
device_class: temperature
state_class: measurement
accuracy_decimals: 1
value_type: U_WORD
filters:
- multiply: 0.5
- offset: -30
- platform: modbus_controller
modbus_controller_id: fairland
name: "Gas Uitlaat Temperatuur"
register_type: read
address: 6
force_new_range: true
unit_of_measurement: "°C"
device_class: temperature
state_class: measurement
accuracy_decimals: 1
value_type: U_WORD
filters:
- multiply: 0.5 # Type 2 — no offset
- platform: modbus_controller
modbus_controller_id: fairland
name: "Buitenspoel Temperatuur"
register_type: read
address: 7
force_new_range: true
unit_of_measurement: "°C"
device_class: temperature
state_class: measurement
accuracy_decimals: 1
value_type: U_WORD
filters:
- multiply: 0.5
- offset: -30
- platform: modbus_controller
modbus_controller_id: fairland
name: "Gas Retour Temperatuur"
register_type: read
address: 8
force_new_range: true
unit_of_measurement: "°C"
device_class: temperature
state_class: measurement
accuracy_decimals: 1
value_type: U_WORD
filters:
- multiply: 0.5
- offset: -30
- platform: modbus_controller
modbus_controller_id: fairland
name: "Binnenspoel Temperatuur"
register_type: read
address: 9
force_new_range: true
unit_of_measurement: "°C"
device_class: temperature
state_class: measurement
accuracy_decimals: 1
value_type: U_WORD
filters:
- multiply: 0.5
- offset: -30
- platform: modbus_controller
modbus_controller_id: fairland
name: "Compressor Frequentie"
register_type: read
address: 10
force_new_range: true
unit_of_measurement: "Hz"
state_class: measurement
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: fairland
name: "Compressor Stroom"
register_type: read
address: 11
force_new_range: true
unit_of_measurement: "A"
device_class: current
state_class: measurement
accuracy_decimals: 1
value_type: U_WORD
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: fairland
name: "Koelplaat Temperatuur"
register_type: read
address: 12
force_new_range: true
unit_of_measurement: "°C"
device_class: temperature
state_class: measurement
accuracy_decimals: 1
value_type: U_WORD
filters:
- multiply: 0.5 # Type 2 — no offset
- platform: modbus_controller
modbus_controller_id: fairland
name: "EEV Opening"
register_type: read
address: 13
force_new_range: true
state_class: measurement
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: fairland
name: "DC Ventilator Snelheid"
register_type: read
address: 14
force_new_range: true
unit_of_measurement: "RPM"
state_class: measurement
value_type: U_WORD
# ============================================================
# SWITCH
# ============================================================
switch:
- platform: modbus_controller
modbus_controller_id: fairland
name: "Warmtepomp Aan/Uit"
register_type: coil
address: 0
# ============================================================
# SELECT (mode control)
# ============================================================
select:
- platform: modbus_controller
modbus_controller_id: fairland
name: "Functie Selectie"
address: 0
value_type: U_WORD
optionsmap:
"Auto": 0
"Verwarmen": 1
"Koelen": 2
- platform: modbus_controller
modbus_controller_id: fairland
name: "Werkingsmodus"
address: 1
value_type: U_WORD
optionsmap:
"Smart": 0
"Stil": 1
"Turbo": 3
- platform: modbus_controller
modbus_controller_id: fairland
name: "Waterpomp Modus"
address: 5
value_type: U_WORD
optionsmap:
"Continu": 0
"Watertemperatuur Gestuurd": 1
"Tijd + Watertemperatuur": 2
# ============================================================
# NUMBERS
# Raw registers hidden, template entities show clean °C
# Conversion: °C = (raw - 60) / 2 | raw = (°C × 2) + 60
# ============================================================
number:
# --- Hidden raw Modbus registers ---
- platform: modbus_controller
modbus_controller_id: fairland
id: fairland_verwarmen_raw
internal: true
address: 3
register_type: holding
value_type: U_WORD
min_value: 96
max_value: 140
step: 2
- platform: modbus_controller
modbus_controller_id: fairland
id: fairland_koelen_raw
internal: true
address: 4
register_type: holding
value_type: U_WORD
min_value: 84
max_value: 120
step: 2
- platform: modbus_controller
modbus_controller_id: fairland
name: "Waterpomp Werktijd"
address: 6
register_type: holding
value_type: U_WORD
min_value: 10
max_value: 120
step: 5
unit_of_measurement: "min"
# --- Human-readable °C template entities ---
- platform: template
name: "Verwarmen Doeltemperatuur"
unit_of_measurement: "°C"
device_class: temperature
min_value: 18
max_value: 40
step: 0.5
lambda: |-
return (id(fairland_verwarmen_raw).state - 60.0) / 2.0;
set_action:
- number.set:
id: fairland_verwarmen_raw
value: !lambda return (x * 2.0) + 60.0;
- platform: template
name: "Koelen Doeltemperatuur"
unit_of_measurement: "°C"
device_class: temperature
min_value: 12
max_value: 30
step: 0.5
lambda: |-
return (id(fairland_koelen_raw).state - 60.0) / 2.0;
set_action:
- number.set:
id: fairland_koelen_raw
value: !lambda return (x * 2.0) + 60.0;
To open the Inver-X Vertical: first unscrew 3 screws on the top back of the heatpump to remove the top cover. Then unscrew all screws securing the front plate (multiple on the bottom, multiple on the top hidden under the top cover, also one or 2 on the right side behind the cover where the power cable enters the heatpump). After all screws of the front plate are unscrewed, you can lift the front cover, being carefull as the control screen is connected with a cable, just move it to the side a bit.
Then you can easily connect the atom:
I just left the atom in the enclosure and it had enough WiFi range to connect to my access point which is a couple of meters away.
I didn’t change anything on the dip switches:
In case some else is looking for a suitable 4 pin plug to use instead of opening up the heatpump. This one was a perfect match and is identical to the wifi module plug (4Pin, 0.3mm2). https://nl.aliexpress.com/item/1005011641408936.html Do double check the size references on your own unit.
question regarding power consumption calculation:
which values are you getting reported out of pfc voltage? i do have a ric70t (tripple phase) and the value is 290V which is quite strange. which is in my case power = compressor current 5A * 290V = 1450 Watt which is way too low under full load.
or do i have to calculate compressor current * pfc voltage *3 to get power consumption in total wirh 3 phase models?
Hi,
can you turn on and off ,set temperature and mode your fairland inver-x heatpump with this set (m5stack atom lite / m5stack tail485) or just get data from sensors?
Thanks
Gábor
i implemented this with m5 atom + rs485 exactly like it is described here. everything works, controlling and getting sensor data - the only drawback is to find the best location where to place the m5 to have a proper WiFi signal
Fairland VBIV 20/3F H8 (PC1004 board) via Elfin-EW11A — All Modbus function codes return “Illegal Function”
Hi everyone,
I’m trying to integrate my Fairland/VBIV 20/3F H8 pool heat pump (with PC1004 controller board) into Home Assistant via Modbus. I’ve connected an Elfin-EW11A RS485-to-WiFi gateway to the CN13 port on the PC1004 board (pinout: 12V, 485_A3, 485_B3, GND).
What works
- EW11A connects to WiFi and is reachable at 192.168.178.254:8899
- Home Assistant opens the Modbus connection successfully (“modbus warmtepomp communication open”)
- The device at slave ID 1 responds to requests (no timeouts)
- CRC checks pass — framing is correct
The problem
Every function code returns Exception Code 0x01 (Illegal Function):
# FC03 (Read Holding Registers) at address 3:
send: 0x01 0x03 0x00 0x03 0x00 0x01
recv: 0x01 0x83 0x01 → Illegal Function
# FC04 (Read Input Registers) at address 3:
send: 0x01 0x04 0x00 0x03 0x00 0x01
recv: 0x01 0x84 0x01 → Illegal Function
# FC01, FC02, FC03, FC04 at address 0: all return Illegal Function
I tested both:
- EW11A Protocol = “Modbus” + HA
type: tcp - EW11A Protocol = “None” + HA
type: rtuovertcp
Same result in both modes.
EW11A settings
- Serial: 9600, 8, 1, None
- TCP Server on port 8899
- Before my tests, the EW11A status page showed 6971 frames sent/received with 0 failures (so the serial link was working at some point)
My setup
- Heat pump: VBIV 20/3F H8 (Fairland OEM)
- Controller board: PC1004
- Connected to: CN13 port (pins labeled 12V, 485_A3, 485_B3, GND)
- Gateway: Elfin-EW11A (firmware 1.44.1)
- Home Assistant on 192.168.178.83
My questions
- Is CN13 the correct Modbus port? Most community posts reference a connector labeled “B A G +12V”. The CN13 labels say “485_A3, 485_B3” — could this be a different RS485 bus with a proprietary protocol?
- Does the PC1004 board use standard Modbus? Most documented setups use MWH298 or similar boards. Has anyone successfully connected a PC1004?
- Could the slave ID be different from 1? Is there a way to determine the correct slave ID for this board?
- Does anyone have a register map or documentation for the PC1004?
Any help would be greatly appreciated! I’ve been following this thread and the spdr870 GitHub repo, but those are for different controller boards.
Thanks!
Thank you. I bought the same stuff and it works perfectly. You made my day!
... but you still have to open the cover to reach the connector, don't you? I mean, the Wifi-Connector doesn't seem to be useable for our purpose.
Thank you for your contibuation I was stuck and tried a lot of thing except this ! Once I have connected on D5 & D6 it has instantanely worked !
Thanks a lot for sharing this ESPHome / Modbus configuration. It helped me a lot to get my BWT pool heat pump working in Home Assistant.
In my case, I used an AZDelivery NodeMCU ESP8266 board and connected it through D5 / D6 instead of the original RX/TX setup, which was not working for me.
I also don’t have the ESPHome add-on available in my Home Assistant setup. ESPHome Builder was crashing on Home Assistant because my Raspberry Pi 3 is already close to its usage limits, so I had to do it another way using the terminal.
One important thing asked in some replies: I did not change the DIP switch pin settings.
After that, I was able to integrate the entities into my Home Assistant dashboard. Thanks again for the work and for sharing it! Now lots of fun making cards and automations ![]()
Thank you so much! Awesome work.
I finally made my own integration with github-repos from contributors here and other documents found around.
It is configured to use RS485-protocol towards the Aquaforte MWH367-PBC-board on it's Wifi-port.
phendrickx/Aquaforte-PoolHeater: RS485 integration through ESPHome on Aquaforte Heatpump
A question regarding the switch from Tuya to ESPhome control, are you able to set timers and do they operate on the unit same as when set by Tuya app?
When set from the app, the heat pump will start/stop to sample water temperature and decide whether to stay running.









