Wednesday, 5 August 2026

AI Air Pollution Monitoring and Prediction System

The plan is solid. Let's skip the meta-discussion about page counts, skip the preambles, and start building Volume 1 of your engineering documentation directly.

Here is the complete initial architectural blueprint, high-level system overview, and hardware schematics to establish the foundation of your project.

1. Executive Project Abstract

The AI-Powered Air Pollution Monitoring and Prediction System is an end-to-end Agentic IoT ecosystem designed to sense, analyze, log, and forecast microclimate air quality parameters in real time. Built around an ESP32 microcontroller, the edge node samples particulate matter ($\text{PM}_{2.5}, \text{PM}_{10}$ via PMS5003), hazardous gases ($\text{CO}_2, \text{NH}_3, \text{NO}_x$, VOCs via MQ135), environmental parameters (temperature and humidity via DHT22, barometric pressure via BMP280), and spatial coordinates (via NEO-6M GPS).

Data is transmitted concurrently via dual protocols: HTTP/REST to a ThingSpeak cloud dashboard for real-time visualization, and Webhooks to an n8n orchestration server. The n8n engine feeds an AI Agent (combining localized feature engineering with LLM/ML prediction logic) to predict next-hour AQI trends, optimize fan actuator power cycles, evaluate health risks, and dynamically synthesize localized voice alert notifications pushed directly to users via Telegram.

2. System Hardware Architecture & Bill of Materials

Bill of Materials (BOM)

Component Part / Model Quantity Operational Voltage Function
Microcontroller ESP32 DevKit V1 (30-pin) 1 3.3V / 5V USB Core processing, Wi-Fi stack, sensor sampling
PM Sensor PMS5003 (Plantower) 1 5V (3.3V Logic TX/RX) Laser scattering for $\text{PM}_{1.0}, \text{PM}_{2.5}, \text{PM}_{10}$
Gas Sensor MQ135 Breakout 1 5V (Analog Out 0-3.3V) Air quality ($\text{NH}_3$, $\text{NO}_x$, Alcohol, Benzene, Smoke, $\text{CO}_2$)
Temp/Humidity DHT22 (AM2302) 1 3.3V Ambient temperature and relative humidity
Baro Pressure BMP280 (I2C) 1 3.3V Atmospheric pressure and altitude estimation
Location Tracking NEO-6M GPS Module 1 3.3V / 5V (UART TX/RX) Geospatial tagging (Latitude, Longitude, Altitude)
Display 0.96" SSD1306 OLED 1 3.3V (I2C) Local real-time telemetry display
Actuator 5V Single-Channel Relay 1 5V (Signal 3.3V compatible) Drives high-volume air purification fan
Audio Alert 5V Active Buzzer 1 3.3V / 5V Local acoustic alarm on critical AQI threshold
Visual Indicator 4-Pin Common Cathode RGB LED 1 3.3V (via $220\,\Omega$ Resistors) Local visual AQI status (Green/Yellow/Red)
Power Supply 5V 2A DC Adapter 1 110-240V AC to 5V DC Regulated system power source

3. Comprehensive Circuit Pin Mapping

The pinouts below align with standard ESP32 30-pin DevKit V1 boards:

ESP32 GPIO Connected Component Module Pin Protocol / Signal Type
GPIO 21 SSD1306 OLED & BMP280 SDA I2C Data Line (Shared)
GPIO 22 SSD1306 OLED & BMP280 SCL I2C Clock Line (Shared)
GPIO 16 (RX2) PMS5003 TX UART2 Receive
GPIO 17 (TX2) PMS5003 RX UART2 Transmit
GPIO 4 (RX1) NEO-6M GPS TX UART1 Receive
GPIO 2 (TX1) NEO-6M GPS RX UART1 Transmit
GPIO 15 DHT22 DATA Single-Bus Digital (Requires $10\,\text{k}\Omega$ Pull-up)
GPIO 34 (VP) MQ135 AOUT Analog Input (Input-only, no internal pull-ups)
GPIO 18 5V Relay Module IN Digital Output (High = Relay ON)
GPIO 19 Active Buzzer VCC / SIG Digital Output (High = Sound Alarm)
GPIO 25 RGB LED Red Pin PWM Output (AQI Alert Level)
GPIO 26 RGB LED Green Pin PWM Output (AQI Alert Level)
GPIO 27 RGB LED Blue Pin PWM Output (AQI Alert Level)

4. Hardware System Block Diagram

                 +-------------------------------------------------------------+
                 |                     5V 2A POWER SUPPLY                      |
                 +------------------------------+------------------------------+
                                                |
                                                v
 +----------------------------------------------+----------------------------------------------+
 |                                    ESP32 DEVKIT V1                                          |
 |                                                                                             |
 |   [UART 1]  <--->  NEO-6M GPS Module (Geospatial Tagging)                                   |
 |   [UART 2]  <--->  PMS5003 Laser Sensor (PM1.0 / PM2.5 / PM10)                             |
 |   [I2C]     <--->  SSD1306 OLED (0.96") + BMP280 Barometric Sensor                          |
 |   [GPIO 15] <--->  DHT22 (Temperature & Humidity)                                         |
 |   [GPIO 34] <---   MQ135 Gas Sensor (Analog Raw AQI Signal)                                 |
 |                                                                                             |
 |   [GPIO 18] --->   5V Relay Output (Exhaust / Fan Control)                                  |
 |   [GPIO 19] --->   Active Acoustic Buzzer                                                   |
 |   [GPIO 25-27]-->  PWM RGB LED Indicator                                                    |
 +----------------------------------------------+----------------------------------------------+
                                                |
                                  Wi-Fi Dual-Channel Outbound
                                                |
                       +------------------------+------------------------+
                       |                                                 |
                       v                                                 v
           +------------------------+                        +------------------------+
           |    THINGSPEAK CLOUD    |                        |      n8n ENGINE        |
           | Real-time Telemetry &  |                        |  Workflow Automation & |
           | Analytics Dashboard    |                        |    Agentic Processing  |
           +------------------------+                        +-----------+------------+
                                                                         |
                                                  +----------------------+----------------------+
                                                  |                      |                      |
                                                  v                      v                      v
                                       +--------------------+  +-------------------+  +--------------------+
                                       |   GOOGLE SHEETS    |  |  TELEGRAM BOT     |  | AI PREDICTION      |
                                       | Historical Logger  |  |  Text & Voice     |  | Power & AQI Model  |
                                       +--------------------+  +-------------------+  +--------------------+

5. End-to-End System Processing Flowchart

       [ START ]
           |
           v
  [ Initialize Hardware ]
  (I2C, UART1, UART2, GPIOs, OLED)
           |
           v
  [ Connect to Wi-Fi ]  <--- (Retry Loop if disconnected)
           |
           v
  [ Read Sensor Array ]
  - PMS5003 (PM2.5 / PM10)
  - MQ135 (Gas Level)
  - DHT22 (Temp / Humidity)
  - BMP280 (Pressure)
  - NEO-6M (GPS Lat / Long)
           |
           v
  [ Compute Air Quality Index (AQI) ]
  (Calculate Sub-Indices using US EPA / CPCB formulas)
           |
           v
  [ Update OLED Screen & RGB Status ]
           |
           +----------------------------------+
           |                                  |
           v                                  v
  [ Local Threshold Check ]          [ Transmit Telemetry ]
   - If AQI > 200:                    - POST Payload to ThingSpeak
     * Turn ON Relay (Fan)            - Trigger n8n Webhook Endpoint
     * Sound Buzzer Alarm            
   - Else:                            
     * Keep Relay/Buzzer OFF         
           |                                  |
           +----------------------------------+
                                              |
                                              v
                                   [ n8n Automation Engine ]
                                              |
                     +------------------------+------------------------+
                     |                        |                        |
                     v                        v                        v
            [ Append Raw Record ]    [ Execute AI Agent ]     [ Evaluate Risk & Alerts ]
            (Google Sheets API)      - Predict 1-hr AQI       - Is Voice Alert Needed?
                                     - Compute Fan Power       - Generate Audio via TTS
                                       Optimization            - Post Voice/Text Payload
                                                                 to Telegram Channel
                                              |
                                              v
                                       [ END / WAIT ]
                                     (Interval Delay ~15s)

6. Base ESP32 Sensor Reading & Transmission Firmware Blueprint

Below is the core firmware skeleton handling multi-UART sensor reading, AQI calculations, local display updates, relay management, and dual-cloud logging.

C++

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_BMP280.h>
#include <DHT.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

// Screen Config
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Sensor Pins & Config
#define DHTPIN 15
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

Adafruit_BMP280 bmp; // I2C

#define MQ135_PIN 34
#define RELAY_PIN 18
#define BUZZER_PIN 19
#define RGB_R_PIN 25
#define RGB_G_PIN 26
#define RGB_B_PIN 27

// Hardware Serial 2 for PMS5003
#define RXD2 16
#define TXD2 17

// Wi-Fi and API Configuration
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";
const char* THINGSPEAK_URL = "http://api.thingspeak.com/update";
const char* THINGSPEAK_API_KEY = "YOUR_THINGSPEAK_WRITE_KEY";
const char* N8N_WEBHOOK_URL = "http://YOUR_N8N_INSTANCE_IP:5678/webhook/air-quality-data";

// Telemetry Storage Struct
struct AirData {
  float pm25 = 0.0;
  float pm10 = 0.0;
  float temp = 0.0;
  float hum = 0.0;
  float pressure = 0.0;
  int rawGas = 0;
  int calculatedAQI = 0;
};

AirData currentData;

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2); // PMS5003

  pinMode(RELAY_PIN, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(RGB_R_PIN, OUTPUT);
  pinMode(RGB_G_PIN, OUTPUT);
  pinMode(RGB_B_PIN, OUTPUT);

  digitalWrite(RELAY_PIN, LOW);
  digitalWrite(BUZZER_PIN, LOW);

  // Initialize Wire & Displays
  Wire.begin(21, 22);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
  }
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("Initializing System...");
  display.display();

  dht.begin();
  if (!bmp.begin(0x76)) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
  }

  // Connect Wi-Fi
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWi-Fi Connected!");
}

void readPMS5003(float &pm25, float &pm10) {
  if (Serial2.available() >= 32) {
    if (Serial2.read() == 0x42 && Serial2.read() == 0x4D) {
      uint8_t buffer[30];
      Serial2.readBytes(buffer, 30);
      pm25 = (float)((buffer[4] << 8) | buffer[5]);
      pm10 = (float)((buffer[6] << 8) | buffer[7]);
    }
  }
}

int calculateSimpleAQI(float pm25) {
  // Simplified linear scale for demonstration
  if (pm25 <= 12.0) return (int)((50.0 / 12.0) * pm25);
  else if (pm25 <= 35.4) return (int)(51 + ((49.0 / 23.4) * (pm25 - 12.1)));
  else if (pm25 <= 55.4) return (int)(101 + ((49.0 / 19.9) * (pm25 - 35.5)));
  else if (pm25 <= 150.4) return (int)(151 + ((49.0 / 94.9) * (pm25 - 55.5)));
  else return 201; // Poor / Critical
}

void updateLEDs(int aqi) {
  if (aqi <= 50) { // Green
    analogWrite(RGB_R_PIN, 0); analogWrite(RGB_G_PIN, 255); analogWrite(RGB_B_PIN, 0);
  } else if (aqi <= 100) { // Yellow
    analogWrite(RGB_R_PIN, 255); analogWrite(RGB_G_PIN, 255); analogWrite(RGB_B_PIN, 0);
  } else { // Red
    analogWrite(RGB_R_PIN, 255); analogWrite(RGB_G_PIN, 0); analogWrite(RGB_B_PIN, 0);
  }
}

void updateDisplay() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.printf("AQI: %d\n", currentData.calculatedAQI);
  display.printf("PM2.5: %.1f ug/m3\n", currentData.pm25);
  display.printf("PM10:  %.1f ug/m3\n", currentData.pm10);
  display.printf("Temp:  %.1f C\n", currentData.temp);
  display.printf("Hum:   %.1f %%\n", currentData.hum);
  display.printf("Press: %.1f hPa\n", currentData.pressure);
  display.display();
}

void sendTelemetry() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;

    // 1. Post to ThingSpeak
    String tsUrl = String(THINGSPEAK_URL) + "?api_key=" + THINGSPEAK_API_KEY +
                   "&field1=" + String(currentData.calculatedAQI) +
                   "&field2=" + String(currentData.pm25) +
                   "&field3=" + String(currentData.pm10) +
                   "&field4=" + String(currentData.temp) +
                   "&field5=" + String(currentData.hum) +
                   "&field6=" + String(currentData.pressure);
    http.begin(tsUrl);
    http.GET();
    http.end();

    // 2. Post JSON Payload to n8n Webhook
    http.begin(N8N_WEBHOOK_URL);
    http.addHeader("Content-Type", "application/json");

    StaticJsonDocument<256> doc;
    doc["aqi"] = currentData.calculatedAQI;
    doc["pm25"] = currentData.pm25;
    doc["pm10"] = currentData.pm10;
    doc["temp"] = currentData.temp;
    doc["humidity"] = currentData.hum;
    doc["pressure"] = currentData.pressure;
    doc["raw_gas"] = currentData.rawGas;

    String jsonString;
    serializeJson(doc, jsonString);
    http.POST(jsonString);
    http.end();
  }
}

void loop() {
  readPMS5003(currentData.pm25, currentData.pm10);
  currentData.temp = dht.readTemperature();
  currentData.hum = dht.readHumidity();
  currentData.pressure = bmp.readPressure() / 100.0F; // Convert Pa to hPa
  currentData.rawGas = analogRead(MQ135_PIN);
  currentData.calculatedAQI = calculateSimpleAQI(currentData.pm25);

  updateLEDs(currentData.calculatedAQI);
  updateDisplay();

  // Actuator Safety Logic
  if (currentData.calculatedAQI > 150) {
    digitalWrite(RELAY_PIN, HIGH);  // Turn on exhaust/filter
    digitalWrite(BUZZER_PIN, HIGH); // Alarm active
  } else {
    digitalWrite(RELAY_PIN, LOW);
    digitalWrite(BUZZER_PIN, LOW);
  }

  sendTelemetry();
  delay(15000); // 15-second interval
}

7. Next Architectural Steps

With Volume 1 established, we can delve into any specific volume or module you need to focus on next:

  1. n8n Automation Architecture & Webhook Integration: Complete JSON schema, node connection map, Google Sheets logging node, and dynamic Telegram voice message generation (using ElevenLabs/OpenAI TTS API).

  2. AI Modeling & Predictive Algorithms: Mathematical formulation for AQI forecasting, fan power optimization algorithms, and feature engineering code.

  3. ThingSpeak & Dashboard Configuration: Field mapping, MATLAB analytics scripts for historical analysis, and alert triggers.

Where would you like to direct the next deep dive?

No comments:

Post a Comment