#include <Arduino.h>
#include <IRremote.hpp>
#include <DHT.h>
// --- Pin Definitions (Corrected) ---
#define DHT_PIN 15
#define DHT_TYPE DHT22
#define IR_RECEIVE_PIN 23 // MOVED to a safe, non-ADC2 pin
#define SMOKE_PIN 34
#define METHANE_PIN 35
#define CO_PIN 32
#define LDR_PIN 36
#define BUTTON_PIN 5
// --- Sensor Objects ---
DHT dht(DHT_PIN, DHT_TYPE);
// --- Hazard & Alert Logic ---
enum HazardLevel { SAFE, ALERT };
HazardLevel currentHazard = SAFE;
volatile bool isAlarmMuted = false;
// --- THRESHOLDS (CRITICAL: These are placeholders and MUST be calibrated) ---
// Calibrate by noting the sensor's reading in clean air, then in a test environment.
const int SMOKE_THRESHOLD = 1500;
const int METHANE_THRESHOLD = 1800;
const int CO_THRESHOLD = 1600;
// --- Non-Blocking Timers ---
unsigned long previousSensorReadMillis = 0;
const long sensorReadInterval = 2000; // Read sensors every 2 seconds
unsigned long lastButtonPressMillis = 0;
const long debounceDelay = 50; // Debounce time for button
void setup() {
Serial.begin(115200);
Serial.println("ShieldSense System Initialized (Corrected Version)");
dht.begin();
// Initialize IR receiver on the new, safe pin
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(SMOKE_PIN, INPUT);
pinMode(METHANE_PIN, INPUT);
pinMode(CO_PIN, INPUT);
pinMode(LDR_PIN, INPUT);
}
void loop() {
unsigned long currentMillis = millis();
// --- Handle Inputs (Non-Blocking) ---
handleButton();
handleIR();
// --- Timed Sensor Reading (Non-Blocking) ---
if (currentMillis - previousSensorReadMillis >= sensorReadInterval) {
previousSensorReadMillis = currentMillis;
// Read all sensors
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
int smokeVal = analogRead(SMOKE_PIN);
int methaneVal = analogRead(METHANE_PIN);
int coVal = analogRead(CO_PIN);
int ldrVal = analogRead(LDR_PIN);
// Check for sensor read errors
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Failed to read from DHT sensor!");
}
// Evaluate the hazard level based on new readings
if (smokeVal > SMOKE_THRESHOLD || methaneVal > METHANE_THRESHOLD || coVal > CO_THRESHOLD) {
currentHazard = ALERT;
} else {
currentHazard = SAFE;
}
// Display the updated status
printStatus(temperature, humidity, smokeVal, methaneVal, coVal, ldrVal);
// Trigger the alarm if necessary
triggerAlarm();
}
}
// --- Input Handling Functions ---
void handleButton() {
// Non-blocking button press check with debounce
if (millis() - lastButtonPressMillis > debounceDelay) {
if (digitalRead(BUTTON_PIN) == LOW) {
toggleMute();
lastButtonPressMillis = millis(); // Reset debounce timer
}
}
}
void handleIR() {
// NOTE: The LDR logic to disable the IR receiver is kept as requested,
// but consider if this feature is truly necessary for your project.
int ldrVal = analogRead(LDR_PIN);
if (ldrVal < 500) { // Dark environment
IrReceiver.start();
if (IrReceiver.decode()) {
Serial.print("IR Code Received: 0x");
Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);
toggleMute();
IrReceiver.resume(); // Prepare for the next signal
}
} else { // Light environment
IrReceiver.stop();
}
}
// --- Alert & Mute Functions ---
void toggleMute() {
isAlarmMuted = !isAlarmMuted;
if (isAlarmMuted) {
Serial.println(">>>> ALARM MUTED <<<<");
} else {
Serial.println(">>>> ALARM UNMUTED <<<<");
}
}
void triggerAlarm() {
if (currentHazard == ALERT && !isAlarmMuted) {
// This is where you would activate a real buzzer or light
Serial.println("!!! HAZARD DETECTED - ALARM ACTIVE !!!");
}
}
// --- Display Function ---
void printStatus(float temp, float hum, int smoke, int methane, int co, int ldr) {
Serial.print("Temp: ");
Serial.print(temp, 1);
Serial.print("°C | Hum: ");
Serial.print(hum, 1);
Serial.print("% | Smoke: ");
Serial.print(smoke);
Serial.print(" | Methane: ");
Serial.print(methane);
Serial.print(" | CO: ");
Serial.print(co);
Serial.print(" | LDR: ");
Serial.print(ldr);
if (currentHazard == ALERT) {
Serial.print(" -> [ALERT]");
} else {
Serial.print(" -> [SAFE]");
}
Serial.println();
}