Rectronx Circuits
Back to Blog
Tutorial Projek Akhir Tahun8 min read2026-06-17

Tutorial Projek Akhir Tahun: Cara Bina Sistem Pengesanan Gas LPG dan Kebakaran dengan Kawalan Injap Automatik

Bina sistem keselamatan IoT yang boleh kesan kebocoran gas LPG, asap kebakaran, dan api secara serentak, kemudian tutup injap gas dan hantar amaran kecemasan. Tutorial dengan sensor MQ-2, MQ-6, flame sensor, solenoid valve fail-safe, dan ESP32.

R

Rectronx

2026-06-17

Gas sensor and electronic detection circuit

Tutorial Projek Akhir Tahun: Cara Bina Sistem Pengesanan Gas LPG dan Kebakaran dengan Kawalan Injap Automatik

Kebakaran rumah di Malaysia — banyak daripadanya berpunca daripada kebocoran gas LPG yang tidak dikesan — menyebabkan kehilangan nyawa dan harta benda setiap tahun. Bomba Malaysia menerima ribuan panggilan berkaitan kebakaran dapur dan ledakan gas setiap tahun.

Projek FYP ini membina sistem keselamatan IoT yang komprehensif: kesan gas LPG, asap, DAN api secara serentak, tutup bekalan gas secara automatik sebaik kebocoran dikesan, dan hantar amaran kepada penghuni serta pihak bomba melalui tiga peringkat alert yang berbeza.


Kenapa Projek Ini Outstanding untuk FYP?

Sistem tiga lapis: Kebanyakan projek keselamatan hanya ada satu sensor. Projek ini guna sensor fusion — tiga jenis sensor secara serentak untuk kurangkan false positive dan tingkatkan kebolehpercayaan. Ini adalah reka bentuk sistem yang matang.

Fail-safe design: Penggunaan solenoid valve NC (Normally Closed) memastikan bahawa walaupun sistem terputus kuasa atau ESP32 crash, bekalan gas tetap diputuskan. Ini adalah konsep defence-in-depth dalam kejuruteraan keselamatan.

Tiga peringkat alert: Amaran awal (pra-berbahaya), amaran bahaya, dan amaran kecemasan — masing-masing dengan tindak balas yang berbeza. Ini menunjukkan pemikiran sistem yang terstruktur.


Senarai Komponen

KomponenSpesifikasiAnggaran Harga
ESP32 Development Board38-pinRM 20–28
Sensor Gas MQ-2LPG, Butana, Propana, Asap, H2RM 8–12
Sensor Gas MQ-6LPG, Butana, Propana (lebih spesifik)RM 8–12
Sensor Nyala Api (Flame Sensor)IR, 760–1100nm, 60°RM 5–8
Solenoid Valve NC12V DC, 1/2" BSPRM 25–40
Modul Relay1-channel, 5VRM 4–6
Buzzer Kuat12V, 95dBRM 8–12
LED Merah, Kuning, Hijau5mmRM 2
Ekzos/Exhaust Fan Kecil5V atau 12V, 80mmRM 15–20
Relay KeduaUntuk fanRM 4–6
OLED 0.96"I2C, SSD1306RM 10–15
Buck Converter 12V→5VUntuk ESP32 dari supply solenoidRM 5–8
Resistor Set220Ω, 10kΩRM 3

Jumlah anggaran: RM 117–172


Sistem Tiga Peringkat Alert

PeringkatTriggerTindakan
⚠️ WASPADAGas > 30% dari threshold maksimumLED kuning, Telegram amaran awal
🚨 BAHAYAGas > 70% threshold ATAU nyala api kesanLED merah, buzzer, tutup gas, hidupkan fan
🆘 KECEMASANGas > 100% threshold DAN apiSemua amaran, Telegram kecemasan, cadangkan hubungi Bomba

Gambarajah Pendawaian

Sensor MQ-2 ke ESP32:

  • VCC → 5V, GND → GND
  • AO (Analog) → GPIO36, DO (Digital) → GPIO34

Sensor MQ-6 ke ESP32:

  • VCC → 5V, GND → GND
  • AO → GPIO39, DO → GPIO35

Flame Sensor ke ESP32:

  • VCC → 3.3V, GND → GND
  • DO (Digital) → GPIO32 (api = LOW)
  • AO (Analog) → GPIO33

Solenoid Valve NC via Relay:

  • Relay IN → GPIO26
  • Relay COM → 12V, Relay NO → Solenoid terminal
  • Dioda flyback 1N4007 selari solenoid

Exhaust Fan via Relay 2:

  • Relay 2 IN → GPIO27
  • Sambung fan ke relay dalam konfigurasi yang sama

LED & Buzzer:

  • LED Hijau → GPIO14 → 220Ω → GND
  • LED Kuning → GPIO12 → 220Ω → GND
  • LED Merah → GPIO13 → 220Ω → GND
  • Buzzer → GPIO25

Kod Arduino/ESP32

#include <Wire.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const char* WIFI_SSID     = "NamaWiFiKau";
const char* WIFI_PASSWORD = "PasswordWiFi";
const char* BOT_TOKEN     = "TOKEN_BOT_TELEGRAM";
const char* CHAT_ID       = "CHAT_ID_KAU";

// Pins
#define MQ2_AO     36
#define MQ6_AO     39
#define FLAME_DO   32
#define FLAME_AO   33
#define RELAY_GAS  26   // LOW = buka gas, HIGH = tutup gas (active HIGH untuk NC valve)
#define RELAY_FAN  27
#define LED_GREEN  14
#define LED_YELLOW 12
#define LED_RED    13
#define BUZZER_PIN 25

// Threshold (perlu kalibrasi mengikut sensor sebenar)
#define GAS_WASPADA  800   // ADC value — ~30% dari maksimum
#define GAS_BAHAYA   2000  // ADC value — ~70% dari maksimum
#define GAS_KRITIKAL 3000  // ADC value

// Status peringkat
enum AlertLevel { SELAMAT, WASPADA, BAHAYA, KECEMASAN };
AlertLevel tahapSemasa = SELAMAT;
AlertLevel tahapLepas  = SELAMAT;

bool gasValveOpen = true; // True = valve BUKA (gas mengalir)
bool fanRunning   = false;

Adafruit_SSD1306 display(128, 64, &Wire, -1);
WiFiClientSecure client;
UniversalTelegramBot bot(BOT_TOKEN, client);

unsigned long lastTelegramSent = 0;
unsigned long warmUpEnd = 0;
bool warmUpDone = false;

void bukaGas() {
  digitalWrite(RELAY_GAS, LOW); // LOW = relay OFF = solenoid NC = tutup gas...
  // NOTA: Bergantung kepada jenis relay (active HIGH atau LOW) dan sambungan COM/NC/NO
  // Verify dengan multimeter sebelum sambung gas sebenar!
  gasValveOpen = true;
}

void tutupGas() {
  digitalWrite(RELAY_GAS, HIGH);
  gasValveOpen = false;
}

void hidupFan() {
  digitalWrite(RELAY_FAN, LOW);
  fanRunning = true;
}

void matiFan() {
  digitalWrite(RELAY_FAN, HIGH);
  fanRunning = false;
}

void setLED(AlertLevel tahap) {
  digitalWrite(LED_GREEN,  tahap == SELAMAT  ? HIGH : LOW);
  digitalWrite(LED_YELLOW, tahap == WASPADA  ? HIGH : LOW);
  digitalWrite(LED_RED,    (tahap == BAHAYA || tahap == KECEMASAN) ? HIGH : LOW);
}

void hantarTelegram(String msg) {
  if (millis() - lastTelegramSent < 30000) return;
  bot.sendMessage(CHAT_ID, msg, "Markdown");
  lastTelegramSent = millis();
  Serial.println("Telegram dihantar");
}

AlertLevel tentukan_tahap(int mq2, int mq6, bool ada_api) {
  int gasMax = max(mq2, mq6);

  if (ada_api && gasMax > GAS_BAHAYA) return KECEMASAN;
  if (ada_api || gasMax > GAS_BAHAYA) return BAHAYA;
  if (gasMax > GAS_WASPADA) return WASPADA;
  return SELAMAT;
}

void kendalikanTahap(AlertLevel tahap, int mq2, int mq6, bool ada_api) {
  setLED(tahap);

  switch (tahap) {
    case SELAMAT:
      noTone(BUZZER_PIN);
      if (!gasValveOpen) bukaGas();
      matiFan();
      break;

    case WASPADA:
      noTone(BUZZER_PIN);
      if (tahap != tahapLepas) {
        hantarTelegram("⚠️ *WASPADA GAS*\nGas dikesan pada tahap rendah. Sila periksa kawasan dapur.\n"
                       "MQ2: " + String(mq2) + " | MQ6: " + String(mq6));
      }
      break;

    case BAHAYA:
      tone(BUZZER_PIN, 1500, 500);
      tutupGas();
      hidupFan();
      if (tahap != tahapLepas) {
        hantarTelegram("🚨 *BAHAYA! KEBOCORAN GAS DIKESAN!*\n\n"
                       "MQ2: " + String(mq2) + " | MQ6: " + String(mq6) + "\n"
                       "Api: " + String(ada_api ? "KESAN" : "Tidak") + "\n\n"
                       "⛔ Bekalan gas *DIPUTUSKAN* automatik\n"
                       "💨 Kipas ekzos *DIHIDUPKAN*\n\n"
                       "Sila keluar dari kawasan dan pastikan tingkap terbuka!");
      }
      break;

    case KECEMASAN:
      tone(BUZZER_PIN, 2000);
      tutupGas();
      hidupFan();
      if (tahap != tahapLepas) {
        hantarTelegram("🆘 *KECEMASAN! GAS + API DIKESAN!*\n\n"
                       "BAHAYA LETUPAN/KEBAKARAN!\n\n"
                       "⛔ Gas diputuskan\n"
                       "🚒 Hubungi Bomba: *994*\n"
                       "⚡ Matikan suis utama elektrik\n"
                       "🏃 KELUAR SEGERA!");
      }
      break;
  }
}

void kemaskiniOLED(int mq2, int mq6, bool api) {
  const char* statusStr[] = {"SELAMAT", "WASPADA", "BAHAYA", "KECEMASAN"};

  display.clearDisplay();
  display.setCursor(0, 0);
  display.print("SISTEM KESELAMATAN GAS");
  display.drawLine(0, 9, 127, 9, SSD1306_WHITE);
  display.setCursor(0, 12);
  display.printf("MQ2:  %d\n", mq2);
  display.printf("MQ6:  %d\n", mq6);
  display.printf("Api:  %s\n", api ? "KESAN!" : "Tiada");
  display.printf("Gas:  %s\n", gasValveOpen ? "BUKA" : "TUTUP");
  display.printf("Fan:  %s\n", fanRunning ? "ON" : "OFF");
  display.setCursor(0, 55);
  display.printf("[%s]", statusStr[tahapSemasa]);
  display.display();
}

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);

  pinMode(RELAY_GAS,  OUTPUT); pinMode(RELAY_FAN, OUTPUT);
  pinMode(LED_GREEN,  OUTPUT); pinMode(LED_YELLOW, OUTPUT);
  pinMode(LED_RED,    OUTPUT); pinMode(BUZZER_PIN, OUTPUT);
  pinMode(FLAME_DO, INPUT);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);

  // Mulakan valve dalam keadaan BUKA (gas mengalir secara normal)
  bukaGas(); matiFan();
  setLED(SELAMAT);

  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Warm-up sensor...");
  display.println("Sila tunggu 30 saat");
  display.display();

  warmUpEnd = millis() + 30000;

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) { delay(500); }
  client.setInsecure();

  Serial.println("WiFi bersambung. Menunggu warm-up sensor...");
}

void loop() {
  if (!warmUpDone && millis() < warmUpEnd) {
    display.setCursor(0, 32);
    display.printf("Tinggal: %ds    ", (warmUpEnd - millis()) / 1000);
    display.display();
    delay(500);
    return;
  }

  if (!warmUpDone) {
    warmUpDone = true;
    bot.sendMessage(CHAT_ID, "✅ Sistem Pengesanan Gas & Kebakaran AKTIF.\nSistem memantau kawasan dapur.", "");
    display.clearDisplay();
    display.display();
  }

  int mq2Val   = analogRead(MQ2_AO);
  int mq6Val   = analogRead(MQ6_AO);
  bool adaApi  = (digitalRead(FLAME_DO) == LOW);

  tahapLepas  = tahapSemasa;
  tahapSemasa = tentukan_tahap(mq2Val, mq6Val, adaApi);

  kendalikanTahap(tahapSemasa, mq2Val, mq6Val, adaApi);
  kemaskiniOLED(mq2Val, mq6Val, adaApi);

  Serial.printf("MQ2:%d MQ6:%d Api:%s Tahap:%d\n", mq2Val, mq6Val, adaApi ? "YA" : "TIDAK", tahapSemasa);

  delay(500); // Semak setiap 500ms untuk response pantas
}

Langkah Demi Langkah

Langkah 1 — Warm-up Sensor MQ Sensor MQ memerlukan masa warm-up 2–5 minit sebelum bacaan stabil. Pastikan sistem dihidupkan beberapa minit sebelum digunakan. Kod sudah ada timer warm-up 30 saat sebagai minimum.

Langkah 2 — Kalibrasi Threshold Dalam Persekitaran Selamat Ambil bacaan baseline dalam udara bersih. Kemudian uji dengan gas LPG dalam kuantiti sangat kecil (semburan ringan dari pemetik api yang ditekan tanpa menyala) dan rekod nilai ADC. Tetapkan threshold berdasarkan data sebenar ini.

Langkah 3 — Verify Logik Relay SEBELUM Sambung Gas Ini langkah KRITIKAL. Guna multimeter untuk pastikan relay berfungsi betul sebelum sambung solenoid gas. Verify: bila ESP32 kasi signal HIGH pada relay, adakah solenoid dapat kuasa atau tidak? Pastikan logik betul.

Langkah 4 — Test Sistem Lengkap Tanpa Gas Test semua fungsi — LED, buzzer, fan, Telegram — tanpa melibatkan gas. Guna asap daripada dupa (incense stick) untuk trigger sensor asap.

Langkah 5 — Packaging yang Selamat Pastikan semua komponen elektrik dalam kotak yang tidak boleh jadi punca pencetus api. Jauhkan komponen electronic daripada kawasan yang mungkin ada gas. Letak sensor pada ketinggian yang betul (LPG lebih berat dari udara, kumpul di bawah).


Tips Pembentangan

  • Jelaskan prinsip NC fail-safe: Ini biasanya mencuri markah dalam FYP keselamatan — panel faham implikasinya.
  • Terangkan sensor fusion: Mengapa guna MQ-2 DAN MQ-6? MQ-2 lebih sensitif kepada asap, MQ-6 lebih spesifik untuk LPG. Gabungan keduanya kurangkan false positive.
  • Demo dengan kawalan: Guna dupa atau asap dari kertas terbakar (dalam keadaan terkawal!) untuk demo. JANGAN guna gas sebenar semasa pembentangan.
  • Tunjukkan tiga tahap amaran: Demo setiap tahap dengan trigger yang berbeza — tunjukkan eskalasi amaran secara visual.

Penutup

Sistem pengesanan gas dan kebakaran ini boleh menyelamatkan nyawa — dan itulah poin terkuat yang boleh kau bawa ke pembentangan FYP. Untuk komponen sensor MQ-2, MQ-6, solenoid valve NC, dan semua aksesori, kunjungi Rectronx di rectronx.com.

Need Help With Your FYP?

We've helped hundreds of students complete their projects on time. Get a free quote today.

Chat with Rectronx