Window air conditioners running esphome

tl;dr I hacked two window ACs to run esphome

All of this is mains electrical, so if you don’t know the difference between live and neutral, you’ve got some studying to do before tackling this kind of a job.

I’ve done this to two of my window ACs, but in theory it should be possible to modify any freestanding “dumb” air conditioner. I’m not sure about units with electronics (e.g. a screen or remote) - I’ve only been able to hack apart my cheapest-available units.


This wiring diagram shows how the unit works. It’s entirely electro-mechanical, meaning it’s only two switches and a relay. Paying careful attention to the wire colors, and peek under the cover to identify all the wires. In my case, the supply wires are easy to spot (live, neutral and ground), and the fan low wire is black, fan high is red, and compressor is brown.

I hacked apart a 5v USB power supply, just to include everything inside the AC unit. Wired supply in line with the mains input, and the 5V output is powering a dual relay board.

I’ve wired the dual relay board the same way the internals were designed - if the fan is not powered on, the supply side of the compressor is not live. Basically, output from the fan relay is the common pin for the compressor.

I stuffed the guts (properly isolated, of course) inside the unit, and passed out the 5v, GND, IN1 and IN2 lines out the front of the unit. Put it all back together, and voila:

ESPHome sketch is pretty simple for now. The plan is to integrate a DHT22 so it’ll have a full blown thermostat in the code on the device, and i2c display to show the settings, and maybe a rotary encoder for input. Not sure yet. For now, I’ve integrated a different sensor in the same room.
image

It’s an ongoing process, just excited to share my progress. Ideally I’ll have a better interface on the device, a sensor (or more), and a 3d printed enclosure that fits in with the machine.

3 Likes

I love seeing this kind of stuff. Thanks for sharing!

1 Like

Excellent work! Thanks for sharing. I would love to see your EspHome code. Also, please keep us posted of the future improvements.

Thanks,

Sorry for the delay in posting the yaml, I somehow deleted the original esphome device, so had to rewrite it from scratch. It’s very basic so far, no support yet for on-device temp/humidity sensor, but that should be coming in the near future.

esphome:
  name: ac_01
  platform: ESP8266
  board: d1_mini

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

  ap:
    ssid: "AC 01"

captive_portal:

# Enable logging.
logger:
  level: debug

# Enable Home Assistant API.
api:

# Enable over-the-air updates.
ota:

# Enable Web server.
web_server:
  port: 80

# Sync time with Home Assistant.
time:
  - platform: homeassistant
    id: homeassistant_time


# Text sensors with general information.
text_sensor:
  # Expose WiFi information as sensors.
  - platform: wifi_info
    ip_address:
      name: AC 01 IP
    ssid:
      name: AC 01 SSID

# Sensors with general information.
sensor:
  - platform: uptime
    name: AC 01 Uptime
    
  - platform: homeassistant
    entity_id: sensor.esp32_e_temperature
    id: temp
    
binary_sensor:
  - platform: status
    name: AC 01 Status
        
status_led:
    pin:
      number: D4
      inverted: true

output:
  - platform: gpio
    pin: 
      number: D2
      inverted: true
    id: compressor_out
  - platform: gpio
    pin: 
      number: D1
      inverted: true
    id: fan_out
    
switch:
  - platform: output
    output: fan_out
    id: fan
    name: AC 01 Fan
  - platform: output
    output: compressor_out
    id: compressor
    name: AC 01 Compressor
    
climate:
  - platform: bang_bang
    sensor: temp
    default_target_temperature_low: 24 °C
    default_target_temperature_high: 26 °C
    name: AC 01 Thermostat

    cool_action:
      - switch.turn_on: fan
      - switch.turn_on: compressor
    idle_action:
      - switch.turn_off: compressor
      - delay: 120s
      - switch.turn_off: fan

Great! Thanks again and please keep us posted of the future improvements.

An update from the weekend: I’ve managed to integrate an HTU21D temperature/humidity sensor, a BH1750 light level sensor (just because I had one handy) and an oled screen. Using the dev branch of esphome (which now supports single function climate in the bang-bang controller) and I’ve got a fully functional AC.

The schematic looks like this:

And the updated yaml, which is much more generalized, since I’ll be re-using the code on a few devices.

substitutions:
  DEVICE_ID: ac_01                                  # Device ID to show in Home Assistant. Access from the integrations tab, by adding ${DEVICE_ID}.local
  DEVICE_NAME: AC 01                                # The human-friendly device name
  STATUS_PIN: D4                                    # On-board LED pin, to indicate status. D4 on a Wemos D1 mini
  COMPRESSOR_OUTPUT: D6                             # GPIO that controls the compressor relay
  FAN_OUTPUT: D7                                    # GPIO that controls the fan on/off
  SDA: D2                                           # i2c data GPIO
  SCL: D1

esphome:
  name: ${DEVICE_ID}
  platform: ESP8266
  board: d1_mini

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

  ap:
    ssid: ${DEVICE_ID}

captive_portal:

# Enable logging.
logger:
  level: debug

# Enable Home Assistant API.
api:

# Enable over-the-air updates.
ota:

# Enable Web server.
web_server:
  port: 80
  
# Enable the i2c bus
i2c:
  sda: ${SDA}
  scl: ${SCL}
  scan: False
  
# Sync time with Home Assistant.
time:
  - platform: homeassistant
    id: homeassistant_time

# Text sensors with general information.
text_sensor:
  # Expose WiFi information as sensors.
  - platform: wifi_info
    ip_address:
      name: ${DEVICE_NAME} IP
    ssid:
      name: ${DEVICE_NAME} SSID

# Sensors with general information.
sensor:
  - platform: uptime
    name: ${DEVICE_NAME} Uptime
    
  - platform: htu21d
    temperature:
      id: temp
      name: ${DEVICE_NAME} Temperature
    humidity:
      id: hum
      name: ${DEVICE_NAME} Humidity
    update_interval: 10s
    
  - platform: bh1750
    name: ${DEVICE_NAME} Lux
    id: lux
    address: 0x23
    update_interval: 10s
    
binary_sensor:
  - platform: status
    name: ${DEVICE_NAME} Status
        
status_led:
    pin:
      number: ${STATUS_PIN}
      inverted: true

output:
  - platform: gpio
    pin: 
      number: ${COMPRESSOR_OUTPUT}
      inverted: true
    id: compressor_out
  - platform: gpio
    pin: 
      number: ${FAN_OUTPUT}
      inverted: true
    id: fan_out
    
# switch:
#   - platform: output
#     output: fan_out
#     id: fan
#     name: ${DEVICE_NAME} Fan
#   - platform: output
#     output: compressor_out
#     id: compressor
#     name: ${DEVICE_NAME} Compressor
    
climate:
  - platform: bang_bang
    sensor: temp
    default_target_temperature_high: 25
    name: ${DEVICE_NAME} Thermostat
    id: therm

    cool_action:
      - output.turn_on: fan_out
      - delay: 10s
      - output.turn_on: compressor_out
    idle_action:
      - output.turn_off: compressor_out
      - delay: 60s
      - output.turn_off: fan_out

font:
  - file: 'slkscr.ttf'
    id: font1
    size: 8

  - file: 'bebas.ttf'
    id: font2
    size: 36
    glyphs: "0123456789°.-"

  - file: 'arial_narrow_7.ttf'
    id: font3
    size: 12
    glyphs: "0123456789°%.L:"
  
display:
  - platform: ssd1306_i2c
    model: "SH1106 128x64"
    address: 0x3C
    id: oled
    lambda: |-
      it.printf(64, 0, id(font1), TextAlign::TOP_CENTER, "${DEVICE_NAME}");
      
      it.printf(64, 0, id(font2), TextAlign::TOP_CENTER, "%.1f", id(temp).state);
      
      // Print target temperature
      it.printf(3, 52, id(font3), TextAlign::TOP_LEFT , "%.1f°", id(therm).target_temperature);
      
      // Print humidity
      if (id(hum).has_state()) {
        it.printf(42, 52, id(font3), TextAlign::TOP_CENTER , "%.0f%%", id(hum).state);
      }
      // Print lux
      if (id(lux).has_state()) {
        if (id(lux).state < 100) {
          it.printf(80, 52, id(font3), TextAlign::TOP_RIGHT , "%.0fLx", id(lux).state);
        } else if (id(lux).state < 1000) {
          it.printf(80, 52, id(font3), TextAlign::TOP_RIGHT , "%.0fL", id(lux).state);
        } else {
          it.printf(80, 52, id(font3), TextAlign::TOP_RIGHT , "%.0f", id(lux).state);
        }
      }
      
      // Print time in HH:MM format
      it.strftime(120, 52, id(font3), TextAlign::TOP_RIGHT, "%H:%M", id(homeassistant_time).now());
      
2 Likes