Cooling the rooms my central air can't keep up with

Some links in this post are Amazon affiliate links. As an Amazon Associate I earn from qualifying purchases.

Comfort Masters walked my house, did the measurements, talked through duct balancing and a proper heat-load calculation, and handed me a number: $24,000 to fix the way my house cools.

The problem is real. A few rooms, mine worst of all, run hot no matter what my central air does, because the house has an overwhelming heat load. A balanced system sized to a real Manual J load is the correct answer. But $24,000 is a lot of correct, and I’m not ready to spend it today.

So I passed for now and kept running the central air I already have. To pick up the slack in the rooms it can’t keep cold on its own, I bought three Midea 12,000 BTU Duo portable air conditioners, around $400 each, and put Home Assistant in charge of them. I’d rather pay a bit more on the power bill every month than $24,000 up front.

Why my room is the hard case

My bedroom is the worst room in the house for this, and it has every excuse to be. It sits over an uninsulated garage, so the floor is whatever temperature the garage is. The windows are old single-pane aluminum, the siding is original, the house leaks air, and there isn’t enough insulation anywhere. The central air runs, but in summer this room soaks up heat from below and through the walls faster than one vent can pull it back out.

Fixing the envelope is a winter project: windows, siding, insulation, sealing up the garage ceiling. That’s the real answer the $24,000 quote was aimed at. Until then I’m brute-forcing comfort, which is exactly what a portable unit and some automation are good at.

The units

All three are the same Midea 12,000 BTU Duo. I bought mine at Costco, and right now they’re on sale there for $379.99 in store or $409 online. The same unit on Amazon is $619 as I write this, so the Costco price is the one to catch if you have a membership.

Here’s where they live:

  • Brandon room, my room, the priority. I want it cold at all times, including overnight.
  • Cat room upstairs. The network closet is inside this room’s closet, so cooling here protects my gear too.
  • Guest bedroom, on its own circuit, only needs a few short runs a day.

One physical constraint drives the whole design: the Brandon room unit and the cat room unit are on the same 20-amp circuit. They can’t both run at once. Start both compressors and the breaker trips. Everything below is built around never letting that happen.

Getting them into Home Assistant

These are Matter devices, so the join was painless. I added each one to the Apple Home app first, then shared it into Home Assistant over Matter using the new matter.js app and integration. No Midea cloud account, and nothing sitting in the middle that breaks when the vendor pushes new firmware.

Each unit shows up natively as a handful of entities:

  • A climate entity, the thermostat itself: off, cool, or fan only
  • A fan entity with low, medium, high, and auto speeds
  • A temperature sensor reading from the unit

The fan entity is the one that matters. I can set fan speed without touching the thermostat, and everything below depends on that.

A better sensor than the one in the AC

First thing I changed: I stopped trusting the temperature reading built into each AC. Those sensors sit right next to the cold-air intake, so they read low and jump around. Fine for the unit’s own thermostat, useless for deciding what the room actually feels like.

So I drive everything off dedicated room sensors instead. My room uses a Zooz ZSE44 temperature and humidity sensor, and the cat room, guest room, and network closet each have their own. Real room air, measured away from the cold blast. Every decision below reads from those, not from the AC.

Keeping my room cold without the fan hunting

A portable AC’s thermostat is crude. Set it to 70 and it cycles the compressor on and off around that number, and the room temperature swings with it. I didn’t want swings. So I set my unit to its minimum, 61 degrees, which means the compressor basically never reaches target and just runs continuously. Then I control comfort entirely with fan speed.

The first version flipped the fan up and down constantly. It would ramp down to low, then back to high a few minutes later, over and over. The problem was that my trigger points sat right inside the temperature range where the room normally hovers, so the smallest drift kept crossing a line.

The fix is a deadband. The fan rests on medium across a comfortable zone and only changes when the room really leaves it:

  • Above 70 degrees, fan goes high, and it reacts fast, after 2 minutes
  • 68 to 70 degrees, fan sits on medium, the normal resting state
  • Below 68 degrees, fan drops to low, but slowly, only after 10 minutes

Making the “drop the fan” decision deliberately slow is what killed the hunting. A brief cool dip isn’t enough to ramp down anymore. The room sits in its band and the fan barely moves.

The breaker interlock

This is the safety-critical piece. My room and the cat room can’t cool at the same time.

The rule is simple and absolute: if both units are ever in cool mode at once, the cat room unit switches off immediately. My room wins. The Midea units don’t report over Matter whether the compressor is actually drawing power, only what mode they’re in, so I treat “cool mode” as “drawing power” and never allow the overlap. It’s the conservative read, and I’d rather be conservative than go reset a breaker.

Cooling the network closet on demand

The network closet lives in the cat room’s closet, and networking gear makes heat. But the gear has its own fans, so I let it run warmer than a living space.

When the closet climbs above 87 degrees, or the cat room itself gets above 82, a separate automation kicks in:

  1. It turns my AC fully off first, freeing the 20-amp circuit.
  2. It runs the cat room unit on high, set to 72.
  3. It guarantees a protected 15-minute minimum so the closet actually gets cooled.
  4. After that it ends as soon as the closet drops back down, the cat room cools off, or my room creeps above 75 degrees, whichever comes first.
  5. Then it turns my AC back on and restores everything.

That fourth point is the one I care about most. Turning my own AC off for up to half an hour to cool a closet is a fine trade, right up until my room gets uncomfortable. So I automated the line I wasn’t willing to cross: if my room hits 75, the closet burst ends early and my cooling comes back, no matter what.

The guest room

The guest room is the easy one. It’s on a separate circuit, so it never threatens the breaker. It runs a 25-minute burst whenever its sensor reads above 79 degrees, and sends a notification to my phone reminding me to open the guest room door so the cool air spills into the upstairs living room. Temperature-driven, not on a clock, so it only runs when there’s a reason to.

Mr. Freeze mode

Sometimes I don’t want comfortable. I want cold. Movie night, a brutal afternoon, whenever.

So I built a button. One toggle in Home Assistant, which I can hit from a dashboard or say to Siri. When it turns on, it:

  • Drops the Ecobee to 68 to pull the whole house down
  • Runs my room and the guest room both on high
  • Starts a 2-hour timer so it can’t run all night by accident

While Mr. Freeze is on, the normal fan logic steps aside so my room stays pinned on high instead of politely ramping itself back down. When the timer runs out, or I flip it off, everything reverses: the Ecobee hold is cancelled so it returns to its schedule, the guest room shuts off, and my room goes back to its steady 61-and-modulate-the-fan routine.

I turned it on for a movie the other night. Within seconds the Ecobee was holding 68, both units were on high, and a notification told me it would shut itself off in two hours. That’s the whole point: a one-tap cold blast I don’t have to remember to undo.

The automations

There are three. AC Manager does the everyday work: the fan deadband, the breaker interlock, and the guest room burst, all keyed off trigger IDs. The burst cool automation handles the network closet. Mr. Freeze Mode is the on-demand override.

AC Manager:

alias: AC Manager
mode: parallel
max: 10
triggers:
  - alias: Brandon room above 70F for 2 min
    trigger: numeric_state
    entity_id: sensor.brandon_room_climate_air_temperature
    above: 70
    for: "00:02:00"
    id: fan_high
  - alias: Brandon room 68 to 70F for 5 min
    trigger: numeric_state
    entity_id: sensor.brandon_room_climate_air_temperature
    above: 68
    below: 70
    for: "00:05:00"
    id: fan_medium
  - alias: Brandon room below 68F for 10 min
    trigger: numeric_state
    entity_id: sensor.brandon_room_climate_air_temperature
    below: 68
    for: "00:10:00"
    id: fan_low
  - alias: Brandon AC switched to cool (init fan)
    trigger: state
    entity_id: climate.brandon_ac
    to: cool
    id: fan_init
  - alias: Cat Room AC switched to cool (interlock)
    trigger: state
    entity_id: climate.cat_room_upstairs_ac
    to: cool
    id: interlock
  - alias: Brandon AC switched to cool (interlock)
    trigger: state
    entity_id: climate.brandon_ac
    to: cool
    id: interlock
  - alias: Guest room above 79F for 5 min
    trigger: numeric_state
    entity_id: sensor.guest_room_temperature
    above: 79
    for: "00:05:00"
    id: guest
actions:
  - choose:
      - alias: Hot, set Brandon fan to high
        conditions:
          - condition: trigger
            id: fan_high
          - condition: state
            entity_id: input_boolean.mr_freeze_mode
            state: "off"
        sequence:
          - action: fan.set_preset_mode
            target:
              entity_id: fan.brandon_ac
            data:
              preset_mode: high
      - alias: Comfortable, set Brandon fan to medium
        conditions:
          - condition: trigger
            id: fan_medium
          - condition: state
            entity_id: input_boolean.mr_freeze_mode
            state: "off"
        sequence:
          - action: fan.set_preset_mode
            target:
              entity_id: fan.brandon_ac
            data:
              preset_mode: medium
      - alias: Cool, set Brandon fan to low
        conditions:
          - condition: trigger
            id: fan_low
          - condition: state
            entity_id: input_boolean.mr_freeze_mode
            state: "off"
        sequence:
          - action: fan.set_preset_mode
            target:
              entity_id: fan.brandon_ac
            data:
              preset_mode: low
      - alias: Init Brandon fan when AC turns on
        conditions:
          - condition: trigger
            id: fan_init
          - condition: state
            entity_id: input_boolean.mr_freeze_mode
            state: "off"
        sequence:
          - choose:
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.brandon_room_climate_air_temperature
                    above: 70
                sequence:
                  - action: fan.set_preset_mode
                    target:
                      entity_id: fan.brandon_ac
                    data:
                      preset_mode: high
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.brandon_room_climate_air_temperature
                    above: 68
                sequence:
                  - action: fan.set_preset_mode
                    target:
                      entity_id: fan.brandon_ac
                    data:
                      preset_mode: medium
            default:
              - action: fan.set_preset_mode
                target:
                  entity_id: fan.brandon_ac
                data:
                  preset_mode: low
      - alias: Breaker interlock, Brandon wins, Cat Room off
        conditions:
          - condition: trigger
            id: interlock
          - condition: state
            entity_id: climate.brandon_ac
            state: cool
          - condition: state
            entity_id: climate.cat_room_upstairs_ac
            state: cool
        sequence:
          - action: climate.set_hvac_mode
            target:
              entity_id: climate.cat_room_upstairs_ac
            data:
              hvac_mode: "off"
      - alias: Guest room 25-min cooling burst
        conditions:
          - condition: trigger
            id: guest
        sequence:
          - action: climate.set_hvac_mode
            target:
              entity_id: climate.guest_bedroom_guest_room_ac
            data:
              hvac_mode: cool
          - action: climate.set_temperature
            target:
              entity_id: climate.guest_bedroom_guest_room_ac
            data:
              temperature: 70
          - action: fan.set_preset_mode
            target:
              entity_id: fan.guest_bedroom_guest_room_ac
            data:
              preset_mode: high
          - action: notify.mobile_app_brandon_iphone
            data:
              title: Guest room cooling
              message: >-
                Guest room is above 79F, AC running 25 min. Open the guest room
                door to push cool air into the upstairs living room.
          - delay: "00:25:00"
          - action: climate.set_hvac_mode
            target:
              entity_id: climate.guest_bedroom_guest_room_ac
            data:
              hvac_mode: "off"

The network closet burst, in its own automation so it can’t tangle with the everyday fan logic:

alias: Cat Room / Network Closet burst cool
mode: single
triggers:
  - alias: Network closet above 87F for 5 min
    trigger: numeric_state
    entity_id: sensor.network_closet_temperature
    above: 87
    for: "00:05:00"
    id: closet
  - alias: Cat room above 82F for 5 min
    trigger: numeric_state
    entity_id: sensor.cat_room_temperature
    above: 82
    for: "00:05:00"
    id: catroom
actions:
  - alias: Turn Brandon AC off (free the 20A circuit)
    action: climate.set_hvac_mode
    target:
      entity_id: climate.brandon_ac
    data:
      hvac_mode: "off"
  - delay: "00:00:05"
  - action: climate.set_hvac_mode
    target:
      entity_id: climate.cat_room_upstairs_ac
    data:
      hvac_mode: cool
  - action: climate.set_temperature
    target:
      entity_id: climate.cat_room_upstairs_ac
    data:
      temperature: 72
  - action: fan.set_preset_mode
    target:
      entity_id: fan.cat_room_upstairs_ac
    data:
      preset_mode: high
  - alias: Protected 15-min minimum run
    delay: "00:15:00"
  - alias: Wait until satisfied or Brandon room hits 75F (max 15 more min)
    wait_for_trigger:
      - trigger: numeric_state
        entity_id: sensor.network_closet_temperature
        below: 80
      - trigger: numeric_state
        entity_id: sensor.cat_room_temperature
        below: 76
      - trigger: numeric_state
        entity_id: sensor.brandon_room_climate_air_temperature
        above: 75
    timeout: "00:15:00"
    continue_on_timeout: true
  - action: climate.set_hvac_mode
    target:
      entity_id: climate.cat_room_upstairs_ac
    data:
      hvac_mode: "off"
  - action: climate.set_hvac_mode
    target:
      entity_id: climate.brandon_ac
    data:
      hvac_mode: cool
  - action: climate.set_temperature
    target:
      entity_id: climate.brandon_ac
    data:
      temperature: 61

And Mr. Freeze, which is just an input_boolean plus a timer:

alias: Mr Freeze Mode
mode: queued
max: 5
triggers:
  - alias: Mr Freeze turned on
    trigger: state
    entity_id: input_boolean.mr_freeze_mode
    to: "on"
    id: activate
  - alias: Mr Freeze turned off
    trigger: state
    entity_id: input_boolean.mr_freeze_mode
    to: "off"
    id: deactivate
  - alias: Mr Freeze timer finished
    trigger: event
    event_type: timer.finished
    event_data:
      entity_id: timer.mr_freeze
    id: timer_done
actions:
  - choose:
      - alias: Activate, max cooling
        conditions:
          - condition: trigger
            id: activate
        sequence:
          - action: climate.set_temperature
            target:
              entity_id: climate.ecobee
            data:
              temperature: 68
          - action: climate.set_hvac_mode
            target:
              entity_id: climate.brandon_ac
            data:
              hvac_mode: cool
          - action: fan.set_preset_mode
            target:
              entity_id: fan.brandon_ac
            data:
              preset_mode: high
          - action: climate.set_hvac_mode
            target:
              entity_id: climate.guest_bedroom_guest_room_ac
            data:
              hvac_mode: cool
          - action: climate.set_temperature
            target:
              entity_id: climate.guest_bedroom_guest_room_ac
            data:
              temperature: 70
          - action: fan.set_preset_mode
            target:
              entity_id: fan.guest_bedroom_guest_room_ac
            data:
              preset_mode: high
          - action: timer.start
            target:
              entity_id: timer.mr_freeze
          - action: notify.mobile_app_brandon_iphone
            data:
              title: Mr Freeze on
              message: >-
                Ecobee set to 68F, Brandon + Guest rooms on high. Auto-ends in
                2h or when you turn it off.
      - alias: Timer done, turn Mr Freeze off
        conditions:
          - condition: trigger
            id: timer_done
        sequence:
          - action: input_boolean.turn_off
            target:
              entity_id: input_boolean.mr_freeze_mode
      - alias: Deactivate, restore normal cooling
        conditions:
          - condition: trigger
            id: deactivate
        sequence:
          - action: timer.cancel
            target:
              entity_id: timer.mr_freeze
          - action: ecobee.resume_program
            target:
              entity_id: climate.ecobee
            data:
              resume_all: true
          - action: climate.set_hvac_mode
            target:
              entity_id: climate.guest_bedroom_guest_room_ac
            data:
              hvac_mode: "off"
          - action: climate.set_hvac_mode
            target:
              entity_id: climate.brandon_ac
            data:
              hvac_mode: cool
          - action: climate.set_temperature
            target:
              entity_id: climate.brandon_ac
            data:
              temperature: 61
          - choose:
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.brandon_room_climate_air_temperature
                    above: 73
                sequence:
                  - action: fan.set_preset_mode
                    target:
                      entity_id: fan.brandon_ac
                    data:
                      preset_mode: high
              - conditions:
                  - condition: numeric_state
                    entity_id: sensor.brandon_room_climate_air_temperature
                    above: 69
                sequence:
                  - action: fan.set_preset_mode
                    target:
                      entity_id: fan.brandon_ac
                    data:
                      preset_mode: medium
            default:
              - action: fan.set_preset_mode
                target:
                  entity_id: fan.brandon_ac
                data:
                  preset_mode: low

The math

Let me be honest about the running cost, because my first guess was way too low.

One of these units pulls up to 11.9 amps, about 1.4 kW at the wall. Mine runs close to around the clock. Call it a conservative 1.2 kW on average: 1.2 kW times 24 hours times 30 days is roughly 860 kWh a month for that one unit. Residential power around here runs about 16 cents a kWh right now and climbs in summer, so my room alone is somewhere near $140 a month when it’s hot. The other two run in bursts, so add maybe $40 to $80 on top. And this is on top of the central air I’m already running, not instead of it. Realistically the portables cost me $150 to $250 a month in the worst summer months, not the $50 to $100 I first assumed.

Now the up-front side. Three units at the Costco price is about $1,150, against the $24,000 quote to fix it properly. Even if the portables cost me an extra $250 every single month, all year, that’s $3,000 a year, and it would still take the better part of a decade to spend the difference, and they won’t cost that in winter. By then I’ll have either chipped away at the windows and insulation myself or saved up for the real system on my own schedule.

A $24,000 system is the right call if you want it done once and never think about it again. I’d rather keep the money for now, run three cheap boxes hard, and let the automations hold comfort right where I sit until I get to the windows and insulation.

← All posts