Table of Contents

S.A.M. - Smart Air Monitor

S.A.M. is an IoT home automation device, which obvious purpose is to monitor the various properties of the air inside or around the house, which can be quite useful, or even of critical importance, as the detection of gas leaks or various other pollutants could mean the avoidance of life-threatening scenarios.

Features

Architectural Overview

The setup is quite straightfoward, and it’s best explained by the diagram.

Note! Any device may suffice for hosting the web server and Home Assistant, the Pi 5 is just what I’m currently using.

As it can be seen in the diagram above, the device consists of a RP2040 MCU along with the required sensors and a RGB LED strip, which are listed below:

In order for the sensors to properly function, I have also added 2 10k pull-up resistors, one for the DHT-11 and one for the MQ-135, while the WS2812 does not require anything else. The device is also powered via the micro USB, which is also used when making changes to its code during development.

Software Design

Web server

To implement the web server, I decided to use a flask web server, complete with a light sqlite database for storing all the data. To view the data, I created an endpoint called ”/data/all”, and to post it, I created ”/data/post”. I originally wanted to also build a Home Assistant plugin, but that didn't happen as there were some technical difficulties I will get to below.

Client

The client (the device itself) was coded using the pico sdk. For internet acces, I used the pico_cyw43 driver for the Wi-Fi module, and I managed to use it to connect to the internet, but because of using the C SDK instead of something like MicroPython, I had to use lwip to try to connect to the server, but that failed, as I got a HTTP_TIMEOUT when doing that. Because of the lack of remaining time, I didn't manage to connect the client to the server, but I'll surely do it in the future, using plain TCP.

As for the code driving the sensors, here is a short overview for each component:

* WS2812 - I had to use the onboard “pio” module to drive this LED strip, and I didn't have any luck with getting the right colors using a library I found online, so I heavily modified it and did some bit magic with struct packing in order to solve the problem. I then wrote some utility functions which light up the whole strip in a specific color, and hooked that to the output of the MQ135, so that it changes color when it detects higher CO2/dangerous gas levels, alerting the user.

* MQ135 - This is the sensor I had the most difficulties with. In order to make it work, I had to let it sit for 24h connected to VCC in a process called “preheating”, which is necessary in order for it to start working properly. I then calibrated the sensor, modifying various values inside a library which I rewrote from c++ to c. After working with it for some days, I managed to get real, quite precise, athmospheric readings.

* DHT11 - Another sensor which was hard to make to work, because of various timing issues. The examples I found online of making the timings work were not valid for my setup, and I had to write the code myself.

As for the build system and overall tech stack for the client, I used the Pico C/C++ SDK with cmake, and nix for pulling these dependencies on my local machine and setting the paths. This brought with it another set of issues, as the SDK is quite messy, and it was very hard doing all the work to make the project compile, and the clangd LSP to work properly. (it still doesn't parse the entire SDK for some reason, but its not so bad)

Code archive: sam.zip

Conclusion

This was a very hard project for me, as debugging the sensors was a pain. I learned a lot though, from low-level embedded programming to web stuff. I hoped I would make the connection to the server work, and also the Home Assistant plugin, but there is room for that in the future.