Air Quality Monitor

I wanted to monitor a variety of air characteristics around the house using a selection of cheap MQ-type sensors. These sensors don’t come calibrated and I don’t have the tools to calibrate them. But they could give me relative readings and feed them back into Home Assistant using ESPHome.

Case & Hardware

There are loads of MQ sensors but I picked an MQ-2 (gas leaks), MQ-7 (Carbon Monoxide), and MQ-135 (general air quality). I would like to add a CO2 sensor but these are bloody expensive.

I designed a 3D-printed case to hold four generic MQ sensor modules on their fairly standard-sized boards. They don’t all come with exactly the same PCB backing but most can be made to fit with minor mods to the mounting plate. This is made available as a separate STL file.

The case is deliberately very modular so you can choose your own variety of sensors. I also added in a DHT-22 to monitor temperature and humidity alongside the three MQs. It holds a NodeMCU on one of its base mounts that gives you a voltage regulator and breaks out the GPIO pins. The barrel jack from the NodeMCU base is exposed at the rear so you can power it with a standard PSU – 6-12V. There are also spaces for an Arduino Pro Mini to give you additional GPIO, and a level shifter module to take the NodeMCU’s 3v3 logic up to 5v. I also added in a strip of veroboard on mine to give more 5V/GND breakouts on some Dupont pins, and to hold some pull-up resistors. But what you need will depend on the sensors you use – and the microcontroller. Use something with 5V logic and you can do away with some of this.

The whole case is held together with just two M3 screws into threaded inserts in the base. I’m really pleased with the neatness and simplicity of this.

I built this many projects ago so this page has been assembled from a combination of memory, Fusion360 files, and what I can see looking inside the case, so forgive any holes in the information.

You can download the full set of STL files on Github.


This is my config file for ESPHome. You will need to follow the instructions for the Arduino port extender if you want to use the same hardware as me.

  name: gas_sensor
  platform: ESP8266
  board: nodemcuv2
  - arduino_port_expander.h

  ssid: "your_ssid"
  password: "your_password"
  use_address: air_monitor.local  

  # Enable fallback hotspot (captive portal) in case wifi connection fails
    ssid: "Air Monitor Fallback Hotspot"
    password: "your_password"


# Enable logging

# Enable Home Assistant API
  password: "your_password"

  password: "your_password"

# define i2c device
# for an ESP8266 SDA is D2 and goes to Arduino's A4
#                SCL is D1 and goes to Arduino's A5
  id: i2c_component

# define the port expander hub, here we define one with id 'expander1',
# but you can define many
  - id: expander1
    lambda: |-
      auto expander = new ArduinoPortExpander(i2c_component, 0x08, true);
      return {expander};

  - platform: status
    name: "Air Monitor Status"

# define analog sensors
  - platform: custom
    lambda: |-
      return {ape_analog_input(expander1, 1),  // 1 = A1
              ape_analog_input(expander1, 2),
              ape_analog_input(expander1, 3)};
      - name: MQ-7
        id: mq7
          # update every 60s
          - throttle: 60s
          # outputs between 0 and 5 volts - turn into percentage
          - lambda: return x *100/1023;
      - name: MQ-135
        id: mq135
          # update every 60s
          - throttle: 60s
          # outputs between 0 and 5 volts - turn into percentage
          - lambda: return x *100/1023;
      - name: MQ-2
        id: mq2
          # update every 60s
          - throttle: 60s
          # outputs between 0 and 5 volts - turn into percentage
          - lambda: return x *100/1023;
  - platform: wifi_signal
    name: "Air Monitor Wifi Signal"
    update_interval: 60s
  - platform: uptime
    name: "Air Monitor Uptime Sensor"
  - platform: dht
    pin: D4
    model: DHT22
      name: "Air Monitor Temperature"
      name: "Air Monitor Humidity"
    update_interval: 60s