Monday, July 15, 2019

Internet of things air conditioning

The last few summers have gotten warm enough here in the Pacific Northwest that we got ourselves a free-standing AC unit, but even it can't really keep up for me. Most summer nights, it's cool enough outside, but the house retains enough heat that we have to ventilate. While Andrea and the boys were in Minnesota these last two weeks, I decided to get around to a project I'd been rolling around for a while: automate the monitoring of inside and outside temperatures, and when it's cool enough outside, kick on one fan for intake and one for exhaust.

Bill of materials

Making the temperature sensor

The first step was, compared to my kegerator project, significantly simpler. My DHT11 sensor already has its pull-up resistor built-in, so wiring this up was little more than connecting ground-to-ground, voltage-to-voltage, and one-pin to a somewhat arbitrary GPIO. Had the microcontroller not come with header pins, I probably could have done away with the PCB.

I played around with getting this working on a breadboard before soldering it up, but this whole process was the least interesting of the whole project, so I'm omitting this info. At the end, I had a component that looks like so:

I had planned to flash the NodeMCU to use MicroPython, but it ended up being a fairly significant pain in the ass to do, and it turns out you can make wifi, temperature readings, and MQTT messages work in just under 60 lines of C code (and C is far from my strong suit). The DHT11 can apparently read at 0.5 Hz (one reading per two seconds), but this is far faster than I need, so I configured it to take a reading every minute.

I already had Home Assistant running on one of my laptops with an MQTT broker, so plugging this sensor into the wall and letting it sit for a while gives me the temperature over time inside our house:

I put this sensor in the boys' room because that's the place I want to make sure is properly climate-controlled.

Next, I debated how to deal with a second temperature sensor outside. Our backyard is on the south side of the house, and it can get a lot of sun. A sensor sitting out there could bake in the sun and get ruined. The front of the house would be protected from that, but there's only one outlet, and it's in a rather inconvenient place.

I decided instead to make an API call to OpenWeatherMap. Their data are updated every ten minutes or so. Having lower time granularity is no big deal to me, and they provide a lot more data than I'd get with a DHT11 and at no cost, to boot. So I setup a cron job to run every ten minutes, publishing the temperature to my MQTT topic. Another 40 lines of code, this time in Python.

Again with the data, but this time, I'm doing a ten minute average of my own sensor with the external data overlaid:

While I've had Home Assistant installed, I haven't been doing much with it, and I've found their nomenclature and configuration to be pretty wonky, and the UI is jarring as well, making it pretty hard to figure out. It took some time, but I was able to get two of my smart switches setup thanks to a contributed VeSync component for Home Assistant. There are certainly some kinks to work out, though I'm not sure if it's with VeSync or with Home Assistant's Lovelace UI. I renamed my switches for this project, yet they're still showing up with some default values:


 No matter. I'm not using the UI for this, anyway. I added a new automation in my automations.yaml to, kick on both smart switches when HomeAssistant receives an MQTT message to the "ventilate" topic with payload "on". Similar for turning it off. From a console, I could turn on and off the fans with a simple command:
$ mosquitto_pub -h localhost -t ventilate -m "on"
$ mosquitto_pub -h localhost -t ventilate -m "off"
The final piece was to automatically send this message under the right circumstances. There's more code to my script, as it's handling both DHT11 and OpenWeatherMap MQTT messages, but the relevant code for comparing recent inside/outside temps is here. Basically, if it's at least five degrees cooler outside than inside, it'll start ventilating. If it's the same temp or warmer outside as inside, it stops. I also added some time bounds so we're not running a rather loud fan in the morning when we're enjoying each others' company.

VoilĂ  ! I have yet to measure how effective this setup is for actually cooling the house, but for a paltry $25 or so and a few hours of time, I'm rather excited by what I find.