This circuit is designed to monitor air quality using an MQ-7 gas sensor and provide visual and auditory alerts based on the detected gas levels. The system uses an Arduino Nano microcontroller to process sensor data and control various output devices, including a traffic light, a passive buzzer, a vibration motor, and an OLED display for real-time data visualization.
Arduino Nano
Traffic Light
MQ-7 Breakout
Passive Buzzer
PWM Vibration Motor Sensor Module Switch
128x64 OLED Display (I2C IIC SPI Serial)
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
// Define OLED display size
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// OLED I2C Address and Reset Pin
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Define pins
int LEDRed = 9; // Red LED (Very Dangerous Level)
int LEDYellow = 10; // Yellow LED (Dangerous Level)
int LEDGreen = 11; // Green LED (Normal Level)
int buzzer = 8; // Buzzer
int motor = 7; // Vibration Motor
int smokeA0 = A0; // MQ-7 output connected to A0
// Calibration constants
float V_ref = 5.0; // Reference voltage
float RL = 10.0; // Load resistance in kOhms
float R0 = 10.0; // Sensor baseline resistance in clean air
// Thresholds
float normalThreshold = 100.0;
float dangerousThreshold = 150.0;
float veryDangerousThreshold = 200.0;
// Variables
int analogSensor; // Analog sensor reading
float VRL, Rs, ppm; // Voltage across load, sensor resistance, and ppm value
void setup() {
// Initialize pins
pinMode(LEDRed, OUTPUT);
pinMode(LEDYellow, OUTPUT);
pinMode(LEDGreen, OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(motor, OUTPUT);
pinMode(smokeA0, INPUT);
// Start Serial Monitor
Serial.begin(9600);
// Initialize OLED
if (!display.begin(0x3C, OLED_RESET)) { // I2C address set to 0x3C
Serial.println(F("OLED initialization failed! Check connections."));
for (;;); // Halt execution if OLED fails
}
// Clear and prepare OLED
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("Initializing...");
display.display();
delay(2000); // Show initializing message
}
void loop() {
// Read sensor data
analogSensor = analogRead(smokeA0);
VRL = (analogSensor / 1023.0) * V_ref; // Convert analog value to voltage
// Check for invalid sensor readings
if (analogSensor < 10) { // Threshold for detecting disconnected or invalid sensor
ppm = 0; // Set ppm to 0 for invalid readings
} else {
Rs = RL * ((V_ref - VRL) / VRL); // Calculate sensor resistance
ppm = calculatePPM(Rs / R0); // Calculate ppm from Rs/R0 ratio
}
// Clear OLED and display data
display.clearDisplay();
display.setCursor(0, 0);
display.print("PPM: ");
display.println(ppm);
// LED, Buzzer, and Motor Control Based on Thresholds
if (ppm >= veryDangerousThreshold) {
display.println("Level: VERY DANGEROUS");
activateAlert(LEDRed, 2000, motor, true); // Red LED, continuous buzzer, motor on
} else if (ppm > normalThreshold && ppm <= dangerousThreshold) {
display.println("Level: DANGEROUS");
activateAlert(LEDYellow, 1500, motor, false); // Yellow LED, intermittent buzzer, motor on/off
} else if (ppm <= normalThreshold && ppm > 0) {
display.println("Level: NORMAL");
activateNormal(LEDGreen); // Green LED, no buzzer, motor off
} else {
// No valid readings
display.println("No Sensor Data");
activateNormal(-1); // Turn off all outputs
}
// Display updates
display.display();
// Serial output for debugging
Serial.print("Analog Value: ");
Serial.print(analogSensor);
Serial.print(" | PPM: ");
Serial.println(ppm);
delay(500); // Adjust reading interval
}
// Function to calculate ppm
float calculatePPM(float ratio) {
return pow(10, (log10(ratio) - log10(1.0)) * 0.3 + 2.0); // Replace constants with calibration values if needed
}
// Function to handle dangerous and very dangerous alerts
void activateAlert(int ledPin, int buzzerFrequency, int motorPin, bool continuous) {
digitalWrite(LEDRed, LOW);
digitalWrite(LEDYellow, LOW);
digitalWrite(LEDGreen, LOW);
if (ledPin != -1) digitalWrite(ledPin, HIGH); // Activate corresponding LED
tone(buzzer, buzzerFrequency); // Activate buzzer
if (continuous) {
digitalWrite(motorPin, HIGH); // Keep motor on continuously
} else {
digitalWrite(motorPin, HIGH);
delay(500); // Intermittent motor activation
digitalWrite(motorPin, LOW);
}
}
// Function to handle normal or invalid level
void activateNormal(int ledPin)