Actron Aircon / ESP32 Controller Help

Snap a photo of labels on the box outside and look it up (most of the time you will see the consumption right on the label). Unless they changed it very recently, the unit will always be power-bound, that is it will always operate at the nominal power level, whether you have 1 or 5 zones active (1 zone will simply cool faster). As with any aircon it’s not about how much it consumes but how fast your house leaks the cold/heat out.

Compatibility wise it works with any variant of LR7 and BM24 panels, if you have NEO or NEXUS panels the chances are the protocol is different.

I’ve tried to get this working to no prevail. I have the actron control unit, but I don’t have a “KEY” line, rather:

SENS-1
SENS-2
AUX
COMMON
POWER

When I press a key, measuring AUX and COMMON I see no voltage change (~3v) even whilst holding key. As soon as I press the power key the HVAC turns on, with zero voltage change.

Possibly I have a different kind of unit is all I can assume. I even tried disconnecting AUX and the commands from display still worked on just using COMMON and POWER.

As I was using multimeter I was switching settings and as soon as switched to BATT (i.e. 1.5v/9v) the AC turned off.

Any insights here would be great.

Looks like you must have a different model wall controller to the ones that we have that must use some different form of communication between the wall panel and the outside unit.

I am not sure that you would be able to get the setup working like we have with your current wall controller. Out of curiosity what model is your wall unit ?

The display model is B512GZ/B512W3.

It seems the model doesn’t support multiple displays, so that’s why there’s no “KEY” like.

It does have a relay (home automation) mode though.

Adding resistance between AUX/COMMON turns it on; removing it turns it off. I’ve connected this to GPIO with a BC549 transistor, making it a smart switch.

I found 16-bit pulses (not 40-bit) and have decoded them—I’ll share the code soon.

These pulses seem to come from the display to the controller, meaning the controller itself doesn’t handle logic, rather the display takes all inputs (from user and temp sensors) then decides whether to run or not. But further testing is tricky as I don’t have an oscillator.

Have done some more testing to see if I can work out the communication protocol from Display → Controller:

  • Tested Display powered by external 19V pack, the display did not send any pulses.
  • Tested plugging ESP into the controller (without display plugged in), no pulses.
  • Tested a 4.7k resistor on power/common lines with ESP plugged in to see if the controller needs to see enough resistance, no pulses.
  • Sent the same a well known “run” state via TX (without display plugged in) and controller did nothing.
  • If buttons were pressed (i.e Power On/Off, Zone 1 On/Off) whilst on 19V adapter, these would be applied as soon as controller plugged in (display has a battery for flash memory). But this shows the 16-bit pulse state is not persisted to controller via button presses, but rather comes from the display.

It seems pulses are only sent when the display is plugged in to the controller. There doesn’t seem to be any polling or boot up pulses either.

I don’t have enough expertise to figure out why the pulses only happen when display and controller are together. Have ordered a logic analyser as my final hope.

OK had another look and this unit appears to be 22 years old - obviously if it aint broke dont fix it ruled with these people !! On the label it is identified as

and it uses this wall controller.

There appears to be very little information online about the main AC unit - whilst there is some info about the control panel not sure which family it falls into.

Craig

Success!! Managed to get the B512GZ controller to work. This was by far one of the biggest projects I’ve done.

As it turns out the B512GZ is a “smart” display, and a “dumb” controller. Where as most of the displays/discussion in this thread are “dumb” displays and a “smart” controller. The dumb display setup is ideal where you have multiple displays.

This display communicates by sending 16-bit pulses every 370ms. Frames are a 10us low and high of 1900us for short/5900us for long. The other displays here have a 40-bit sequence with temp data etc. This display literally just sends FAN Speed (Hi/Med/Low), Compressor (Stage 1/2), Heat (On/Off) and Zone (1/2 or both). Thus if I wanted to go HA I needed to work out all the logic for running the compressor and fans myself.

My main challenge was actually getting the buck to work (as this was to replace the display and I wanted no external wires). It seemed that as soon as the buck was connected to power/common no pulses were being seen (either by controller or by a logic analyser). I thought it was due to noise so added all sorts of caps and ferrite chokes. Even tried a linear reg with no luck. Also tried an opto with no luck.

Spent a good day or so trying different approaches to work that one out. Finally asked ChatGPT to do some deep research and one out of many suggestions was to use a 4-10Ω resistor just before the buck VIN (or in my case caps before the buck). It worked! It seemed this stopped the pulses (or the edges rather) from being absorbed by the big caps.

See the final build below:

Parts used:

  • ESP32-Wroom (Espressify)
  • DC-DC buck from Jaycar (XC4514) turned down to 5v
  • 1A fuse + fuse holder
  • 1000µF cap + .1µF cap (prior to buck)
  • 1000µF cap + 100µF cap + 1µF cap (after buck - i.e. 5v)
  • 10kΩ Epoxy Dip NTC Thermistor + .1µF + 1µF in parallel and a 10k resistor from 3.3v. Using ESP32 (not common) GND as I was getting upstream noise when compressor was running. Using this as a backup temp sensor until I can test out Aqara wireless sensors.
  • BC549 transistor - base goes up to a 330Ω resistor and into TX pin (GPIO17)
  • Also have the voltage divider setup (which others have documented here) still setup for easy RX testing if I wish to plugin the display. Using 22k:4.7k, as I was reading 3.3v with 20k (too close for comfort).

ESPHome:

  • receives a 16-bit frame from home assistant.
  • sends the current frame every 370ms to the controller (GPIO17).
  • will send idle (i.e. system off) frames to controller if HA drops out (i.e. hasn’t sent latest frame in over 1 minute). This is to protect situation where HA drops off and compressor is left running in the wild.
  • sends it’s onboard temp sensor to HA

Home Assistant:

  • runs all the logic of when to run fans/compressor and to select stage 1/stage 2.
  • handles the hysteresis for temp control (i.e. 0-1°C off, >1°C stage 1, >1.5°C stage 2)
  • ensures compressor will not run for a period of time after turning off (i.e 180 seconds) to prevent short cycles
  • runs fan for a period of time after compressor is turned off (i.e. 30 seconds) to prevent condensation build up
  • will automatically ramp up fan speed if a high workload is perceived
  • uses outdoor and forecasted temp to work out cool/heat mode when in auto

Will share this code soon as I’m still tweaking a few things. Glad I got this one figured out!

What’s the model on the back of the display. How does it plug in etc?

Also 22 years is impressive! Our building is replacing all units after just 12 years due to the refrigerant in them being hard to source. And the new refrigerant is much more efficient. Is a new compressor on the cards?

I was hoping not to have to go to a new compressor initially. We are stretching to get the house initially (depending on how much our current one sells for)

And then we have to add Solar and batteries. I would like to live in it for a year or so and see how the AC performs (the house has a very large central two storey atrium (with Glass Roof) so there is very little to no zoning that can be done - so i am not sure yet how much we are going to have to run the unit in Summer (i assume a lot as it is a flat roof house facing North) (and has the previously mentioned glass pyramid roof in the Atrium !) not sure in Winter yet

I have previously had Daikin ducted with Airtouch and loved the level of control and automation i had at my finger tips. Will have to wait and see

Craig

Hey guys,

with all the great work here, I’ve managed to put this circuit together over the past few days with basically no experience, so thank you!
However, I am stuck and I’m reaching out here for some help to see if someone can point me in the right direction of where I have gone wrong.

The current situation is that any voltage that I send from the DAC above 600mV either turns the air-con on or off. I can’t get it to do anything else.

I have measured the voltage from the VOUT of the MCP4725 and it matches what I have set the “DAC Output miliVolts” to in HA. However, the voltage that I read at the KEY line running back to the panel is much lower. For example, if i set “DAC Output miliVolts” to 2000, the voltage at VOUT of the DAC is also ~2000mV but the voltage on the KEY line at J1 ends up being ~26mV.
What voltage should I be expecting when measured at the KEY line?

I have attached a photo here of the circuit in case that helps. It’s basically a copy of the one done by @brettm88:

Maybe check and make sure you have the transistor polarity correct I remember I had some strange issues when I had the transistor the wrong way around. Just check that you have the correct pins. If you have a multimeter you can test it like this.

thanks @lordvorta, I have confirmed that the transistor is wired correctly. Do you know what type of voltage I should be measuring on the output of the collector? At the moment, for all voltages I am sending from the DAC, I am seeing a voltage drop close to 0. For example, If I am sending 2000mV from the DAC, what should I expect at the KEY line?

Hey Alex. Love your work here. Any chance you would be willing to share this? :slight_smile:

Hi Alex, this is really impressive work. Thank you for sharing! If possible, could you please share the logic and any additional details that might help us to build automation.

Hi everyone,

I’ve been following this thread and the extraordinary work being done here on integrating Actron Air systems with Home Assistant. I ordered my own ESP32, built the design, and got it all working.

I then discovered that HA no longer supports custom components. So I started creating an external component for ESPHome that can be shared with the community.

I went down a deep rabbit hole and wrote a full integration for Actron Air systems with AM7/LM7/LM24 wall controllers.

You can find it on GitHub at GitHub - johnf/actron-air-esphome: Actron Air ESP32 Keypad Component for ESPHome · GitHub

What It Does

This project provides full integration for older Actron Air ducted systems (pre-2013) with AM7/LM7/LM24 wall controllers. It:

  • Reads the keypad display - Decodes the 40-bit pulse train from the wall controller to get temperature setpoint, mode, fan speed, and zone status
  • Emulates button presses - Uses an MCP4725 DAC to simulate physical button presses for full control
  • Exposes everything to Home Assistant - Climate entity, 18+ sensors, zone switches, and control buttons
  • Includes a custom Lovelace card - Retro-styled UI that looks like the original keypad

Climate Entity

  • Temperature control
  • Zone control via climate presets
  • Fan speed control
  • HVAC mode control (cool, heat, auto, fan only)
  • Optional current temperature/humidity from external sensors

Lovelace Card


Sensors:

  • Temperature setpoint (from 7-segment display)
  • Mode indicators (cool, heat, auto, run)
  • Fan speeds (high, mid, low, continuous)
  • Up to 7 zone states
  • Room, timer, and inside indicators

Controls:

  • Full climate entity with HVAC modes (off, cool, heat, auto, fan_only)
  • Fan modes (High/Medium/Low, with Continuous variants)
  • Temperature adjustment (16-29°C in 0.5°C steps)
  • Individual zone switching
  • Timer control

ESPHome Component

The ESPHome external component runs on the ESP32 and handles:

  • Interrupt-driven pulse train capture from the keypad
  • 40-bit protocol decoding to extract display and LED status
  • DAC control for button emulation
  • Exposes all sensors, switches, and buttons to Home Assistant via the native API

Keen to hear if anyone gives it a try or has feedback!

Wow, nice work @johnf . I haven’t had mine working for a while and was planning on trying to get it working again in the next couple of weeks. Will definitely give this a bash.

Nice work @johnf
Will definitely try it at some point.

I have 8 zones but I see that your solution supports 7 zones. Can it be easily expanded to 8 zones in the yaml files or is there other requirements?

So it will need a bit of testing. The issue is that I don’t have an 8 zone system. So I don’t know which pulse is used for zone 8.
And all of the 40 pulses are allocated.

The original code says there are 42 pulses and I do notice sometimes I get 40 pulses and sometimes 42.

I suspect the decoding algorithm might not be right.

I reached out to Actron late last week in the hope they might be willing to share some documentation on how this works.

But if we can work out where zone 8 is then super easy to extend it

Thanks - I am away till the 8th of January so I cant do much testing.
But after I get back will start on this and can help with what’s required to identify the 8th zone.

Wow, now that’s real nice!
I have an 8-zone, let me look it up.

Is that what you’re after?

class clsLedProto {
  public: // Add this line to change the access level to public for the following members
  enum ClassStatLeds {
    // Enumerations representing the indices in the pulse train for various status LEDs on the HVAC unit
    // Rooms are counted from the top left button line by line.
    COOL = 0,
    AUTO = 1, 
    ROOM5 = 2,
    RUN = 3,
    ROOM8 = 4,
    ROOM7 = 5,
    ROOM6 = 6,
    TIMER = 7, 
    FAN_CONT = 8, 
    FAN_HI = 9,
    FAN_MID = 10,
    FAN_LOW = 11,
    ROOM3 = 12,
    ROOM4 = 13,
    ROOM2 = 14,
    HEAT = 15,
    _3C = 16,
    _3F = 17,
    _3G = 18,
    _3B = 19,
    _3A = 20,
    ROOM1 = 21,
    _3E = 22,
    _3D = 23,
    _2B = 24,
    _2F = 25,
    _2G = 26,
    _2E = 27,
    DP = 28,
    _2C = 29,
    _2D = 30,
    _2A = 31,
    _1D = 32,
    INSIDE = 33, 
    _1C = 34,
    _1B = 35,
    _1E = 36,
    _1G = 37,
    _1F = 38,
    _1A = 39,
    };

-------------------------------------------
      cool->publish_state(ledProto.p[clsLedProto::COOL] != 0);
      auto_md->publish_state(ledProto.p[clsLedProto::AUTO] != 0);
      room5->publish_state(ledProto.p[clsLedProto::ROOM5] == 0);
      run->publish_state(ledProto.p[clsLedProto::RUN] != 0);
      room8->publish_state(ledProto.p[clsLedProto::ROOM8] == 0);
      room7->publish_state(ledProto.p[clsLedProto::ROOM7] == 0);
      room6->publish_state(ledProto.p[clsLedProto::ROOM6] == 0);
      timer->publish_state(ledProto.p[clsLedProto::TIMER] != 0);
      fan_cont->publish_state(ledProto.p[clsLedProto::FAN_CONT] != 0);
      fan_hi->publish_state(ledProto.p[clsLedProto::FAN_HI] != 0);
      fan_mid->publish_state(ledProto.p[clsLedProto::FAN_MID] != 0);
      fan_low->publish_state(ledProto.p[clsLedProto::FAN_LOW] != 0);
      room3->publish_state(ledProto.p[clsLedProto::ROOM3] != 0);
      room4->publish_state(ledProto.p[clsLedProto::ROOM4] != 0);
      room2->publish_state(ledProto.p[clsLedProto::ROOM2] != 0);
      heat->publish_state(ledProto.p[clsLedProto::HEAT] != 0);
      room1->publish_state(ledProto.p[clsLedProto::ROOM1] != 0);
      inside->publish_state(ledProto.p[clsLedProto::INSIDE] == 0);

I’m not sure how it behaves on 4-zone but notice the bottom row of the buttons (as they would be on the panel - 5,6,7,8 and the “inside”- which is the flag for when the display is showing the house temps instead of target temps) are “reverted”.