Things Used in This Project
Hardware Components:
Raspberry Pi Pico 2
A compact and powerful microcontroller for handling sensor data and communication.
Quantity: 1FireBeetle ESP32 IoT Microcontroller (Supports Wi-Fi & Bluetooth)
A versatile microcontroller with built-in Wi-Fi and Bluetooth, ideal for IoT projects.
Quantity: 1PCBWay MQ135 Sensor
The MQ135 sensor is used to detect air quality, including various gases like ammonia, benzene, alcohol, and smoke.
Quantity: 1PCBWay Custom PCB
A custom-designed PCB for connecting the components and ensuring efficient operation of the device.
Quantity: 1
Software Apps & Online Services:
Fusion
Autodesk Fusion for 3D modeling and designing custom enclosures and PCBs.Arduino IDE
The Arduino Integrated Development Environment (IDE) used for writing and uploading the code to the microcontroller.
Hand Tools & Fabrication Machines:
3D Printer (Generic)
Used for printing custom parts, including the enclosure for the air quality meter.
Story
Hello everyone, and welcome back! Today, I’m excited to share with you a practical and innovative project—a Portable Air Quality Meter.
This compact and handy device allows you to monitor air quality on the go, using the MQ135 sensor to detect gases in the air. The readings are displayed clearly on an OLED screen with the help of the FireBeetle ESP32 E V1 microcontroller.
Thanks to its small size and built-in power supply, this air quality meter is fully portable, meaning you can easily take it anywhere and monitor the air quality wherever you are.
While this device is not a full-fledged Air Quality Index (AQI) meter, it provides valuable information about specific gases in the air, such as CO2, smoke, benzene, alcohol, nitrogen oxide, and ammonia. AQI systems typically monitor particulate matter (PM2.5, PM10), oxygen, nitrogen dioxide, sulfur dioxide, and carbon monoxide, which are important for public health advisories. Our setup, though more limited, gives you an idea of the air quality based on the detection of particular gases.
While it can’t replace professional AQI systems, this meter is a great tool for gaining insight into the presence of harmful gases and monitoring air quality on a daily basis.
The components that make up this project include the MQ135 Air Quality Sensor, the SSD1306 Display, a small 14500 3.7V 600mAh Li-ion cell for power, and the FireBeetle 2 ESP32 Microcontroller, which handles the processing and display. All of these are housed within a custom 3D-printed body, designed for portability and ease of use.
In this article, we’ll go through the entire build process and show you how to put together your own Portable Air Quality Meter.
MQ135 Air Quality Sensor
The MQ135 sensor is a versatile and highly useful component, widely used in various applications such as pollution control, environmental monitoring, and air quality systems. It is particularly well-suited for detecting hazardous gases in the atmosphere, making it ideal for air quality monitoring projects.
This sensor has two key outputs:
Analog Output: It generates an analog voltage signal (ranging from 0–5V) based on the concentration of gases in the air.
Digital Output: It produces a high (5V) or low (0V) digital signal when the gas concentration exceeds a certain threshold.
The MQ135 runs off a 3.3V supply, but it can tolerate up to 5V, providing flexibility in power source compatibility. However, it is important to note that the sensor requires a 20-second preheating time to stabilize and provide accurate readings. During operation, it consumes about 150 mA of current.
The MQ135 is capable of detecting a variety of toxic and harmful gases, including:
Ammonia (NH3)
Nitrogen Oxides (NOx)
Carbon Dioxide (CO2)
Benzene
Smoke
Given its wide range of applications and reliable performance, the MQ135 is an excellent choice for projects that aim to monitor air quality and detect potentially dangerous gases in various environments.
Basic Setup Using Raspberry Pi Pico
To get started with the MQ135 Sensor using the Raspberry Pi Pico 2, we will connect the components in the simplest configuration for testing purposes.
Wiring:
VCC of the MQ135 sensor goes to the 3.3V pin on the Raspberry Pi Pico 2.
GND of the MQ135 sensor connects to the GND pin on the Raspberry Pi Pico 2.
The analog output of the MQ135 sensor is connected to GPIO26 (ADC0) on the Raspberry Pi Pico.
The digital output of the MQ135 sensor is connected to GPIO21 on the Raspberry Pi Pico.
This setup allows the Pico to read both analog and digital outputs from the MQ135 sensor, enabling us to monitor the air quality with both voltage levels and threshold-based signals.
Here’s the basic sketch we used for testing the sensor:
#include <Wire.h>
// Define the pins
const int analogPin = 26; // GP26
const int digitalPin = 21; // GP21
void setup() {
Serial.begin(9600);
pinMode(digitalPin, INPUT);
}
void loop() {
int analogValue = analogRead(analogPin);
int digitalValue = digitalRead(digitalPin);
Serial.print("Analog Value: ");
Serial.print(analogValue);
Serial.print(", Digital Value: ");
Serial.println(digitalValue);
delay(1000);
}
It takes about 20 to 30 seconds for the MQ135 Sensor to preheat before it provides precise readings. The sensor value in the Serial monitor can be observed by the user using the sketch above.
Level 2 – Design
In the Level 2 design, we created a compact enclosure measuring 80 x 55 x 30 mm. The design was split into two main parts: the Base and the Top Lid. The OLED screen was mounted inside the top lid, while the rest of the components, such as the FireBeetle 2 Board, MQ135 Sensor, Power Switch, and Battery, were housed within the Base section.
We added handles on both sides of the base to make the device more portable and comfortable to hold. Additionally, we integrated a hook-like component for attaching an ID card strap or a keychain, enhancing the device’s portability.
To make the design visually appealing, we included two components resembling the letters “O” and “X” on the top lid. These parts were printed in orange PLA, while the rest of the enclosure was printed in grey PLA, adding a splash of color and style to the project.
Why Choose FireBeetle Over Raspberry Pi Pico
For the Level 2 iteration, we opted for the FireBeetle 2 ESP32-E Microcontroller instead of the Raspberry Pi Pico 2. While both microcontrollers are similar in size, we encountered a space issue in the enclosure with the Pico.
The Pico required additional space for a separate charging circuit for the lithium cell, which led us to redesign the enclosure. In contrast, the FireBeetle 2 comes with an onboard TP4056 lithium-ion charging circuit, which solved our space problem. The TP4056 is a full linear charger specifically designed for single-cell lithium-ion batteries, making it ideal for portable devices.
By using the FireBeetle 2, we achieved a more compact design without sacrificing functionality, allowing for a more efficient and user-friendly air quality meter.
MAIN SKETCH
Let’s have a look at the final Sketch which will be used in Firebeetle Setup.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int analogPin = 35; // A3
const int digitalPin = 2; // D2
void setup() {
Serial.begin(9600);
pinMode(digitalPin, INPUT);
// SSD1306 OLED display initialization
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.display();
delay(2000); // Pause for 2 seconds
display.clearDisplay();
}
void loop() {
int analogValueRaw = analogRead(analogPin);
int analogValue = map(analogValueRaw, 0, 4095, 0, 1023); // Scale the value to match the Pico's range
int digitalValue = digitalRead(digitalPin);
String airQuality = getAirQuality(analogValue);
Serial.print("Analog Value (Raw): ");
Serial.print(analogValueRaw);
Serial.print(", Scaled Value: ");
Serial.print(analogValue);
Serial.print(", Digital Value: ");
Serial.println(digitalValue);
// Display scaled analog value and air quality condition on OLED
display.clearDisplay();
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 10); // Start at top-left corner
display.print("Value: ");
display.println(analogValue);
display.setTextSize(1);
display.setCursor(0, 40);
display.print("Air Quality: ");
display.println(airQuality);
display.display();
delay(1000);
}
String getAirQuality(int analogValue) {
if (analogValue <= 200) {
return "Excellent";
} else if (analogValue <= 400) {
return "Good";
} else if (analogValue <= 600) {
return "Moderate";
} else if (analogValue <= 800) {
return "Poor";
} else {
return "Very Poor";
}
}
The three main libraries in the sketch were added specifically to use I2C communication to drive the SSD1306 OLED.
Two outputs are provided by the MQ135 sensor: an analog output that is attached to the Firebeetle’s A3 pin and a digital output that is connected to the Firebeetle’s D2.
We must reduce the raw analog value, which is around 0-4095, to a range of 0-1023 in order to obtain the analog value, which is what we need to obtain the air quality measurements.
Using the Serial.println function, the values are displayed on the screen, but with a twist. The twist here is that we have added getAirQuality Function which takes the scaled analog value and returns a string representing the air quality condition:
- <= 200: “Excellent”
- <= 400: “Good”
- <= 600: “Moderate”
- <= 800: “Poor”
- > 800: “Very Poor”
FireBeetle SSD1306 Display and MQ135 Wiring
To set up the FireBeetle 2 ESP32, SSD1306 Display, and MQ135 Sensor, follow the wiring steps outlined below:
FireBeetle to MQ135 Wiring:
Connect the 3.3V pin of the FireBeetle to the VCC pin of the MQ135 Sensor.
Connect the GND pin of the FireBeetle to the GND pin of the MQ135 Sensor.
FireBeetle to SSD1306 OLED Display Wiring:
Connect the 5V pin of the FireBeetle to the VCC pin of the SSD1306 Display.
Connect the GND pin of the FireBeetle to the GND pin of the SSD1306 Display.
Connecting the MQ135 Sensor to FireBeetle:
Connect the Analog output (A0) of the MQ135 Sensor to the A3 pin of the FireBeetle.
Connect the Digital output (D0) of the MQ135 Sensor to the D2 pin of the FireBeetle.
FireBeetle to SSD1306 Display I2C Wiring:
Connect the SDA pin of the FireBeetle to the SDA pin of the SSD1306 Display.
Connect the SCL pin of the FireBeetle to the SCL pin of the SSD1306 Display.
Power Source Wiring
The project is powered by a 14500 3.7V 600mAh lithium-ion battery combined with a Protection Circuit Module (PCM). The PCM helps protect the battery from overcharge, overdischarge, and short circuits.
Connect the positive terminal of the 14500 lithium-ion battery to the battery positive terminal on the FireBeetle.
Solder the negative terminal of the lithium-ion battery to the on terminal of the rocker switch.
Connect the other terminal of the rocker switch to the battery negative terminal on the FireBeetle.
The rocker switch serves as the primary power switch, allowing you to turn the device on and off by controlling the power flow between the battery and the FireBeetle.
Wiring Summary:
FireBeetle 2 ESP32:
3.3V to MQ135 VCC
GND to MQ135 GND
A3 to MQ135 Analog Output
D2 to MQ135 Digital Output
5V to SSD1306 VCC
GND to SSD1306 GND
SDA to SSD1306 SDA
SCL to SSD1306 SCL
Power Supply:
14500 Li-ion Battery + PCM:
Positive terminal to FireBeetle battery positive
Negative terminal to Rocker switch (on terminal)
Rocker switch (off terminal) to FireBeetle battery negative
Body Assembly Process
To begin the body assembly, we first positioned the OLED screen inside the top lid of the enclosure. We then used hot glue to secure the display in place.
Next, the MQ135 Sensor was slid into its designated spot inside the Base body. The battery and power switch were securely fastened in their positions. After that, we placed the Firebeetle Board in the center of the base body and secured it using hot glue.
Once we confirmed that all the components were in place, we placed the Top Lid over the base body and fastened them together with four M2 screws.
Finally, we applied super glue to the back of the letter O and X components and positioned them onto the top lid for an enhanced aesthetic finish.
With that, the assembly process was complete!
Result and Conclusion
The end result is a portable Air Quality Meter, a handy device that can measure hazardous gases in the environment, providing users with an easy way to monitor the air quality around them. This device serves as a valuable tool for improving air safety, both indoors and outdoors.
For testing, we took readings in two different locations in my city: on my rooftop and near a green area. The readings showed a noticeable difference, with lower carbon concentrations near the green area compared to the higher levels near urban areas.
In the city, the readings ranged from 550 to 620, depending on proximity to major roads, industrial zones, or areas with abundant green spaces. We expect that testing in locations with even fewer pollutants, like mountains or hills, would result in even lower values.
While the project was successfully completed, I plan to make further improvements in the future to reduce the size and increase the portability of the device.
Thanks for following along with this project. Stay tuned for more exciting updates coming soon!
Peace.