🔥 سیستم اعلام حریق با آردوینو: سنسور گاز MQ-2، سنسور دما، آژیر و ریست (کد کامل)

✍️ تیم ووکوی فارسی ·

در این پروژه یک سیستم اعلام حریق با آردوینو می‌سازیم که سه نشانه‌ی آتش را زیر نظر دارد: دود و گاز با سنسور MQ-2، دمای بالا و افزایش ناگهانی دما با سنسور TMP36. دو سطح هشدار دارد (احتیاط و خطر)، آژیر دوصدا می‌زند، یک رله برای فن تخلیه یا آژیر بیرونی روشن می‌کند و مثل پنل‌های واقعی، هشدارش «قفل» می‌شود تا کسی ریستش کند. همه‌چیز را اول در شبیه‌ساز آردوینو می‌سازیم؛ بدون فندک و بدون دود.

⚠️ این پروژه آموزشی است و جای دتکتور دود و گاز استاندارد را نمی‌گیرد. برای امتحان آن هرگز آتش روشن نکن و گاز آزاد نکن؛ در شبیه‌ساز مقدار گاز و دما را با کلیک روی سنسورها عوض کن.

دستگاه چطور تصمیم می‌گیرد؟

وضعیتشرطخروجی
گرم شدن۲۰ ثانیه‌ی اول بعد از روشن شدنLED سبز چشمک می‌زند
عادیهمه‌چیز زیر آستانهLED سبز روشن
احتیاطگاز ≥ ۳۰۰ یا دما ≥ ۴۵ درجهLED زرد و یک بوق کوتاه هر دو ثانیه
خطرگاز ≥ ۴۵۰، یا دما ≥ ۵۷ درجه، یا ۸ درجه افزایش در حدود یک دقیقه، یا شعلهLED قرمز چشمک‌زن، آژیر دوصدا، رله روشن

عدد ۵۷ درجه از دتکتورهای حرارتی ثابت می‌آید و «افزایش سریع» از دتکتورهای نرخ افزایش: آتش واقعی دما را خیلی تند بالا می‌برد، در حالی که یک روز گرم تابستان آرام گرم می‌شود.

قطعه‌ها

سیم‌کشی

قطعهپایهبه آردوینو
MQ-2+ / OUT (آنالوگ) / −5V / A0 / GND
TMP36+ / OUT / −5V / A1 / GND
دکمهدو پایه‌ی روبه‌روD2 و GND
سنسور شعله (اختیاری)DO / VCC / GNDD3 / 5V / GND
رلهIN / VCC / GNDD4 / 5V / GND
LED سبز، زرد، قرمزپایه‌ی بلند از راه ۲۲۰ اهمD5، D6، D7؛ پایه‌ی کوتاه به GND
بازر+ / −D8 / GND

کد کامل

// Fire and gas alarm: MQ-2 smoke/gas sensor + TMP36 heat sensor
// (+ optional flame sensor), three LEDs, a two-tone siren and a relay.
const int GAS_PIN    = A0;   // MQ-2 analog output
const int TEMP_PIN   = A1;   // TMP36 output
const int BUTTON_PIN = 2;    // silence / reset button to GND
const int FLAME_PIN  = 3;    // optional flame sensor DO (LOW = flame)
const int RELAY_PIN  = 4;    // exhaust fan or external siren (low voltage!)
const int GREEN_PIN  = 5;
const int YELLOW_PIN = 6;
const int RED_PIN    = 7;
const int BUZZER_PIN = 8;

const bool HAS_FLAME_SENSOR = false;   // true if you wired a flame sensor
const int GAS_WARN  = 300;             // calibrate in clean air first!
const int GAS_ALARM = 450;
const float TEMP_WARN  = 45.0;         // C
const float TEMP_ALARM = 57.0;         // C, a common fixed-heat detector level
const float RISE_ALARM = 8.0;          // C rise within about one minute
const unsigned long WARMUP_MS  = 20000;  // MQ-2 heater warm-up
const unsigned long SILENCE_MS = 60000;  // the button mutes the siren this long

enum State { WARMUP, NORMAL, WARNING, ALARM };
State state = WARMUP;
bool latched = false;      // an alarm stays on until someone resets it
bool silenced = false;
unsigned long silencedAt = 0, lastMinute = 0, lastReport = 0;
int gas = 0;
float tempC = 25.0, tempMinuteAgo = 25.0;

void readSensors() {
  gas = (gas * 3 + analogRead(GAS_PIN)) / 4;      // smooth the noisy MQ-2
  float volts = analogRead(TEMP_PIN) * 5.0 / 1023.0;
  tempC = (volts - 0.5) * 100.0;                   // TMP36: 0.5 V at 0 C, 10 mV per C
}

State evaluate() {
  bool flame = HAS_FLAME_SENSOR && digitalRead(FLAME_PIN) == LOW;
  bool fastRise = tempC - tempMinuteAgo >= RISE_ALARM;
  if (flame || gas >= GAS_ALARM || tempC >= TEMP_ALARM || fastRise) return ALARM;
  if (gas >= GAS_WARN || tempC >= TEMP_WARN) return WARNING;
  return NORMAL;
}

bool buttonPressed() {
  static bool last = HIGH;
  static unsigned long changedAt = 0;
  bool reading = digitalRead(BUTTON_PIN);
  if (reading != last && millis() - changedAt > 50) {   // 50 ms debounce
    changedAt = millis();
    last = reading;
    return reading == LOW;
  }
  return false;
}

void setTone(int freq) {
  static int current = -1;
  if (freq == current) return;    // only touch the buzzer when the sound changes
  current = freq;
  if (freq > 0) tone(BUZZER_PIN, freq);
  else noTone(BUZZER_PIN);
}

void updateOutputs(unsigned long now) {
  bool fast = (now / 250) % 2;    // flips every 250 ms
  digitalWrite(GREEN_PIN,  (state == NORMAL || (state == WARMUP && fast)) ? HIGH : LOW);
  digitalWrite(YELLOW_PIN, state == WARNING ? HIGH : LOW);
  digitalWrite(RED_PIN,    (state == ALARM && fast) ? HIGH : LOW);
  digitalWrite(RELAY_PIN,  state == ALARM ? HIGH : LOW);

  if (state == ALARM && !silenced) setTone(fast ? 1300 : 900);              // two-tone siren
  else if (state == WARNING && !silenced && now % 2000 < 150) setTone(2000); // short chirp
  else setTone(0);
}

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(FLAME_PIN, INPUT_PULLUP);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(YELLOW_PIN, OUTPUT);
  pinMode(RED_PIN, OUTPUT);
  gas = analogRead(GAS_PIN);
  Serial.println("Fire alarm: warming up the gas sensor...");
}

void loop() {
  unsigned long now = millis();
  readSensors();

  if (state == WARMUP) {
    if (now >= WARMUP_MS) {
      state = NORMAL;
      tempMinuteAgo = tempC;
      lastMinute = now;
      Serial.println("Ready.");
    }
  } else {
    if (now - lastMinute >= 60000) {   // remember the temperature once a minute
      tempMinuteAgo = tempC;
      lastMinute = now;
    }
    State s = evaluate();
    if (s == ALARM) latched = true;
    if (latched) s = ALARM;

    if (buttonPressed()) {
      if (latched && evaluate() != ALARM) {   // danger is gone: reset
        latched = false;
        silenced = false;
        s = evaluate();
        Serial.println("Reset.");
      } else if (s != NORMAL) {               // still dangerous: just mute
        silenced = true;
        silencedAt = now;
        Serial.println("Siren silenced for 60 s.");
      }
    }
    if (silenced && now - silencedAt > SILENCE_MS) silenced = false;
    if (s == NORMAL) silenced = false;

    if (s != state) {
      state = s;
      if (state == ALARM) Serial.println("!!! ALARM !!!");
      else if (state == WARNING) Serial.println("Warning");
      else Serial.println("Normal");
    }
  }

  updateOutputs(now);

  if (now - lastReport >= 500) {       // name:value pairs for the Serial Plotter
    lastReport = now;
    Serial.print("gas:");
    Serial.print(gas);
    Serial.print(" temp:");
    Serial.println(tempC);
  }
  delay(20);
}

توضیح بخش‌های مهم

قدم‌به‌قدم در شبیه‌ساز

  1. قطعه‌ها را طبق جدول بچین و سیم بزن. اگر جایی اشتباه وصل شده باشد، دکمه‌ی «چرا کار نمی‌کند؟» به فارسی می‌گوید کدام سیم.
  2. کد را اجرا کن. ۲۰ ثانیه LED سبز چشمک می‌زند و بعد «Ready.» در سریال مانیتور می‌آید.
  3. زبانه‌ی نمودار را باز کن؛ دو خط gas و temp را زنده می‌بینی.
  4. روی سنسور گاز کلیک کن و مقدارش را کم‌کم بالا ببر. اول LED زرد و بوق کوتاه، بعد آژیر و LED قرمز.
  5. گاز را پایین بیاور: آژیر هنوز می‌زند (قفل). دکمه را بزن تا ریست شود.
  6. دما را یک‌باره ۱۰ درجه بالا ببر تا هشدار «افزایش سریع» را ببینی.

آردوینو اونو در تینکرکد فارسی رایگان است و این پروژه کاملاً بدون اشتراک اجرا می‌شود. برای پروژه‌ی آماده‌ی مشابه، دزدگیر کامل و درس سیستم امنیتی را ببین. برای آشنایی دقیق‌تر با خود سنسور، سنسور گاز MQ-2 با آردوینو را بخوان.

کالیبره کردن روی نمونه‌ی واقعی

عدد MQ-2 به دما، رطوبت و حتی خود سنسور بستگی دارد. سنسور را چند دقیقه در هوای تمیز روشن بگذار، عدد gas را در نمودار ببین و آستانه‌ی احتیاط را حدود ۱۵۰ واحد بالاتر از آن و آستانه‌ی خطر را حدود ۳۰۰ واحد بالاتر بگذار. برای تست، فقط با نظارت بزرگ‌تر و از فاصله، چند ثانیه بخار الکل یا اسپری مخصوص تست دتکتور کافی است؛ هرگز شعله یا گاز شهری. گرم‌کن MQ-2 حدود ۱۵۰ میلی‌آمپر می‌کشد و داغ می‌شود؛ آن را در جعبه‌ی سوراخ‌دار نصب کن و اگر پروژه با باتری کار می‌کند، عمر باتری را حساب کن.

اشکال‌های رایج

قدم‌های بعدی

یک ماژول رله می‌تواند به‌جای فن یک آژیر ۱۲ ولتی را روشن کند. با یک LCD I2C عددها را روی دستگاه نشان بده، یا پروژه را به ESP32 ببر تا هشدار در گوشی هم بیاید؛ ایده‌اش در ۳۰ ایده پروژه اینترنت اشیا هست.

اعلام حریق را رایگان در شبیه‌ساز بساز 🔥

سؤال‌های رایج

می‌شود این پروژه را به‌جای دتکتور دود واقعی در خانه نصب کرد؟

نه. این یک پروژه‌ی آموزشی است. دتکتورهای استاندارد آزمون‌های ایمنی سخت را گذرانده‌اند و باتری پشتیبان دارند. این دستگاه را برای یادگیری، نمایشگاه و هشدار کمکی بساز، نه جایگزین تجهیزات استاندارد.

چرا هشدار بعد از پاک شدن هوا خاموش نمی‌شود؟

چون «قفل‌شونده» است، مثل پنل‌های اعلام حریق واقعی. اگر آتش یک لحظه شعله کشید و خاموش شد، کسی باید بفهمد و بررسی کند. فقط وقتی خطر رفع شده باشد، دکمه هشدار را ریست می‌کند.

سنسور MQ-2 چقدر طول می‌کشد تا آماده شود؟

گرم‌کن داخلی‌اش در دقیقه‌های اول عدد ناپایدار می‌دهد. برای استفاده‌ی واقعی چند دقیقه صبر کن و برای دقت بیشتر سنسور نو را یک بار ۲۴ ساعت روشن بگذار. در کد ۲۰ ثانیه گذاشته‌ایم تا در شبیه‌ساز منتظر نمانی.

مقاله‌های مرتبط

🅿️

پارکینگ هوشمند با آردوینو: دو سنسور اولتراسونیک، راهبند سروو و نمایش جای خالی روی LCD

💡

۳۰ ایده پروژه اینترنت اشیا با ESP32، از مبتدی تا پیشرفته (با قطعه‌ها و نقطه‌ی شروع)

🎓

پروژه پایانی دانشگاه با میکروکنترلر: از انتخاب موضوع تا دفاع (برای دانشجوی برق، کامپیوتر و مکاترونیک)

🌡️

صفحه‌ی وب دما و رطوبت با سنسور DHT روی ESP32

همه‌ی آموزش‌های پروژه‌ها و ایده‌ها ← · همه‌ی مقاله‌ها