I wondered the same thing.
Seen on Aliexpress there is a very cheap clone of the Dr Smart Tool . Thought about buying one just to see how it worked. I figure whatever a Dr Smat Tool could display should be able to be displayed on an esp32/rs485 if you could just figure out the holding addresses of each entity. I’m not smart enough to figure it out,though.
To anyone using @mdrobnak’s code, have you seen behavior like this? Every night at the same time, the follow me temp of the air handler controller stops updating. It’s quite unusual
also to clarify, this graph shows the temp being reported by the esphome as the current indoor temp, and the sensor that is being fed into it for the follow me temperature itself. I suppose it’s possible that the heat pump isn’t calling for heat because the temp @ the coils * 0.3 + the indoor temp * 0.7 is still @ the set point (ie the house is heat soaked) and since the system doesn’t feel like it needs to heat, it isn’t reporting the follow me temp anymore.
After the temp gets down to 64.4F (which is the nearest whole celsius degree), the system recovers. Also the yaml I’m using is as follows:
substitutions:
name: air-handler-controller
friendly_name: Air Handler Controller
esphome:
name: ${name}
friendly_name: ${friendly_name}
esp32:
variant: esp32
framework:
type: arduino
# Enable Home Assistant API
api:
encryption:
key: SECRET
services:
- service: follow_me
variables:
temperature: float
then:
midea_ac.follow_me:
temperature: !lambda "return temperature;"
beeper: false
ota:
- platform: esphome
password: SECRET
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Air-Handler-Controller"
password: SECRET
captive_portal:
logger:
logs:
midea_xye: WARN
external_components:
- source: github://mdrobnak/esphome@delays_updated # haven't updated to latest yet
components: [midea_xye]
# UART settings for RS485 converter dongle (required)
uart:
tx_pin: GPIO17
rx_pin: GPIO16
baud_rate: 4800
# debug: #If you want to help reverse engineer
# direction: BOTH
#dummy_receiver: true
#after:
# delimiter: [0x55]
# Main settings
climate:
- platform: midea_xye
name: Heatpump
period: 1s # Optional. Defaults to 1s
timeout: 200ms # Optional. Defaults to 100ms
beeper: false # Optional. Beep on commands.
#default_target_temperature_low: 18°C
#default_target_temperature_high: 24°C
#custom_auto: true
use_fahrenheit: true
visual: # Optional. Example of visual settings override.
min_temperature: 17 °C # min: 17
max_temperature: 30 °C # max: 30
temperature_step: 0.5 °C # min: 0.5
supported_modes: # Optional.
- FAN_ONLY
- HEAT_COOL
- COOL
- HEAT
# - DRY
# supported_presets: # Optional
# - BOOST
outdoor_temperature:
name: Outside Temp
temperature_2a:
name: Inside Coil Inlet Temp
temperature_2b:
name: Inside Coil Outlet Temp
temperature_3:
name: Outside Coil Temperature
error_flags:
name: Error Flags
protect_flags:
name: Protect Flags
# static_pressure: # I don't wanna mess with this
# name: Static Pressure
# min_value: 0
# timer_start: # since ours is a central heat pump, I never do this
# name: Timer Start
# timer_stop:
# name: Timer Stop
sensor:
- platform: homeassistant
entity_id: sensor.living_room_temperature
id: living_room_thermostat_follow_me
name: "Living Room Temperature Sensor"
filters:
- throttle: 10s # the aranet only reports every minute at best so realistically, we never need to throttle but whatever
- heartbeat: 1min
- debounce: 1s # this probably isn't necessary but for safety I like not overwhelming the follow me functionality
- lambda: return (x - 32.0) * (5.0/9.0); # aranet is in F so we convert to C
on_value:
midea_ac.follow_me:
temperature: !lambda "return x;"
- platform: wifi_signal
name: ${friendly_name} Wi-Fi Signal
update_interval: 5min
Hey all, I am trying to diagnose an issue with my Midea EvoX heatpump. If anyone who has the XYE instrumentation done on their unit could share data of the T1/T2/T3 and T4 temps while heating to compare to mine, I’d be very grateful. Ideally, it should be from another R454B refrigerant unit. Even better if you use grafana, and you share a few hours worth of snapshot.
I have a Midea EvoX Gen2 30k (2.5ton) heatpump. I’d love to compare my data with someone else’s similar Midea or rebrand. Thank you!
That’s a really interesting find. The Dr Smart Inverter Diagnostic Tool video changes how I’m thinking about some of this.
Up until now, I’ve been referring to the bus in my system as “S-Comms,” but based on what’s shown there, it’s possible what I’m seeing is actually PQE (non-S communication) over S1/S2. I hadn’t considered that distinction before.
For context, I’ve been working on a passive sniffer for the S1/S2 lines to monitor inverter behavior (separate from XYE control). The goal isn’t control — just visibility into real operating metrics. I have my current progress documented here if anyone is curious.
What really caught my attention in that video is the use of the “test port.” If that port is consistently populated across these units and operating at a 5V logic level (as suggested for non-S communication outdoor units), that could be a much cleaner and safer place to monitor traffic.
Compared to tapping directly into S1/S2 — where many installations have mains voltage present and significant noise/spikes — a 5V diagnostic interface would be a major improvement for safe, local sniffing.
I haven’t physically scoped the test port yet, so this is still theory. But combining:
Passive monitoring via a low-voltage diagnostic port
Yeah I had the same idea with the Testport. It also has power so could just put a ESP32 hanging from there for a continuous monitoring device that sees both indoor and outdoor data. One thing though to note: in the Dr Smart tool manual it says the testport pins are 5V, GND, SCL and SDA. I wonder if SCL and SDA actually mean I2C communications or they just mislabeled for the manual. I have the tool, I’d just need time to play with it…
Another odd behavior I’m observing (which is actually a pretty significant problem) is that randomly, the follow me temperature is being reported as the minimum allowable setpoint (62F) randomly. This causes the unit to suddenly call for very high heating and I can’t figure out what is causing it. Is anyone else experiencing this? I’ve tried a variety of filter tweaks on the follow me HA sensor but I actually think the issue is down the a communication failure between the AHU and the ESP32 as I stop seeing climate debug logs when this happens.
That said, if for some reason HA is down, and can’t get a value to HA, I’ll see the system go nuts. Otherwise it does report it pretty well…
One thing to note is that you can’t send a follow-me at a 5 minute interval…the system will not respect it. I think it is once a minute is the wired controller behavior.
I guess I need to put some more input validation here / hold onto the last value…
Heya @mdrobnak; yeah I assumed the frequency of heartbeating mattered so I kept it @ 1 minute. I tried other frequencies and other filter options but none seem to prevent this. I’ve since set up an automation that yells at me if the {{ states.climate.air_handler_controller.attributes.current_temperature | int }} is less than the actual device I’m using for follow me.
I definitely think the behavior you described of as if not HA_follow_me_value then previous_temp would be a really nice improvement. If you’re willing to give me a little guidance one where/how to implement that I’d be really keen to help.
Hey thanks so much for this project!! Amazing, I’ve been wanting to integrate my Vulcano duct units for years now and just stumbled on your amazing piece of work after figuring out the USB method wouldn’t work.
I’m using an M5Stack ATOM-Lite and Tail485 connected to the XYE port inside my machine and it’s working beautifully. I first had some issues with the follow me temperature until I realised the YAML earlier in the thread had a conversion to farenheit included in it!
This is my YAML for anyone who wants a ready made Celcius version, just replace with your own secret names and also the follow me entity_id with your own temperature sensor, or comment out that sensor entirely.
substitutions:
name: "dining-room-aircon"
friendly_name: "Dining Room Aircon"
comment: "ESPHome flashed M5Stack Atom with Tail485 attached to dining room aircon"
esphome:
name: ${name}
name_add_mac_suffix: false
friendly_name: ${friendly_name}
comment: ${comment}
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging (but not via UART)
logger:
#baud_rate: 0
#logs:
# component: ERROR
# Enable Home Assistant API
api:
encryption:
key: !secret aircon_encryption_key
services:
- service: follow_me
variables:
temperature: float
then:
midea_ac.follow_me:
temperature: !lambda "return temperature;"
beeper: false
ota:
- platform: esphome
password: !secret ota_password
# Enable wifi
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
use_address: 192.168.1.80
manual_ip:
# Set this to the IP of the ESP
static_ip: 192.168.1.80
# Set this to the IP address of the router. Often ends with .1
gateway: 192.168.1.1
# The subnet of the network. 255.255.255.0 works for most home networks.
subnet: 255.255.255.0
ap:
ssid: "Air-Handler-Controller"
password: !secret access_point_password
captive_portal:
# Optionally enables the ESP web server
web_server:
port: 80
auth:
username: !secret web_server_username
password: !secret web_server_password
external_components:
- source: github://mdrobnak/[email protected]
components: [midea_xye]
refresh: 0s
# UART settings for RS485 converter dongle (required)
uart:
tx_pin: GPIO26
rx_pin: GPIO32
baud_rate: 4800
debug: #If you want to help reverse engineer
direction: BOTH
#dummy_receiver: true
#after:
# delimiter: [0x55]
# Main settings
climate:
- platform: midea_xye
name: Heatpump
id: heatpump
period: 1s # Optional. Defaults to 1s
timeout: 200ms # Optional. Defaults to 100ms
beeper: true # Optional. Beep on commands.
#default_target_temperature_low: 18°C
#default_target_temperature_high: 24°C
#custom_auto: true
use_fahrenheit: false
defrost:
name: Defrost Active
visual: # Optional. Example of visual settings override.
min_temperature: 19 °C # min: 17
max_temperature: 23 °C # max: 30
temperature_step: 1 °C # min: 0.5
supported_modes: # Optional.
- FAN_ONLY
- HEAT_COOL
- COOL
- HEAT
- DRY
supported_presets: # Optional
- BOOST
outdoor_temperature: # Optional. Outdoor temperature sensor
name: Outside Temp
temperature_2a: # Optional. Inside coil temperature
name: Inside Coil Inlet Temp
temperature_3:
name: Outside Coil Temperature
timer_start: # Optional. On timer duration
name: Timer Start
timer_stop: # Optional. Off timer duration
name: Timer Stop
error_flags: # Optional.
name: Error Flags
fan_speed:
name: Fan Speed
protect_flags: # Optional.
name: Protect Flags
static_pressure:
name: Static Pressure
min_value: 0
sensor:
- platform: homeassistant
entity_id: sensor.dining_room_temperature_humidity_temperature_2
id: dining_room_aircon_follow_me
#attribute: current_temperature
name: "Dining Room Temperature Sensor"
filters:
- throttle: 10s
- heartbeat: 1min
- debounce: 1s
- lambda: return x;
on_value:
midea_ac.follow_me:
temperature: !lambda "return x;"
beeper: false
- platform: wifi_signal
name: ${friendly_name} Wi-Fi Signal
update_interval: 60s
- platform: uptime
name: "Uptime"
id: uptime_sec
internal: true
- platform: template
name: ${friendly_name} Uptime Days
lambda: |-
return (id(uptime_sec).state/60)/60/24;
icon: mdi:clock-start
unit_of_measurement: days
update_interval: 60s
switch:
- platform: midea_xye
midea_ac_id: heatpump
use_fahrenheit:
name: Use Fahrenheit
Oh, one thing I’ve noticed is that my “beeper: true” seems to be doing nothing. I tried both the XYE port on the machine itself and the connector going to the existing wall panel (wall panel not plugged in while I was testing that)
Ill have a few commits for this repository as soon as I get my unit working.
Currently getting “Received incorrect message length from AC for Command C0”. I’m getting 15 bytes by the looks of it. This is with the unit off.
Any ideas?
Received byte AA
Received byte C0
Received byte 00
Received byte 00
Received byte 00
Received byte 00
Received byte 00
Received byte 00
Received byte 00
Received byte 00
Received byte 00
Received byte 00
Received byte 00
Received byte 3F
Received byte 01
I switched to a different module and now I’m getting some results!
[20:42:02.881][D][uart_debug:113]: >>> AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55
[20:42:02.914][W][midea_xye:220]: Received 33 bytes for Command C0, using first 32
[20:42:03.025][D][uart_debug:113]: <<< AA:C0:00:00:00:00:E0:00:00:00:11:4F:4B:4C:FF:00:00:00:00:00:00:08:00:00:00:00:00:23:FF:FF:41:55:FE
[20:42:03.887][D][uart_debug:113]: >>> AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
[21:21:02.344][D][uart_debug:113]: >>> AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
[21:21:02.375][W][midea_xye:220]: Received 33 bytes for Command C4, using first 32
[21:21:02.410][D][climate:049]: 'Heatpump' - Setting
[21:21:02.414][D][climate:053]: Mode: DRY
[21:21:02.419][D][climate:438]: 'Heatpump' >>
[21:21:02.423][D][climate:441]: Mode: DRY
[21:21:02.428][D][climate:443]: Action: OFF
[21:21:02.432][D][climate:446]: Fan Mode: LOW
[21:21:02.435][D][climate:452]: Preset: NONE
[21:21:02.439][D][climate:461]: Current Temperature: 19.00°C
[21:21:02.446][D][climate:468]: Target Temperature: 21.00°C
[21:21:02.487][D][uart_debug:113]: <<< AA:C4:00:00:00:00:E0:00:00:81:11:4D:4C:4B:FF:00:00:00:00:00:00:0C:00:80:00:00:00:23:FF:FF:3A:55:FE
[21:21:03.345][D][uart_debug:113]: >>> AA:C3:00:00:00:00:82:04:15:00:00:00:00:3C:66:55
[21:21:03.376][W][midea_xye:220]: Received 33 bytes for Command C3, using first 32
[21:21:03.490][D][uart_debug:113]: <<< AA:C3:00:00:00:00:E0:00:82:81:11:4D:4C:4B:FF:00:00:00:00:00:00:0C:00:80:00:00:00:23:FF:FF:B9:55:FE
[21:21:04.284][I][midea_xye:276]: Sent Follow-Me data.
[21:21:04.359][D][uart_debug:113]: >>> AA:C3:00:00:00:00:82:04:15:00:00:00:00:3C:66:55
[21:21:04.385][W][midea_xye:220]: Received 33 bytes for Command C6, using first 32
[21:21:04.495][D][uart_debug:113]: <<< AA:C3:00:00:00:00:E0:00:82:81:15:4D:4C:4B:FF:00:00:00:00:08:00:0C:00:80:00:00:00:23:FF:FF:AD:55:FE
[21:21:05.354][D][uart_debug:113]: >>> AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55
[21:21:05.385][W][midea_xye:220]: Received 33 bytes for Command C0, using first 32
[21:21:05.388][D][climate:438]: 'Heatpump' >>
[21:21:05.392][D][climate:441]: Mode: DRY
[21:21:05.395][D][climate:443]: Action: FAN
[21:21:05.399][D][climate:446]: Fan Mode: LOW
[21:21:05.402][D][climate:452]: Preset: NONE
[21:21:05.406][D][climate:461]: Current Temperature: 18.50°C
[21:21:05.410][D][climate:468]: Target Temperature: 21.00°C
[21:21:05.489][D][uart_debug:113]: <<< AA:C0:00:00:00:00:E0:00:82:81:15:4D:4C:4B:FF:00:00:00:00:08:00:0C:00:80:00:00:00:23:FF:FF:B0:55:FE
[21:21:06.362][D][uart_debug:113]: >>> AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
[21:21:06.393][W][midea_xye:220]: Received 33 bytes for Command C4, using first 32
[21:21:06.500][D][uart_debug:113]: <<< AA:C4:00:00:00:00:E0:00:00:81:11:4D:4C:4B:FF:00:00:00:00:08:00:0C:00:80:00:00:00:23:FF:FF:32:55:FE
[21:21:07.370][D][uart_debug:113]: >>> AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55
[21:21:07.401][W][midea_xye:220]: Received 33 bytes for Command C0, using first 32
[21:21:07.404][D][climate:438]: 'Heatpump' >>
[21:21:07.408][D][climate:441]: Mode: OFF
[21:21:07.411][D][climate:443]: Action: OFF
[21:21:07.415][D][climate:446]: Fan Mode: LOW
[21:21:07.418][D][climate:452]: Preset: NONE
[21:21:07.422][D][climate:461]: Current Temperature: 18.50°C
[21:21:07.426][D][climate:468]: Target Temperature: 21.00°C
[21:21:07.501][D][uart_debug:113]: <<< AA:C0:00:00:00:00:E0:00:00:81:11:4D:4C:4B:FF:00:00:00:00:00:00:0C:00:80:00:00:00:23:FF:FF:3E:55:FE
Now after setting any climate mode the unit runs (if it has time) for a couple of cycles before turning off.