Md. Khairul Alam
Published © CC BY

Urban Noise & Air Pollution Monitoring

A solar-powered IoT device for monitoring sound level, air quality, humidity, and temperature.

IntermediateFull instructions provided20 hours9,522

Things used in this project

Hardware components

Argon
Particle Argon
The Argon is a powerful Wi-Fi enabled development board that can act as either a standalone Wi-Fi endpoint or Wi-Fi enabled gateway for Particle Mesh networks. It is based on the Nordic nRF52840 and has built-in battery charging circuitry so it’s easy to connect a Li-Po and deploy your local network in minutes. The Argon is great for connecting existing projects to the Particle Device Cloud or as a gateway to connect an entire group of local endpoints.
×1
DFRobot Gravity: Analog Sound Level Meter
This is an Arduino and Particle compatible sound level meter(also known as decibel meter, noise meter). It uses instrument circuit and low noise microphone, which enable it to accurately measure the sound level of the surrounding environment. This product uses instrument circuit, low noise microphone, which make it highly precious. It supports 3.3~5.0V wide input voltage, 0.6~2.6V voltage output. The decibel value is linear with the output voltage, which leads to a simple conversion, without complex algorithm. The connector is plug-and-play, without welding, so this product can be easily used in your application. It can be applied to environmental noise testing, such as highway noise monitoring station, bedroom noise monitoring, etc.
×1
Grove - Air quality sensor v1.3
Seeed Studio Grove - Air quality sensor v1.3
This sensor is designed for comprehensive monitor over indoor air condition. It's responsive to a wide scope of harmful gases, as carbon monoxide, alcohol, acetone, thinner, formaldehyde and so on. Due to the measuring mechanism, this sensor can't output specific data to describe target gases' concentrations quantitatively. But it's still competent enough to be used in applications that require only qualitative results, like auto refresher sprayers and auto air cycling systems.
×1
Seeed Studio Grove - Temperature & Humidity Sensor (DHT11)
DHT11 is the most common temperature and humidity module for Arduino and Raspberry Pi. It is widely favored by hardware enthusiasts for its many advantages. E.g. Low power consumption and excellent long-term stability. Relatively high measurement accuracy can be obtained at a very low cost. The single-bus digital signal is output through the built-in ADC, which saves the I/O resources of the control board.
×1
Solar Power Manager 5V
DFRobot Solar Power Manager 5V
Solar Power Manager 5V is a small power and high-efficiency solar power management module designed for 5V solar panel. It features as MPPT (Maximum Power Point Tracking) function, maximizing the efficiency of the solar panel. The module can provide up to 900mA charging current to 3.7V Li battery with USB charger or solar panel. The ON/OFF controllable DC-DC converters with 5V 1A output satisfies the needs of various solar power projects and low-power applications. The module also employs various protection functions for battery, solar panel and output, which greatly improves the stability and safety of your solar projects.
×1
DFRobot Monocrystalline Solar Panel (5V 1A)
This is a high-performance, lightweight, portable monocrystalline silicon solar panel in a PET package, with an integrated voltage regulator output of 5V, with working indicators, USB type-A mother-port output, plug-and-play. It can supply plenty of power in various environments to prevent the system from shutting down, even in rainy days.
×1
GPS receiver (generic)
Use any UART compatible GPS receiver. I used NEO-6M GPS module for my project.
×1
Battery Holder, 18650 x 2
Battery Holder, 18650 x 2
×1
Rechargeable Battery, Lithium Ion
Rechargeable Battery, Lithium Ion
I used 2400mAh 18650 Li-ion rechargeable cell. I connected two cells in parallel for doubling the capacity.
×1
Gravity: DHT11 Temperature Humidity Sensor For Arduino
DFRobot Gravity: DHT11 Temperature Humidity Sensor For Arduino
Optional. You can either use Grove DHT11 or GravityDHT11.
×1

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE
Ubidots
Ubidots
Ubidots is an Internet of Things (IoT) data analytics and visualization service. It turns sensor data into information that matters for business-decisions, machine-to-machine interactions, educational research, and increase economization of global resources. Ubidots exists as an easy and affordable means to integrate the power of the IoT into your business or research.
Firebase
Google Firebase
Firebase Realtime database is a cloud hosted database that supports multiple platforms Android, iOS and Web. All the data is stored in JSON format and any changes in data, reflects immediately by performing sync across all the platforms & devices. This allows us to build more flexible realtime apps easily with minimal effort.
Maker service
IFTTT Maker service
IFTTT users build Applets (recipes), which are comprised of a Trigger and an Action (cause and effect). Through the IFTTT Maker Webhooks service, users will be able to use your Laravel Notifications as triggers to perform a multitude of actions on the IFTTT service.
Google Sheets
Google Sheets
Google Sheets is a spreadsheet program included as part of a free, web-based software office suite offered by Google within its Google Drive service. The app allows users to create and edit files online while collaborating with other users in real-time.
Zapier
Zapier is an online platform that aims to connect various apps together to automate workflows easily in the business or even for personal productivity. With its powerful technology, Zapier moves information between user web apps automatically, so users can focus on the more important work at hand. More: https://www.process.st/what-is-zapier/
MIT App Inventor 2
MIT App Inventor 2
MIT App Inventor is basically for creating Android Apps in your browser where you design how the app will look and function. Like fitting together puzzle pieces, you set how your app will behave to different events by simply signing in with your Gmail Account. Making custom Applications for Android OS can be difficult unless you have a deep understanding of Java. MIT's App Inventor removes that barrier by providing an easy to use drag and drop style of coding to App development.

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free
Mastech MS8217 Autorange Digital Multimeter
Digilent Mastech MS8217 Autorange Digital Multimeter

Story

Read more

Schematics

System Block Diagram

Schematic Diagram

Screenshot of the App

Screenshot of the app when email sent

Code

Source Code

Arduino
The code was developed using Particle WebIDE.
//All external libraries are added here
#include "Particle.h"
#include "Adafruit_DHT.h"
#include <Air_Quality.h>
#include "Arduino.h"
#include <TinyGPS++/TinyGPS++.h>


#define DHTPIN 2     // what pin DHT11 sensor is connected to
#define DHTTYPE DHT11		// Type of DHT sensor
#define SoundSensorPin A1  //this pin read the analog voltage from the sound level meter
#define VREF  5.0  //voltage on AREF pin, default:operating voltage

//Object declaration for DHT sensor
DHT dht(DHTPIN, DHTTYPE);

//Object declaration for air quality sensor
//AirQuality airqualitysensor;

//Object declaration for GPS
TinyGPSPlus gps;

//Global variables for the sensor data
char air_quality[20] = "";
float temperature = 0.0;
float humidity = 0.0;
float dbValue = 0.0;
float latitude = 0.0;
float longitude = 0.0;

float startTime;

int current_quality =-1;

bool requestSent = false;
void hookResponseHandler(const char *event, const char *data);


void setup() {
    
	Serial1.begin(9600);      //default buad rate for NEO-6M gps is 9600
	dht.begin();              //initialize dht sensor
	airqualitysensor.init(A0);//initialize air quality sensor
	//receive response after publishing data to particle cloud
	Particle.subscribe("hook-response/Ubidots", hookResponseHandler, MY_DEVICES);
	startTime = millis();     //time count start
}

void loop() {
    if (millis() > startTime + 30000) {    //publish data every 30 second
       startTime = millis();
	   //all the global variables are automatically updated on functions call
       read_dht_value();
       read_air_quality();
       read_sound_level();
       publish_data();
       delay(1000);
    }
     
    while (Serial1.available() > 0){
       if (gps.encode(Serial1.read())){
           if (gps.location.isValid()){
              latitude = gps.location.lat();    //get latitude and longitude
              longitude = gps.location.lng();
           }
       }
    }
    delay(5000); //Check for gps data every 5 seconds
}

void hookResponseHandler(const char *event, const char *data) {
	float elevation = atof(data);
}

//this function reads temperature and humidity from dht11 sensor
void read_dht_value() {
    //Reading temperature or humidity takes about 250 milliseconds!
    //Sensor readings may also be up to 2 seconds 'old' (its a 
    // very slow sensor)
	float h = dht.getHumidity();
    //Read temperature as Celsius
	float t = dht.getTempCelcius();
    // Check if any reads failed and exit early (to try again).
	if (isnan(h) || isnan(t)) {
		return;
	}
    else {
        temperature = t;
        humidity = h;
    }
}

//this function reads the quality of the air
void read_air_quality()
{
    current_quality=airqualitysensor.slope();
    if (current_quality >= 0)// if a valid data returned.
    {
        if (current_quality==0)
            air_quality = "Very High pollution";
        else if (current_quality==1)
            air_quality = "High pollution";
        else if (current_quality==2)
            air_quality = "Low pollution";
        else if (current_quality ==3)
            air_quality = "Fresh air";
    }
}

//interrupt service routine for air quality sensor
ISR(TIMER2_OVF_vect)
{
    if(airqualitysensor.counter==122)//set 2 seconds as a detected duty
    {
        airqualitysensor.last_vol=airqualitysensor.first_vol;
        airqualitysensor.first_vol=analogRead(A0);
        airqualitysensor.counter=0;
        airqualitysensor.timer_index=1;
        PORTB=PORTB^0x20;
    }
    else
    {
        airqualitysensor.counter++;
    }
}

// This function read the data from sound sensor and convert the value into decibel. 
void read_sound_level()
{
    float voltageValue;
    voltageValue = analogRead(SoundSensorPin) / 1024.0 * VREF;
    dbValue = voltageValue * 5.0;  //convert voltage to decibel value
}


void publish_data(){
    char data[256];
	char data1[256];
	//I made two data array because ubidots required position value with a context, firebase doesn't 
    snprintf(data, sizeof(data), "{\"position\": {\"value\":1, \"context\":{\"lat\": %.6f, \"lng\": %.6f}}, \"temp\":%.2f, \"noise\":%.2f, \"air\": {\"value\":1, \"context\":{\"quality\": \"%s\"}}, \"humid\":%.2f}",
    latitude, longitude, temperature, dbValue, air_quality, humidity);

    snprintf(data1, sizeof(data1), "{\"lat\": %.6f, \"lng\": %.6f, \"temp\":%.2f, \"noise\":%.2f, \"air\":\"%s\", \"humid\":%.2f}",
    latitude, longitude, temperature, dbValue, air_quality, humidity);

    Particle.publish("Ubidots", data, PRIVATE);  //trigger webhooks for Ubidots
    Particle.publish("Google_Sheet", data1, PRIVATE); //trigger webhook to Zapier for uploading to Google Sheet
	Particle.publish("Firebase", data1, PRIVATE);  //Store data to firebase
	Particle.publish("Firebase_put", data1, PRIVATE); //Update data to firebase.
	//The main difference here is that the requestType is PUT, not POST. The PUT method doesn't create a table of values; 
	//it just creates a single element to hold the data, overwriting any previous data at that location.
}

Android Source

HTML
Developed in MIT App Inventor 2
No preview (download only).

Android App

HTML
APK file
No preview (download only).

Credits

Md. Khairul Alam

Md. Khairul Alam

64 projects • 567 followers
Developer, Maker & Hardware Hacker. Currently working as a faculty at the University of Asia Pacific, Dhaka, Bangladesh.

Comments