RFC: Improving vane controls on Mitsubishi minisplits

I have a MSZ-FH09NA minisplit head. The OEM remote supports a number of vane controls which are missing from esphome’s Mitsubishi IR transmitter module:

  • Horizonal vane can be set to point left, center left, center, center right, right, or Swing.
  • Two separate vertical vanes, one on the left and one on the right, can be independently controlled. As with other Mitsubishi units, each one can be set to auto, swing, or five different fixed positions.
  • The “i-see” presence sensor can be set to blow air on the occupant, blow air away from the occupant, or ignore the occupant.

Presently, the only vane options in esphome are Swing and Auto. Both options cause hot air to be blown directly in my face. Additionally, esphome can only control the right vertical vane; it doesn’t set any of the necessary bits to control the left one. Ideally I would like to be able to choose fixed vane positions from HA.

I set up an IR sniffer, wrote a protocol decoder, and started mapping out the commands sent by the OEM remote. The hard part, I think, will be plumbing up the necessary APIs to get these vendor-specific functions. There was some previous discussion at Vane control for Climate integrations - #5 by akhand but it seemed inconclusive.

Some options might include:

  • Make the Mitsubishi vane controls a “first class citizen” in the HA climate module, somehow agreeing on what format to use across manufacturers and designing something that everyone agrees is sufficiently future proof.
  • Or, esphome can offer mappings to override default behavior. Maybe an optional, off-by-default setting that tells it to send left + right vane controls. Maybe an option that maps Swing or Auto to a fixed vane position.
  • Or, esphome can offer a way to send arbitrary Mitsubishi-formatted commands. For instance, when I have to use an unsupported NEC protocol variant, I do:
button:
  - platform: template
    name: "tv-remote-on"
    on_press:
      - remote_transmitter.transmit_raw:
          carrier_frequency: 38000
          code: [4500, -4500, 560, -1690, 560, -1690, 560, -1690, 560, -560, 560, -560, 560, -560, 560, -560, 560, -560, 560, -1690, 560, -1690, 560, -1690, 560, -560, 560, -560, 560, -560, 560, -560, 560, -560, 560, -1690, 560, -560, 560, -560, 560, -1690, 560, -1690, 560, -560, 560, -560, 560, -1690, 560, -560, 560, -1690, 560, -1690, 560, -560, 560, -560, 560, -1690, 560, -1690, 560, -560, 560]
          repeat:
            times: 3
            wait_time: 20ms

Maybe, if I want to send an arbitrary Mitsubishi command, I could ask the Mitsubishi IR transmitter module to do something like:

# Automatically fill in header and checksum for the raw command:
# 23 cb 26 01 00 20 48 08 40 40 62 00 00 00 91 00 00 f8

code: [ 0x20, 0x48, 0x08, 0x40, 0x40, 0x62, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00 ]

The missing commands I mapped out are:

Horizontal vane control:

swing horizontal vane:
     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
HEX: 23 cb 26 01 00 20 48 08 c0 40 62 00 00 00 91 00 00 78

left:
HEX: 23 cb 26 01 00 20 48 08 10 40 62 00 00 00 91 00 00 c8
                             ^^   

center left:
HEX: 23 cb 26 01 00 20 48 08 20 40 62 00 00 00 91 00 00 d8
                             ^^

center:
HEX: 23 cb 26 01 00 20 48 08 30 80 62 00 00 00 91 00 00 28
                             ^^ ^^

center right:
HEX: 23 cb 26 01 00 20 48 08 40 40 62 00 00 00 91 00 00 f8
                             ^^

right:
HEX: 23 cb 26 01 00 20 48 08 50 40 62 00 00 00 91 00 00 08
                             ^^

i-See operation:

swing horizontal vane, i-see disabled:
     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
HEX: 23 cb 26 01 00 20 48 08 c0 40 62 00 00 00 91 00 00 78

indirect mode:
HEX: 23 cb 26 01 00 20 48 08 00 40 62 00 00 00 91 02 00 ba
                             ^^                   ^^
direct mode:
HEX: 23 cb 26 01 00 20 48 08 00 40 62 00 00 00 91 03 00 bb
                                                  ^^

Right vertical vane:

wide vane sweep, l/r vane auto, fan high:
     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
HEX: 23 cb 26 01 00 20 48 08 c0 84 61 00 00 00 91 00 00 bb

change right vane to highest fixed position:
HEX: 23 cb 26 01 00 20 48 08 c0 4c 61 00 00 00 91 00 00 83
                                ^^
                                1000 0100 -> 0100 1100
then lower:
HEX: 23 cb 26 01 00 20 48 08 c0 54 61 00 00 00 91 00 00 8b
                                ^^
                                0100 1100 -> 0101 0100

HEX: 23 cb 26 01 00 20 48 08 c0 5c 61 00 00 00 91 00 00 93
                                ^^
                                0100 0100 -> 0100 1100
HEX: 23 cb 26 01 00 20 48 08 c0 64 61 00 00 00 91 00 00 9b
                                ^^
                                0100 1100 -> 0110 0100

HEX: 23 cb 26 01 00 20 48 08 c0 6c 61 00 00 00 91 00 00 a3

then swing:
HEX: 23 cb 26 01 00 20 48 08 c0 7c 61 00 00 00 91 00 00 b3
                                ^^

back to auto:
HEX: 23 cb 26 01 00 20 48 08 c0 84 61 00 00 00 91 00 00 bb

Left vertical vane:

swing mode: both, fan high (from remote):
     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
HEX: 23 cb 26 01 00 20 48 08 c0 7c 60 00 00 00 91 00 38 ea

change left vane to Auto:
     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
HEX: 23 cb 26 01 00 20 48 08 c0 bc 60 00 00 00 91 00 00 f2
                                ^^                   ^^
                                0111 -> 1011

change left vane to highest fixed position:
     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
HEX: 23 cb 26 01 00 20 48 08 c0 7c 60 00 00 00 91 00 08 ba
                                ^^                   ^^

change left vane to next lower position:
     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
HEX: 23 cb 26 01 00 20 48 08 c0 7c 60 00 00 00 91 00 10 c2
                                                     ^^
then as it goes lower, substitute 18, 20, 28

then left vane swing:
HEX: 23 cb 26 01 00 20 48 08 c0 7c 60 00 00 00 91 00 38 ea
                                                     ^^

One other data point:

I have another head without the fancy vanes (MSZ-GS12NA). Using the OEM GS remote with the FH, I see similar issues to using esphome. i.e. it only controls the rightmost vane. The GS remote is missing the L/R vane controls, horizontal vane control, and i-See control.

I had originally suspected that Mitsubishi built some sort of backward compatibility into their remotes, such that a less-capable remote would “do the right thing” on an FH unit and control both vertical vanes. The GS and FH remotes set some different bits in bytes 0x0e and 0x06. But this doesn’t seem to be used for compatibility, hinting that we will probably need the user to explicitly tell esphome which features to use on their head.

The GS commands looked like:

vane auto:
     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
HEX: 23 cb 26 01 00 20 08 00 30 80 74 00 00 00 81 00 00 e2

1,2,3,4,5:
     00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
HEX: 23 cb 26 01 00 20 08 00 30 48 74 00 00 00 81 00 00 aa
                                ^^
HEX: 23 cb 26 01 00 20 08 00 30 50 74 00 00 00 81 00 00 b2
HEX: 23 cb 26 01 00 20 08 00 30 58 74 00 00 00 81 00 00 ba
HEX: 23 cb 26 01 00 20 08 00 30 60 74 00 00 00 81 00 00 c2
HEX: 23 cb 26 01 00 20 08 00 30 68 74 00 00 00 81 00 00 ca

swing:
HEX: 23 cb 26 01 00 20 08 00 30 78 74 00 00 00 81 00 00 da

BTW, the (not quite complete but good enough) reference I used for initially understanding the protocol was Reverse engineering the Mitsubishi AC Infrared protocol

I also found HVAC-IR-Control/python/hvac_ircontrol/mitsubishi.py at 4b6b7944b28ce78247f19744c272a36935bbb305 · r45635/HVAC-IR-Control · GitHub which agrees with my findings on the horizontal vane control, but disagrees on other controls like i-see. Possibly there are several subtly different versions of the protocol.

1 Like

I don’t know what’s the point of your post, are you willing to write external component for your Mitsu? If not, did you try heatpumpir platform, it includes several Mitsu protocols and might offer some improvement for you.

The point is that the vane configurations listed here only represent a tiny subset of possible settings:

and 100% of them blow hot air in my face. When I use the OEM remote, I can trivially configure the vanes not to blow hot air in my face. I would like a way to configure HA/esphome to (likewise) not blow hot air in my face.

Based on the sniffer traces above I know the IR codes to do what I want to do. But I’m looking for feedback on how best to integrate the new functionality into esphome/HA.

This presumably involves enhancing esphome/esphome/components/mitsubishi/mitsubishi.cpp at 5a36cea5eccead440a6984227ae84d2ac4c34173 · esphome/esphome · GitHub ? Or is this component superseded by something else?

Sure. Is there another example of this I could look at? Specifically, an external component for an HVAC device that uses esphome to send IR codes for features that aren’t supported by the stock climate module?

The documentation I see at IR Remote Climate - ESPHome - Smart Home Made Simple says:

The heatpumpir platform supports dozens of manufacturers and hundreds of AC units by utilising the Arduino-HeatpumpIR library. This platform compiles only under arduino framework or LibreTiny, and should only be used if your AC unit is not supported by any of the other (native) platforms from above. No support can be provided for Arduino-HeatpumpIR, because it is a third party library. This platform utilises the library’s generic one-size-fits-all API, which might not line up perfectly with all of the supported AC units. For example, some AC units have more fan speed options than what the generic API supports.

I am not sure how that helps me. Glancing through the Mitsubishi* source files at GitHub - ToniA/arduino-heatpumpir: An Arduino library to control split-unit heatpumps over Infrared I don’t see separate controls for left/right vanes or i-See. Based on the bolded quote above, it seems unlikely that anyone will want to add more parameters to e.g. HeatpumpIR::send() to support manufacturer-specific functionality.

Also, I found this commit where horizontal swing was added: Add horizontal swing support to ClimateEntity (#125578) · home-assistant/core@a7db35c · GitHub

It’s theoretically possible to plumb up the fixed vane positions, left/right vanes, i-See, etc. the same way. But I don’t know if the project owners actually want to do that; it significantly increases the interface’s complexity. Hence the RFC.

Is there a better way to expose this functionality?

Esphome component is very generic. High-end mitsu models have so many functions that it’s not practical to cover everything.
I mentioned heatpumpir, because it covers many mitsu models and supposed to offer 5-step vertical control (don’t know if that was your main issue).
Of course you can build your own component if you have skills for that.
Another possible approach is to record your favorite settings and use them without normal ir-climate manner.

heatpumpir suffers from the same problem: it only knows how to control the right vane. The left vane always blows hot air in my face.

Is there an example of this, ideally for another IR-controlled HVAC device? I’d like to better understand what existing infrastructure (e.g. climate APIs) would or would not be leveraged for this solution.

Yes, like I wrote it offers 5-step vertical control (you didn’t specify which missing parameter “blows to your face”).

I don’t know. Do some search.
IRremoteESP8266 or HeatpumpIR likely offer you the main job done, decoding protocol, so all you need to do is to make esphome component.

It doesn’t control the left vane at all, therefore the left vane gets stuck on Auto and points in an unwanted direction.

Not seeing any functional difference with HeatpumpIR. It seems to use the same API to talk to HA as the Mitsubishi module, therefore it’s missing the fine grained vane settings. All you can do is override them statically in the yaml.

I mean, those two (arduino) libraries have probably your protocol decoded. If so, you “just” need to make external component for esphome.

I already have the protocol decoded. That’s the subject of the entire first post in this thread.

The question is how best to integrate the new functionality (e.g. left vane control) into esphome/HA if I want to let the user control manufacturer-specific features.

Or some part of it.

Either propose these additions to native esphome component on github or make your own.