Home Assistant Air Quality Monitors from IKEA Vindriktning

IKEA recently discontinued Vindriktning, their older air quality monitor.

Inside the device, they put a cubic PM1006K particle sensor. I bought three for $16.95 each last year, because I’d seen people hack them by adding sensors and a Wi-Fi microcontroller to send all of the data to Home Assistant. For my modding I bought:

The YouTube video linked above is a great guide to follow. I didn’t connect wires to the fan or the light sensor since I had no use for them. I also didn’t stack my sensors because I wanted the BME280 to be outside of the enclosure, where it would be less affected by the heat produced by the ENS160 and D1.

Even with the sensor outside of the case, the BME280 still reads high, because it heats itself up. I actually tested different lengths of wires and placements of the sensor before realizing I was still going to have to adjust the data. An ESPHome filter made the adjustment easy, which I did individually for each unit after comparing to a mobile Ecobee thermostat sensor. This is the code from the unit for my shop.

substitutions:
  slug: shop
  friendly: Shop

esphome:
  name: ${slug}-air-quality
  friendly_name: ${friendly} Air Quality

esp8266:
  board: d1_mini

logger:
  level: WARN

api:
  encryption:
    key: 'xxx'

ota:
  - platform: esphome
    password: 'xxx'

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: xxx
    gateway: xxx
    subnet: 255.255.255.0

i2c:
  frequency: 100kHz

uart:
  - rx_pin: D7
    baud_rate: 9600

sensor:
  - platform: pm1006
    pm_2_5:
      name: PM 2.5µm

  - platform: bme280_i2c
    address: 0x76
    temperature:
      name: Temperature
      id: ${slug}_temp
      filters:
        - offset: -3.38
    humidity:
      name: Humidity
      id: ${slug}_humid
      filters:
        - offset: 7.63
    iir_filter: 16x

  - platform: aht10
    variant: AHT20
    temperature:
      name: AHT21 Temperature
      id: ${slug}_aht21_temp
    humidity:
      name: AHT21 Humidity
      id: ${slug}_aht21_humid

  - platform: ens160_i2c
    address: 0x53
    eco2:
      name: CO²
    tvoc:
      name: VOC
    aqi:
      id: ${slug}_aqi
      name: AQI
    compensation:
      temperature: ${slug}_aht21_temp
      humidity: ${slug}_aht21_humid

text_sensor:
  - platform: template
    name: AQI Rating
    lambda: |-
      switch ( (int) ( id( ${slug}_aqi ).state ) ) {
        case 1: return {"Excellent"};
        case 2: return {"Good"};
        case 3: return {"Moderate"};
        case 4: return {"Poor"};
        case 5: return {"Unhealthy"};
        default: return {"N/A"};
      }

These resources were a huge help when I wired everything up and made changes to the YAML code:

Here is how I’m displaying the data on one of my Home Assistant dashboards.

As I was working on this project I knew I wanted a couple more air quality monitors around the house, which will be finished soon.

Update: I’ve had to make a small update by adding a 47uF capacitor to each ENS160 board, because they have power issues, causing the reading to stop for periods of time. My boards matched up with the right ones in the picture at that link. Here’s a picture of another ENS160 I modified, since it was a tight squeeze to made the modification on the devices I posted about here with everything already wired up. I also realized I was powering these through the 3V3 pin instead of VIN, so I fixed that.

I’ve also improved the display of the data on my dashboard by using mini-graph-card.

Creating an ESPHome Remote Control Device with Infrared & Radio Frequency

In order to automate the processes of getting the golf sim ready to play and shutting it all down when finished I needed to create a remote control device. I’m using Home Assistant (HA) to run my home smart system (more posts to come), but two things involved with the golf sim aren’t connected to the network:

The projector has an infrared (IR) remote and the light has a radio frequency (RF) remote. I’ve done some things with IR and still had a stash of IR LEDs (for transmitting) and receivers. I’ve never attempted any RF stuff, so I ordered a 5 pack of 433mhz wireless RF transmitter and receiver pairs.

Since I’m using HA, I let ESPHome handle all of the main programming. All I had to do was wire everything properly and get the configuration correct. I made use of an old ESP8266 NodeMCU microcontroller and worked on the IR aspect of the project first.

When I took the picture I was using a 470Ω resistor, which I eventually switched to 100Ω, to increase the strength of the IR signal. The transistor is a PN2222A. Here’s the ESPHome configuration:

esphome:
  name: golf-remote
  friendly_name: Golf Remote

esp8266:
  board: nodemcuv2

logger:

api:
  encryption:
    key: "xxxxxxxxxx"

ota:
  - platform: esphome
    password: "xxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: x.x.x.x
    gateway: x.x.x.x
    subnet: 255.255.255.0

remote_receiver:
  - id: GOLF_IR_RX
    pin:
      number: D1
      inverted: True
      mode:
        input: True
        pullup: True
    dump: all

remote_transmitter:
  - id: GOLF_IR_TX
    pin: D2
    carrier_duty_percent: 50%

I used the receiver to intercept the codes sent by the projector’s actual remote when pressing the Power, Input, and OK buttons. Then I created some buttons.

button:
  - platform: template
    name: Projector Power
    on_press:
      - remote_transmitter.transmit_nec:
          transmitter_id: GOLF_IR_TX
          address: 0x3000
          command: 0xFD02
  - platform: template
    name: Projector Input
    on_press:
      - remote_transmitter.transmit_nec:
          transmitter_id: GOLF_IR_TX
          address: 0x3000
          command: 0xFB04
  - platform: template
    name: Projector OK
    on_press:
      - remote_transmitter.transmit_nec:
          transmitter_id: GOLF_IR_TX
          address: 0x7788
          command: 0xE619

It all went very smooth. Next I connected the circuits for the RF components, which was straightforward. Here are the pinouts from the Amazon product page.

I soldered on the antennas (smaller one to the transmitter) and connected everything on the breadboard.

By using examples from the documentation I was able to intercept RF codes.

When I tried to recreate those codes through the transmitter the results weren’t matching up and the spotlight wasn’t responding. It took some trial and error to configure the various parameters of the receiver. Here’s the end result, with the combined configuration for IR and RF.

esphome:
  name: golf-remote
  friendly_name: Golf Remote

esp8266:
  board: nodemcuv2

logger:

api:
  encryption:
    key: "xxxxxxxxxx"

ota:
  - platform: esphome
    password: "xxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: x.x.x.x
    gateway: x.x.x.x
    subnet: 255.255.255.0

remote_receiver:
  - id: GOLF_IR_RX
    pin:
      number: D1
      inverted: True
      mode:
        input: True
        pullup: True
    dump: all
  - id: GOLF_RF_RX
    pin:
      number: D6
      mode:
        input: True
        pullup: True
    dump:
      - rc_switch
    tolerance: 50%
    filter: 250us
    idle: 4ms
    buffer_size: 2kb # only for ESP8266

remote_transmitter:
  - id: GOLF_IR_TX
    pin: D2
    carrier_duty_percent: 50%
  - id: GOLF_RF_TX
    pin: D6
    carrier_duty_percent: 100%

After using the remote_receiver instances to get the button press codes I needed, I commented out that section of the code. If I ever need to add more functionality to my remote, I can enable the receivers at that point. Here are the button codes for the spotlight.

  - platform: template
    name: Spotlight On
    on_press:
      - remote_transmitter.transmit_rc_switch_raw:
          transmitter_id: GOLF_RF_TX
          code: '111001000000100100000011'
          protocol: 1
          repeat:
            times: 10
            wait_time: 0s
  - platform: template
    name: Spotlight Off
    on_press:
      - remote_transmitter.transmit_rc_switch_raw:
          transmitter_id: GOLF_RF_TX
          code: '111001000000100100000001'
          protocol: 1
          repeat:
            times: 10
            wait_time: 0s
  - platform: template
    name: Spotlight Green
    on_press:
      - remote_transmitter.transmit_rc_switch_raw:
          transmitter_id: GOLF_RF_TX
          code: '111001000000100100000111'
          protocol: 1
          repeat:
            times: 10
            wait_time: 0s

Then I was able to use both sets of buttons in scripts, which can feed to Alexa for voice commands.

Once everything was tested I wired and soldered a more permanent circuitboard. I included a folded dollar bill for scale.

I was planning to mount it in the ceiling, but the IR was having trouble, because the projector’s receiver faces the ground. Mounting it to the side of the PC cart worked great.

This was a lot of fun!

Update: Less than a week later I’ve already modified it, by adding a DHT22, which reports temperature and humidity. Might as well use that empty D7 pin on the microcontroller.

Home Automation Part 2: Software

Part 1 covered the devices I’m using for home automation. It’s been over a year and there have been some changes. I added a Leviton switch and got rid of the Wink hub.

This post will be about the software that brings things together, making it easy for me to manage and allows the devices to “talk” to each other. Maybe it’s a good thing it’s taken me almost a year to write this part 2 because there have been some dramatic improvements to how everything runs. I was using homebridge for a period of time, but found I never really used HomeKit/Siri. Home Assistant has been updating a new HomeKit component, so I’ll have to give it a try.

I’ve talked about Home Assistant in a lot of posts; it’s the software running on the Raspberry Pi 3 Model B to handle everything. It’s very powerful software and has been a lot of fun for me to configure everything. Being on a Linux box and having to configure everything through YAML files makes it a tough entry for the average homeowner though. It’s improved a lot in the year I’ve been using it with better documentation and some UI configuration tools, so it’ll be interesting to watch for the next 12 months.

Being Open Source was a big draw of HA for me. Open Sourcecraft has a good article about the creator. The project operates on an aggressive schedule you don’t see much; every 2 weeks a new version oh Home Assistant is released. These aren’t small updates either. Each update fixes a ton of bugs and adds support for new devices.

I did install HA using Hass.io, which simplifies the process and makes it easy to do upgrades and install add-ons. Here are the add-ons I’m using.

ha-hassio-add-ons.png

In addition to running Home Assistant, I wrote a couple of small services I run on Pis. The first is the temperature sensor/monitor I use in my garage. I’ve improved it a lot in the last year. The second service is home-assistant-pi, which reports a bunch of data about each Raspberry Pi on my network back to Home Assistant, which you’ll see in the screenshot below.

The beauty of Home Assistant is you can set everything up the way you want. Your limitation is your imagination and your comfort level with configuration files and code. I took a bunch of screenshots of my setup.

ha-day-home.png
The main screen, with a daytime theme active.

ha-night-home
The same screen, but at night.

ha-night-temps
All of the weather and indoor climate data.

ha-night-pis
Status of my Raspberry Pis.

ha-night-rooms
Groupings by room.

ha-night-multimedia
Sort of a multimedia group, showing my TVs and cameras.

ha-night-sensors
A catchall sensor screen with less frequently used info.

img_0757
The iOS app gives access to everything and works the same way.

I keep all of my configuration (except the secrets file) in a GitHub repo in case I mess something up. I’ve learned a lot by looking at other examples, so my repo is public as well. Maybe my config will help out someone else. The repo is home-assistant-config. If you have any questions about anything you see in this post or in my configuration, let me know.

In the final post of this series, I’ll explain the cool part of this whole thing, the actual automations. I need to go through my ideas list and implement all of them though.

From Rest API to MQTT

After the recent changes to my home network and Home Assistant server, I noticed the logs in Pi-Hole were being dominated by the domain I use for dynamic DNS on the box. Roughly 15,000 DNS requests a day out of 30,000 on my entire network. Really skews the ad blocking stats.

Why so many DNS requests? Because home-assistant-pi and home-assistant-temperature-monitor were both using the Home Assistant REST API to fetch data. That’s 15k requests/day with only two of my seven other Raspberry Pis turned on, so it would get worse when I put some of the other Pis into “production” around the house. The temperature project only runs on one box, but the first project in installed on every Pi.

I briefly tried to switch those two projects over to using the local IP address of the server and continue to use the REST API, but with SSL enabled it was complicated. MQTT was already running on the server and those projects publish updates to Home Assistant over MQTT, so it was an easy decision to use it for subscribing as well.

While I was at it, I took the opportunity to simplify a lot of the code and have the devices update more frequently. So far it seems to have solved a couple of lingering stability or connection issues I was having with home-assistant-pi. All of the code changes are available in the respective GitHub repos linked earlier.

Update: I forgot I had home-assistant-pi connecting to google.com in to help with determining the local IP address in Python. Another update to clear that up will eliminate over five thousand DNS requests per day.

Home Network Updates

My router had been flaking out, so I picked up a Eero with 1 beacon. Setup was smooth and painless. I decided to use a new Wi-Fi network name, which was not one of my best ideas; reconfiguring about 30 devices was a pain in the ass!hass-io-install

While I was working on my network I took the opportunity to do a fresh install of everything on the Raspberry Pi server running Home Assistant and Pi-Hole. Instead of installing Raspbian and all of the software myself,  I took advantage of Hass.io, which is a preconfigured image and works well. When I first started using Home Assistant, the project was pretty immature so I didn’t use it.

Installing Pi-Hole as a Hass.io add-on is slick. Due to issues with my old router I’d been living without ad blocking for a few weeks and it was horrible. It’s hard going back to a web littered with ads when you’ve been living without them.

Figured I might as well keep going, so I also made a bunch of improvements to the Raspberry Pi Temperature Monitor I use in my garage. Seems to run much more stable, which may also have something to do with the fresh Home Assistant install. Changed a few things with home-assistant-pi as well.

Another big change I made to the server is connecting it to my network via ethernet instead of WiFi. It’s wired in through an AirPort Time Capsule, which is connected to the Eero via a really long cable running through the basement. I bet this has done more than anything to improve the stability and consistency of my system. A bonus of this connection change is the Speedtest reporting inside HA is much more accurate.

Now I need to make time to get more automating done in Home Assistant and publish part 2 and 3 of my home automation series. It’s coming up on a year since part 1, so long overdue.

Updates to Home Assistant Projects

My garage temp sensor, running home-assistant-temperature-monitor stopped working several months ago. I didn’t have time to figure it out and then summer hit, when it’s not important since I don’t heat up the garage before I workout. This weekend I finally got around to troubleshooting the problem.

Turned out I needed to install Adafruit_Python_GPIO. I must have updated my code at some point without fully testing, otherwise I’m not sure how any of it worked before. I didn’t investigate that though; I was more concerned with fixing it and doing some improvements. I updated the OS and everything on the Raspberry Pi since it hadn’t been turned on in quite some time.

Earlier this year, another Pi on my network, the one running Home Assistant and Pi-hole, ran out of disk space without warning. I’ve wanted to put in a notification system so it never happens again, so I updated home-assistant-pi to report the disk use % to HA. I added an automation to notify me whenever it’s above 90% for one of my Pis. I also reworked all of the automations in home-assistant-pi to make it easier to configure each time I get a new Pi.

img_9705

That all took much longer than I expected. Most of the trouble was trying to understand the Jinja template system used in HA and where it can be applied to configurations. I think I’m finally getting the hang of it.

While writing this post, I found an old draft with some other updates to home-assistant-pi I never published. Maybe I never finished and that’s why everything stopped working! Here’s a list of some previous updates:

  • Fixed errors causing program to crash.
  • It wasn’t reconnecting very well, especially if Home Assistant went away (ex. for a restart after an upgrade). Rewrote how the MQTT connection works.
  • Switch from PushBullet to iOS notifications.
  • Changed show/hide Home Assistant group automations.

Now that this stuff is running again and I have a better understanding of the Home Assistant automation capabilities, I need to continue the series of posts I planned on home automation. It’s been five and a half months since I published Part 1!

Home Assistant Pi

With all of the Raspberry Pis I have (now up to 6 after adding “flapper”), I wanted to get a bunch of data in Home Assistant (yes, I’m still working on a larger home automation post) and have an easy way to reboot or shutdown each computer.

I wrote a little app which runs as a service on each Pi. Here’s an example of what shows up in Home Assistant.

home-assistant-pi-groups.png

The Python app and sample Home Assistant configurations are in my home-assistant-pi project on GitHub. Of course it’s all Open Source.

Garage Monitor Updates

I made some updates to the Garage Temperature Sensor & Monitor. I didn’t like how the desired temperature was set via the app’s configuration file, so I moved it to a slider control in Home Assistant and updated the LCD to always show the value. Only being able to enable/disable monitoring via the device’s button also wasn’t great. I converted the binary sensor I was using to flag monitor mode in HA to a switch control and moved the actual monitoring logic from the Python app to HA automation. Everyhing is updated on GitHub.

updated-garage-monitor-ha.png
Info and controls in Home Assistant

img_8761
Custom temperature and humidity monitor

Garage Temperature Sensor & Monitor

I’ve been working on this project here and there for a few weeks, with most of the early work being experimentation. Everything is now up and running and it’s “deployed to production” so to speak. This was my prototyping setup…

After wiring everything together and repurposing a cardboard box, here is a short video to show the final product.

A few notes on how it works:

  • The button toggles monitor mode. The LED inside the button indicates if Monitor mode is on/off.
  • When monitor mode is on and the desired temperature is reached, I get a notification.
  • I should have shown the knob, but all it does is adjust the LCD’s contrast.
  • The thing on the top left of the box is the sensor chip for reading temperature and humidity. Originally it was inside the box behind a little window there but it was picking up too much heat from the Pi and LCD in there.
  • The backlight color of the LCD is based on the measured temperature and updates each time new temperature is read. Anything 32° Farenheit and below is blue, 80° and above is red, and everything in between is based on where it falls within that 32-80 range. As you can see in the example, 48° is a lighter blue. A few degrees warmer and I think it would have started to look more green.
  • Outside temperature/humidity is pulled in from the Dark Sky data in my Home Assistant setup (which I’ll post about soon).
  • Data is sent to Home Assistant via MQTT.

home-assistant-garage.png

Really happy with how things turned out. The Pi  I wrote this in Python and it’s all available as home-assistant-temperature-monitor on GitHub if you want to make your own or use some of the code for your own project. There is also a list of all the components used.

Here are some pictures I took while assembling the enclosure/box.

Making sure the Pi and attached Hat fit right after drilling the holes. Seemed like there was so much room at this point.

img_8663
Everything soldered to the HAT. Amazingly I didn’t make any mistakes and everything worked on the first try. A good prototyping setup, having pictures of my final prototype, and keeping a list of where everything connected was invaluable.

The Raspberry Pi, Hat, LCD, USB cables to power and WiFi, and all of the other wiring jammed in! Reaching inside to get things screwed through the box wasn’t easy.

There is a lot more room in the other part of the box where the sensor, button, and knob are. Nice for the WiFi adapter and cable to come across and have some room.

Update: Adafruit released a new Learn guide that does some similar stuff to this project.