Building Air Quality Monitoring Station with .NetCore and Raspberry Pi

Nermin Kaharovic

In recent years, air toxicity contributed grossly to mortality rates. With the increase in the urban population, air quality has become an alarming concern around the world. Thus, the necessity to constantly monitor air quality arose.

In Sarajevo, the capital of Bosnia and Herzegovina, the situation is no different than in other highly polluted cities. We are struggling with a very high degree of pollution, especially during the winter.

Golden hour in Sarajevo Bosnia

It has even come to a point where all the locals know and talk about PM particles, precisely PM2.5, and PM10 on a daily basis.

So, what are these?

PM10 is a particulate matter of 10 micrometers or less in diameter, while PM2.5 has 2.5 micrometers or less in diameter. By way of comparison, a human hair is about 100 micrometers, so roughly 40 fine particles could be placed on its width.

According to the European Environment Agency, these particles have a high impact on human health and are a major cause of premature death due to heart disease, stroke, lung disease, and cancer. They are also the single largest environmental health risk in Europe.

Unfortunately, during this past winter, our city hit the top of the charts several times as the most polluted city in the world.

It was almost impossible to find any kind of air purifier device without waiting for at least a month. Everything was sold out.

While waiting for one to arrive I was thinking about a quick solution for something that will allow me to at least monitor air quality in my home.

The only prerequisite was that it had to include some coding. 🙂

After a few hours of intensive research, I have found a really interesting sensor that could help me with this mission – SDS 011. The sensor was developed by Inovafit, a spin-off from the University of Jinan (in Shandong), China.

Sensor technology is based on laser diffraction theory, where particle density distribution is specified from the light intensity distribution patterns.

The sensor contains a digital output and a built-in fan. It measures the particle density distribution between 0.3 to 10 ╬╝m in the air. A built-in algorithm converts the particle density distribution into particle mass.

SDS011 sensor and Raspberry Pi 4


First thing I wanted to do is to create a simple PoC application

Initial idea was to deploy the worker service to Raspberry Pi so I can place it at any location I want and then create some kind of client/receiver app that will display the sensor s readings. I decided to use .Net Core Worker service as the background service for the connection with the actual sensor and SignalR for real-time streaming.

When I started with development I faced a quite interesting challenge; how to actually get those two magical numbers (PM10 and PM2.5) from the sensor s serial port?

After spending a few hours with sensor schema and on research, I have found an existing Github project which I used as a starting point. It saved me a lot of time.

Once I was done with the service, I deployed everything to the Raspberry Pi. There are a lot of things that needed to be configured but I ll not go into details (configuration of Raspbian OS, .Net Core SDK, Nginx reverse proxy, configuring service to be able to run on Linux OS, deploying it as a daemon, etc.).

The next thing was to create an angular app that behaves as a client/receiver. Once I wired up everything, the data started to show up on the UI! And since I used SignalR, everything was in real-time!

Command Line Interface (CLI)

After I was done with the PoC application, I could not resist investigating further on the sensor capabilities, which led me to interesting findings!

Service life is the key parameter of a laser dust sensor. The laser diode
in this sensor is high-quality and its service life is up to 8000 hours.

If you need real-time data (such as detector), you can use the default configuration that measures at the frequency of 1 time per second.
In the occasion of real-time demand not being too not high (such as filter, air quality monitoring, etc.), you can use the discontinuous working method to prolong the service life. For example, you can start the sensor for 30 seconds per minute.

This means that the sensor can be configured to work in different modes! After just a few minutes, I was able to find sensor data schema:

So for example, if you want to configure the sensor to work every minute, you need to send the following command via serial port:

AA B4 08 01 01 00 00 00 00 00 00 00 00 00 00 A1 60 0B AB

Here is an example of how we can accomplish this via C# code:

if (!string.IsNullOrWhiteSpace(numberOfminutes))
     var minutes = Convert.ToByte(numberOfminutes);
     var checksumBytes = new byte[]
     var checksum = 
     var finalCommands = new byte[19];
     finalCommands[0] = SerialPortCommands.HEAD;
     finalCommands[1] = SerialPortCommands.CMD_ID;
     for (int i = 0; i < checksumBytes.Length; i++)
         finalCommands[i + 2] = checksumBytes[i];
     finalCommands[17] = Convert.ToByte(checksum);
     finalCommands[18] = SerialPortCommands.TAIL;
     if (serialPort.IsOpen)
         serialPort.Write(finalCommands, 0, finalCommands.Length);

The next step was to create some kind of sensor configuration tool.
I decided to make my work interesting so for this purpose I choose .Net Core Global Tool. This tool allows us to create and deploy the application as a CLI. You are probably familiar with the .Net Core CLI or Angular CLI. Once the application has been installed you can access it from the command prompt.

There are a lot of other sensor modes I didn t code yet, but I plan to (sleep and work modes, different query modes, etc.).

Architecture v2

I really had a great time working on this. Once I was done with the initial set up, and after a quick demo and brainstorming with one of my teammates, I decided to bring up the whole design to the next level (potential real-world architecture).

We came up with a draft of the new architecture that could enable us to connect multiple sensors, track all data, generate on-demand reports and provide an interface for different integrations such as real-time data streaming via SignalR, gRPC, REST, etc.

Now, the only thing that was left to do is to try to develop everything according to the new architecture. A little more coding there it was!!

This would allow us to have the capability to measure hazardous particles such as PM 10 and PM 2.5, but in the later phases of this solution, the system could potentially measure temperature, humidity, smoke, etc.

This system could be implemented in public areas or in any place where the mentioned parameters are of critical importance. The data collected could then be further used for Data Science and Machine Learning purposes.

In the end, a huge thanks to Maestral folks who supported the whole idea and decided to actively participate in further development! #bestteam

Hopefully we ll have some fun and come up with something interesting and very useful!

Further readings:

  • SignalR – is an open-source library that simplifies adding real-time web functionality to apps. Real-time web functionality enables server-side code to push content to clients instantly.
  • gRPC – is a modern open-source high-performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication.
  • gRPC-Web – provides a JavaScript library that lets browser clients access a gRPC service – it s still under the heavy development but you might want to check it out!


Leave a Reply

Your email address will not be published. Required fields are marked *

After you leave a comment, it will be held for moderation, and published afterwards.

The reCAPTCHA verification period has expired. Please reload the page.