Building an environmental monitoring station with multiple sensors in one integrated build is the ultimate maker project for understanding indoor and outdoor conditions comprehensively. Rather than separate single-sensor builds, this guide shows you how to combine temperature, humidity, barometric pressure, air quality (VOC), particulate matter (PM2.5/PM10), noise level, and UV index sensors on a single ESP32 platform. The result is a powerful, unified environmental monitoring station suitable for homes, schools, and office deployments across India.
Table of Contents
- Sensor Selection for a Complete Station
- System Architecture
- Wiring All Sensors to ESP32
- Unified Arduino Code
- Local Display with OLED
- Cloud Dashboard Upload
- Power Supply Design
- Frequently Asked Questions
Sensor Selection for a Complete Station
A comprehensive environmental monitoring station measures multiple parameters simultaneously. Here is the recommended sensor complement for an Indian all-in-one build:
| Parameter | Sensor | Interface | Approx. Cost (INR) |
|---|---|---|---|
| Temperature + Humidity + Pressure | BME280 | I2C | ₹150–300 |
| VOC + eCO2 | SGP30 | I2C | ₹500–800 |
| PM2.5 + PM10 | PMS5003 | UART | ₹800–1200 |
| Noise Level | MAX4466 + Microphone | Analog | ₹150–250 |
| UV Index | VEML6075 | I2C | ₹300–500 |
Total sensor cost: approximately ₹1,900–₹3,050. Add ESP32 (₹350), display (₹200), enclosure (₹300), and power supply (₹200) for a complete build around ₹3,000–₹4,000.
System Architecture
The ESP32’s dual-core processor is ideal for this multi-sensor build. Core 0 handles Wi-Fi, cloud uploads, and the web server. Core 1 handles sensor reading loops on different schedules:
- Every 1 second: Read noise level (rolling average for dB calculation)
- Every 5 seconds: Read BME280 (temperature, humidity, pressure)
- Every 10 seconds: Read SGP30 (TVOC, eCO2) and PMS5003 (PM2.5, PM10)
- Every 30 seconds: Read VEML6075 (UV index)
- Every 60 seconds: Upload all readings to cloud dashboard
Use FreeRTOS tasks on the ESP32 to run sensor reading and cloud upload independently without blocking each other. The ESP32’s Arduino core includes FreeRTOS and tasks can be created with xTaskCreate().
Wiring All Sensors to ESP32
The ESP32 supports multiple I2C buses. Place BME280 (0x76), SGP30 (0x58), and VEML6075 (0x10) on the primary I2C bus (GPIO 21/22). The PMS5003 uses UART2 (GPIO 16/17). The MAX4466 microphone uses an analog pin (GPIO 34):
// ESP32 Pin Assignments
#define I2C_SDA 21 // BME280, SGP30, VEML6075
#define I2C_SCL 22
#define PMS_RX 16 // PMS5003 UART2
#define PMS_TX 17
#define MIC_PIN 34 // MAX4466 analog output
#define OLED_SDA 21 // SSD1306 shares I2C bus (addr 0x3C)
#define OLED_SCL 22
Unified Arduino Code
#include <Wire.h>
#include <Adafruit_BME280.h>
#include "Adafruit_SGP30.h"
#include <HardwareSerial.h>
Adafruit_BME280 bme;
Adafruit_SGP30 sgp;
HardwareSerial pmsSerial(2);
struct EnvData {
float temp, humidity, pressure;
uint16_t tvoc, eco2;
uint16_t pm25, pm10;
int noiseDB;
float uvIndex;
};
EnvData currentData;
void readBME() {
currentData.temp = bme.readTemperature();
currentData.humidity = bme.readHumidity();
currentData.pressure = bme.readPressure() / 100.0F;
}
void readSGP() {
if (sgp.IAQmeasure()) {
currentData.tvoc = sgp.TVOC;
currentData.eco2 = sgp.eCO2;
}
}
void readNoise() {
int maxVal = 0, minVal = 1023;
for (int i = 0; i < 100; i++) {
int val = analogRead(MIC_PIN);
maxVal = max(maxVal, val);
minVal = min(minVal, val);
delayMicroseconds(125);
}
int amplitude = maxVal - minVal;
// Approximate dB conversion (calibrate with reference)
currentData.noiseDB = map(amplitude, 0, 1023, 30, 100);
}
void printData() {
Serial.printf("T:%.1fC H:%.1f%% P:%.1fhPa TVOC:%dppb eCO2:%dppm PM2.5:%d PM10:%d Noise:%ddB
",
currentData.temp, currentData.humidity, currentData.pressure,
currentData.tvoc, currentData.eco2,
currentData.pm25, currentData.pm10, currentData.noiseDB);
}
void setup() {
Serial.begin(115200);
Wire.begin();
pmsSerial.begin(9600, SERIAL_8N1, 16, 17);
bme.begin(0x76);
sgp.begin();
}
void loop() {
readBME();
readSGP();
readNoise();
printData();
delay(10000);
}
Local Display with OLED
A 0.96-inch SSD1306 OLED provides a local readout without requiring network connectivity. Use a scrolling display that cycles through different sensor groups every 5 seconds, showing the most important parameters on each screen. Alternatively, a larger 2.42-inch SSD1309 display (128×64 pixels) can show all parameters simultaneously in a compact layout.
Cloud Dashboard Upload
ThingSpeak’s 8-field limit is insufficient for all parameters from this station. Use InfluxDB Cloud or Grafana Cloud (both free tiers available) for unlimited fields. Alternatively, use two ThingSpeak channels — one for atmospheric parameters and one for air quality. The ESP32’s Wi-Fi stack handles HTTP POST requests efficiently using the HTTPClient library.
Power Supply Design
Running 5 sensors plus ESP32 continuously draws approximately 300-400mA at 5V. Use a quality 5V/1A USB adapter (not a phone charger — use one with proper regulation). For backup during Indian power outages, add an 18650 Li-ion cell with a TP4056 charger and a boost converter to maintain 5V output during charging. A 3000mAh 18650 provides approximately 6-8 hours of backup at full sensor load.
Frequently Asked Questions
Can I run all these sensors on an Arduino Uno instead of ESP32?
Arduino Uno can run the sensors but lacks Wi-Fi, has only one hardware serial port (conflicts with PMS5003), and has limited SRAM (2KB) which will overflow when storing readings for all sensors. Use Arduino Mega (4 hardware serial ports, 8KB SRAM) or ESP32. The ESP32 at ₹350-500 is the clear choice for this multi-sensor build.
Why do I need VEML6075 for UV measurement when I can estimate UV from the date?
UV intensity in India varies enormously with cloud cover, monsoon haze, and local air pollution. Delhi in winter with heavy pollution can have UV index 2-3 when the unclouded sky would give 8-9. A VEML6075 provides actual real-time measurement critical for applications like plant growth chambers (which need minimum UV thresholds) or personal UV exposure alerts.
How do I handle the 15-second minimum interval for ThingSpeak with 8+ fields?
Use two ThingSpeak channels with different write API keys. Upload atmospheric data (temperature, humidity, pressure, UV) to Channel 1 and air quality data (VOC, CO2, PM2.5, PM10, noise) to Channel 2. Stagger uploads by 5 seconds to avoid rate limiting. Both channels can be displayed together on a ThingSpeak App dashboard using the MATLAB visualisation.
What enclosure size do I need for this multi-sensor build?
A 200x120x75mm polycarbonate IP65 enclosure comfortably fits all components. The PMS5003 needs external ventilation openings for air sampling — use a louvred vent with insect mesh on the enclosure’s side. Mount the VEML6075 under a small glass or acrylic window on top of the enclosure for UV measurement without compromising weatherproofing.
How accurate is DIY noise measurement compared to a professional sound level meter?
A MAX4466 with an electret microphone gives a rough approximation of noise levels, accurate to ±5 dB for relative comparisons. For absolute dB measurements, the microphone needs calibration against a reference sound source at a known dB level. For regulatory compliance monitoring (like monitoring construction noise against Indian CPCB standards), use a certified Class 2 sound level meter. The DIY approach is suitable for trend monitoring and alerts.
Add comment