Industrial manufacturing
Industrial Internet of Things | Industrial materials | Equipment Maintenance and Repair | Industrial programming |
home  MfgRobots >> Industrial manufacturing >  >> Manufacturing Technology >> Manufacturing process

LoRa‑Based Smart City Air‑Quality Monitoring System

Components & Materials

LoRa‑Based Smart City Air‑Quality Monitoring System
Arduino UNO
×1
LoRa‑Based Smart City Air‑Quality Monitoring System
Seeed Base Shield V2
×1
LoRa‑Based Smart City Air‑Quality Monitoring System
NodeMCU ESP8266 Breakout Board
×1
LoRa‑Based Smart City Air‑Quality Monitoring System
Seeed Loudness Sensor
×1
LoRa‑Based Smart City Air‑Quality Monitoring System
Seeed Grove – Air Quality Sensor v1.3
×1
Seeed Grove – Temperature & Humidity Sensor (DHT11)
×1
Reyax LoRa Module
×1
Seeed Small Solar Panel 80x100mm 1W
×1
Seeed LiPo Rider Pro
×1
LoRa‑Based Smart City Air‑Quality Monitoring System
Rechargeable Battery, 3.7 V
×1

Necessary Tools & Equipment

LoRa‑Based Smart City Air‑Quality Monitoring System
3D Printer (generic)

Software & Online Services

LoRa‑Based Smart City Air‑Quality Monitoring System
Arduino IDE
LoRa‑Based Smart City Air‑Quality Monitoring System
Grandeur
LoRa‑Based Smart City Air‑Quality Monitoring System
Grandeur Canvas

Project Overview

Smart City & Air Quality

According to the World Bank, a smart city leverages technology to deliver highly efficient public services and a sustainable urban environment. Central to this vision is real‑time environmental monitoring, which identifies pollution sources and informs data‑driven policy decisions—whether that means optimizing traffic flows or advising residents on the safest walking routes.

Problem & Solution

Urban air pollution poses significant health risks, and timely data is essential for mitigation. Internet‑of‑Things (IoT) networks of low‑cost sensor nodes can continuously capture air quality and meteorological parameters. When combined with a reliable, low‑power communication layer, these networks enable city authorities to detect pollution hotspots and respond proactively.

Project Plan

Our solution monitors key environmental metrics—noise, temperature, humidity, and air quality—and relays the data wirelessly to a cloud platform. The entire node is powered by a 1 W solar panel with Li‑ion battery backup, ensuring autonomous operation. A cloud dashboard visualizes the data in real time, facilitating immediate insights and long‑term trend analysis.

Instead of connecting each sensor directly to the cloud—an approach that inflates power usage and costs—we aggregate data from multiple nearby nodes and transmit it through a single LoRa gateway. LoRa’s long‑range, low‑power characteristics make it ideal for dense urban deployments.

LoRa‑Based Smart City Air‑Quality Monitoring System

We chose Grandeur as the backend platform due to its user‑friendly SDKs for Arduino, NodeMCU, and Raspberry Pi, as well as its drag‑and‑drop dashboard builder.

Solar power provides a sustainable, maintenance‑free energy source for remote nodes, and the Li‑ion battery guarantees operation during periods of low insolation.

Building the Sensor Node

The node integrates a Grove air‑quality sensor, a Grove loudness sensor, and a DHT11 temperature/humidity sensor—all of which plug into the Seeed Base Shield without soldering, simplifying assembly and maintenance.

LoRa‑Based Smart City Air‑Quality Monitoring System

Power is supplied by a 1 W solar panel and a Seeed LiPo Rider Pro charger, which includes a 5 V boost converter to keep the Arduino within its operating voltage range.

The Reyax RYLR998 LoRa transceiver handles wireless transmission. Because the module accepts 3.6 V logic, a simple voltage divider protects the Arduino’s 5 V TX line.

LoRa‑Based Smart City Air‑Quality Monitoring System

Below is the wiring diagram that connects the LoRa module to the Base Shield via a custom adapter.

LoRa‑Based Smart City Air‑Quality Monitoring System

When connecting the LoRa module, ensure the Base Shield’s power switch is set to 3.3 V.

LoRa‑Based Smart City Air‑Quality Monitoring System

After assembly, verify communication by sending an AT command from the Arduino to the LoRa module.

LoRa‑Based Smart City Air‑Quality Monitoring System

Upload & Test

Upload the provided Arduino sketch, then open the serial monitor to confirm that sensor readings are transmitted correctly.

LoRa‑Based Smart City Air‑Quality Monitoring System

Enclosure Assembly

Print the STL files supplied in the attachment section. After confirming fit, assemble the components inside the enclosure using double‑sided tape or hot glue. Mount the solar panel on the top and route power cables through the designated hole.

LoRa‑Based Smart City Air‑Quality Monitoring System
LoRa‑Based Smart City Air‑Quality Monitoring System

Once all components are secured, the node is ready for field deployment.

LoRa‑Based Smart City Air‑Quality Monitoring System

Configuring Grandeur

Grandeur is an IoT backend that pairs devices with users and provides a real‑time dashboard. Follow these steps to set up your project:

  1. Create a new project on grandeur.dev.
  2. Register a user account; this account will be used to pair devices later.
  3. Define a device model with the JSON schema:
    {"temp":0, "humid":0, "air":0, "noise":0}
  4. Instantiate a device, capture its unique ID and access token, and store them for the Arduino firmware.
  5. Pair the device with the user via the dashboard or the API (e.g., pairDevice()).
  6. Build a Canvas dashboard: add four graph widgets—one each for temperature, humidity, noise level, and air quality—and bind them to the corresponding variables.

Once Canvas is authorized, users can log in to view live data. The API key and device token are required in the gateway firmware.

Gateway Setup

The NodeMCU acts as a LoRa gateway, receiving UART data from the sensor node and forwarding it to Grandeur via Wi‑Fi. Although a Raspberry Pi could serve this role, the NodeMCU offers a compact, low‑cost solution that meets the project’s bandwidth and latency requirements.

LoRa‑Based Smart City Air‑Quality Monitoring System

Gateway Firmware

The firmware parses the comma‑separated payload received from the LoRa module, converts each value to float, and pushes it to Grandeur using the provided SDK. Below is the core logic for data extraction and transmission.

void process_received_data(){
  start_pos = inputString.indexOf(start_val);
  end_pos = inputString.indexOf(end_val);
  String data_string = inputString.substring(start_pos+1, end_pos-1);
  int firstCommaIndex = data_string.indexOf(',');
  int secondCommaIndex = data_string.indexOf(',', firstCommaIndex+1);
  int thirdCommaIndex = data_string.indexOf(',', secondCommaIndex+1);
  String temperature = data_string.substring(0, firstCommaIndex);
  String humidity = data_string.substring(firstCommaIndex+1, secondCommaIndex);
  String noise_level = data_string.substring(secondCommaIndex+1, thirdCommaIndex);
  String air_auality = data_string.substring(thirdCommaIndex+1);
  temp = temperature.toFloat();
  humid = humidity.toFloat();
  noise = noise_level.toFloat();
  air = air_auality.toFloat();
  inputString = "";
  stringComplete = false;
}

Dashboard View

LoRa‑Based Smart City Air‑Quality Monitoring System
LoRa‑Based Smart City Air‑Quality Monitoring System

Firmware Code

  • Sensor Node Code
  • Gateway Code
Sensor Node (Arduino)
#include "AirQuality.h" // Grove air quality library
#include "Arduino.h"
#include "DHT.h"

#define DHTPIN 4     // Digital pin for DHT11
#define DHTTYPE DHT11   // Sensor model

DHT dht(DHTPIN, DHTTYPE);

AirQuality airqualitysensor;
int current_quality =-1;

const int sampleWindow = 50; // 20 Hz sampling
unsigned int sample;
float noise;
float temp, humid;
int airQuality;

void setup() {
  Serial.begin(115200); // UART for LoRa
  airqualitysensor.init(14);
  dht.begin();
}

void loop() {
  noise = calculate_sound_in_db();
  airQuality = calculate_air_quality();
  calculate_temp_humid();

  String values = String(temp)+","+String(humid)+","+String(noise)+","+String(airQuality);
  String cmd = "AT+SEND=0,"+String(values.length())+","+values;
  Serial.println(cmd);
  delay(15000);
}

float calculate_sound_in_db(){
  unsigned long startMillis= millis();
  float peakToPeak = 0;
  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;
  while (millis() - startMillis < sampleWindow){
    sample = analogRead(A1);
    if (sample < 1024){
      if (sample > signalMax) signalMax = sample;
      else if (sample < signalMin) signalMin = sample;
    }
  }
  peakToPeak = signalMax - signalMin;
  float db = map(peakToPeak,0,1000,48,120);
  return db;
}

int calculate_air_quality(){
  current_quality=airqualitysensor.slope();
  return current_quality;
}

void calculate_temp_humid(){
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  if (isnan(h) || isnan(t)) return;
  temp = t;
  humid = h;
}

ISR(TIMER1_OVF_vect){
  if(airqualitysensor.counter==61){
      airqualitysensor.last_vol=airqualitysensor.first_vol;
      airqualitysensor.first_vol=analogRead(A0);
      airqualitysensor.counter=0;
      airqualitysensor.timer_index=1;
      PORTB=PORTB^0x20;
  }else{
    airqualitysensor.counter++;
  }
}
Gateway (Arduino)
/* Including the SDK and WiFi library */
#include <Grandeur.h>
#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>

SoftwareSerial LORA(D7, D8);

/* Configurations */
String deviceID = "your device id";
String apiKey = "your api key";
String token = "your device token";

/* WiFi credentials */
String ssid = "your wifi ssid";
String password = "your wifi password";

/* Create variable to hold project and device */
Grandeur::Project project;
Grandeur::Project::Device device;

/* Variable to keep track of connection state and time */
int connected = 0;
uint32_t lastUpdate = 0;

String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
//: and % was set from the transmitter node for the eage of data separation
char start_val = ':';
char end_val = '%';
int start_pos = 0;
int end_pos = 0;

float temp = 0;
float humid = 0;
float air = 0;
float noise = 0;

/* Function to check device's connection status */
void onConnection(bool status) {
  switch(status) {
        case CONNECTED:
          Serial.println("Device is connected to the cloud.");
          connected = 1;       
          lastUpdate = millis();
          return;
        case DISCONNECTED:
          Serial.println("Device is disconnected from the cloud.");
          connected = 0;
          return;
  }
}

/* Function to connect to WiFi */
void connectWiFi() {
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
         delay(500);
         Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println(WiFi.localIP());
}

/* Function to confirm that data has been updated */
void dataCallback(const char* code, Var res) {
  if(code == "DEVICE-DATA-UPDATED") {
    double temp_data = (double) res["update"]["temp"];  
    double humid_data = (double) res["update"]["humid"];  
    double noise_data = (double) res["update"]["noise"];  
    double air_data = (double) res["update"]["air"];    
    Serial.printf("Temperature: %f Humidity: %f Noise Level: %f Air Quality: %f\n", temp_data, humid_data, noise_data, air_data);
    return;
  }
  Serial.println("Failed to Update DATA");
  return;
}

/* Function to send updated current and power readings */
void sendUpdate() {
    Var data;
    data["temp"] = temp;
    data["humid"] = humid;
    data["noise"] = noise;
    data["air"] = air;
    device.data().set("temp", temp, dataCallback);
    device.data().set("humid", humid, dataCallback);
    device.data().set("noise", noise, dataCallback);
    device.data().set("air", air, dataCallback);
}

void setup() {
    Serial.begin(9600);
    LORA.begin(115200);
    inputString.reserve(200);
    connectWiFi();   
    project = grandeur.init(apiKey, token);    
    device = project.device(deviceID);    
    project.onConnection(onConnection);
}

void loop() {
    serialEvent();
    project.loop(WiFi.status() == WL_CONNECTED);
    if (stringComplete) {
      process_received_data();
      if (connected) sendUpdate();
    }
}

void serialEvent() {
  while (LORA.available()) {    
    char inChar = (char)LORA.read();     
    if (inChar == '\n') {
      stringComplete = true;
    }
    else
      inputString += inChar;
  }
}

Manufacturing process

  1. Tiny PM2.5 & VOC Sensors Deliver Real‑Time Personal Air‑Quality Monitoring
  2. Bosch Sensortec Unveils AI‑Enabled BME688 Air Quality Sensor to Reduce Virus Transmission Risk
  3. Helium-Based Solar‑Powered Air Quality Sensor: Design & Deployment Guide
  4. Smart Indoor Air Quality & Waste Monitoring System
  5. LoRa‑Enabled COVID‑19 Patient Monitoring System for Remote Health Care
  6. Build a Precise Air Quality Monitor with the Sharp GP2Y1010AU0F Sensor
  7. Arduino-Based Indoor Air Quality & Comfort Sensor Kit
  8. Advanced Indoor Air Quality Monitoring System with Arduino & IoT
  9. Smart Home Monitoring Powered by Alexa
  10. Advanced Carbon‑Based NO₂ Sensor Enhances Indoor Air Quality Monitoring