Aloe Ninja

MQTT Indoor Air Quality Sensor

Device for indoor air quality control

Sensor Exterior

This extremely simple device measures temperature, humidity, pressure, carbon dioxide and volatile organics in the air and sends the data to the MQTT broker.

Based on this data, other devices in our IoT network will be able to perform appropriate actions, such as turning on ventilation or a humidifier. But we will simply display them in a dashboard.


Sensor Components

  • ESP-12F module
  • CJMCU-8128 module
  • Double sided breadboard 70x30
  • Resistor 4.7k
  • Linear stabilizer LM1117–3.3
  • Capacitors 10uF and 0.1uF, two each
  • Breakout with micro-USB connector.
  • Mounting wire
  • Optional 3D printed housing and M3x10 screws with nuts
  • Optional LED and resistor ~220

To flash the module, you will need a USB-UART converter with an output high logic level of 3.3V and a pair of temporary buttons for connecting to the RESET and FLASH pins.


Power Stablilizer

Air sensor circuit


Traditionally, for such devices, I prefer not to fool around with LUT or order boards at the factory, but quickly sculpt on a breadboard to the best of my mad skills. Therefore, we will not dwell on this in detail. Need. Just. Connect. Everything. By. Scheme.

It should turn out something like this:

Air sensor PCB 0


The CJMCU-8182 module consists of three sensors connected to the I2C bus - CCS811, BMP280 and SI7021.

For their work, you need to download to the library project directory:

We also place the main firmware files there.


import gc
import network
import esp

essid = "yourWiFiSSID"
password = "yourWiFiPassword"


server = ""
port = 19780
mqttuser = "mqttlogin"
mqttpwd = "MQttPassWord123"

TOPIC_PREFIX = 'sensor0/'
import machine
import time
import ntptime
import ubinascii
from umqtt.simple import MQTTClient
import bmp280
from ccs811 import CCS811
from si7021 import Si7021
from config import *

def initmqtt():
    client_id = ubinascii.hexlify(machine.unique_id())
    client = MQTTClient(client_id, server, port, mqttuser, mqttpwd)
    print("MQTT Connected")
    return client

def connect():
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print("Connecting to {}...".format(essid))
        sta_if.connect(essid, password)
        while not sta_if.isconnected():
    print("Network config:", sta_if.ifconfig())


rtc = machine.RTC()
    print('Error setting time')

    client = initmqtt()
    print('Error initializing MQTT')

sec = time.time() + TIMEZONE * 3600
localtime = time.localtime(sec)

i2c = machine.I2C(scl=machine.Pin(5), sda=machine.Pin(4), freq=400000)

data = {}

ccs = CCS811(i2c=i2c, addr=0x5a)
si = Si7021(i2c, address=0x40)
bmp = bmp280.BMP280(i2c, addr=0x76)
bmp.power_mode = bmp280.BMP280_POWER_NORMAL
bmp.temp_os = bmp280.BMP280_TEMP_OS_8
bmp.press_os = bmp280.BMP280_PRES_OS_16
bmp.standby = bmp280.BMP280_STANDBY_500
bmp.iir = bmp280.BMP280_IIR_FILTER_16

data['eCO2'] = str(ccs.eCO2)
data['tVOC'] = str(ccs.tVOC)

data['t0'] = str(round(si.temperature, 2))
data['h0'] = str(round(si.relative_humidity, 2))

data['t1'] = str(bmp.temperature)
data['p0'] = str(round(bmp.pressure / 133.32, 2))

for val in data:
    print(TOPIC_PREFIX + val, data[val])
        client.publish(TOPIC_PREFIX + val, data[val], retain=True)

rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
rtc.alarm(rtc.ALARM0, time.ticks_ms() + 300*1000)
print('Entering deepsleep')

In a previous article, I talked about how to install and configure an MQTT broker. The sensor will be connected to it, so the connection parameters are the same.

Do I need to say that you need to specify your addresses, logins and passwords in the file?

The default collection interval is 300 seconds. This, in a good way, should also be put in the config, but if necessary, it can be changed in line 83 of the


The most attentive readers have already noticed that the code is written in micropython, which means that esptool and rshell will again be needed .

First, we flash the micropython itself: --port /dev/ttyUSB0 --baud 115200 write_flash --flash_size=detect -fm dio -ff 40m 0 esp8266–20200911-v1.13.bin

And then the code:

rshell -p /dev/ttyUSB0 -b 115200 cp /pyboard

The process for all my crafts on ESP8266 microcontrollers is always almost the same. Therefore, in the future I will refer to my article about the ticker monitor , where it is described for the first time.

Air sensor PCB 1


This time I made a boring (compared to the brutal simplicity of the micro-information stand) box-case.

Air sensor Case Design

You can download printable files from the Onshape project.


A few seconds after switching on, the sensor will send sensor readings to topics eCO2, tVOC, t0, t1, h0, p1 with the prefix sensor0/

It remains only to add tiles to the MQTT Dashboard to display this data.

Tile config 0

Tile config 1


When first started, the CO2 and VOC readings are zero. After five minutes, however, all readings are collected correctly.

The SI7021 sensor was sealed with a piece of white soft plastic. Possibly breathable. I can no longer check this, because immediately peeled it off.

In my case, the readings of the temperature sensors are overestimated by about 5 degrees. In the screenshot above, T2 is the temperature in the room according to the BMP280, while T1 is according to the DS18B20 from another device.

Original article on Medium


CC BY-SA 4.0

↑ Top