IoTLabs

Nghiên cứu, Sáng tạo và Thử nghiệm

Series 37 Module Cảm Biến – Nguyên Lý Hoạt Động Flame Sensor: Phổ IR Lửa 760-1100nm, LM393 & Ứng Dụng Chữa Cháy

Flame Sensor (cảm biến lửa) phát hiện ngọn lửa bằng cách nhận bức xạ hồng ngoại đặc trưng của lửa ở phổ 760–1100nm. Tương tự IR sensor thông thường nhưng được chọn lọc theo phổ của ngọn lửa, không phải LED IR. Bài này phân tích nguyên lý, giải thích tại sao nắng cũng có thể gây nhiễu, và code robot chữa cháy cạnh tranh.

Nguyên Lý Hoạt Động

1. Lửa Và Phổ Bức Xạ IR

Ngọn lửa (đặc biệt từ hydrocarbon như cồn, nến, LPG) phát ra bức xạ điện từ trên dải rộng, đặc biệt mạnh ở vùng IR gần (Near-IR: 700–1100nm) và có đỉnh đặc trưng.

Phổ bức xạ ngọn lửa hydrocarbon (ví dụ cồn):
                     ↑ Cường độ
                     │
         Visible     │         Near-IR
         ──────────  │  ──────────────────
         400-700nm   │  700-1100nm
                     │       ██
                     │     ██████
                     │   ██████████
                     │ ████████████████
                     ├────────────────────→ Bước sóng (nm)
                    700        940       1100

Đỉnh đặc trưng: ~4.4µm (mid-IR, từ CO₂) và ~2.7µm (từ H₂O) 
→ nhưng module rẻ tiền không phát hiện mid-IR
→ phát hiện qua near-IR 760-1100nm (phổ phát xạ nóng đỏ/vàng)

Điểm khác biệt với ánh sáng thông thường:

  • Đèn LED/huỳnh quang: phát nhiều visible, ít near-IR
  • Bóng đèn sợi đốt (halogen): phát near-IR mạnh → có thể gây nhiễu
  • Ánh sáng mặt trời: phổ rộng bao gồm near-IR → nhiễu lớn nhất
  • Ngọn lửa: phổ liên tục + phát xạ blackbody theo nhiệt độ (~1000-2000K) → very strong near-IR

2. Photodiode Nhạy Phổ 760-1100nm

Photodiode trong flame sensor được chọn lọc (với lớp filter hoặc vật liệu bán dẫn) để nhạy nhất trong khoảng 760–1100nm — bao gồm vùng near-IR mà ngọn lửa phát mạnh.

Ngọn lửa cồn/nến/LPG
        ↓ IR bức xạ 760-1100nm
[Flame Sensor Photodiode]
        ↓
Dòng quang điện tỷ lệ với cường độ IR nhận được
        ↓
Điện trở/điện áp thay đổi
        ↓
LM393 so sánh với ngưỡng
        ↓
OUT thay đổi

Tại sao 760-1100nm thay vì 940nm đơn thuần: Ngọn lửa phát phổ rộng (blackbody radiation), không phải dải hẹp như LED IR. Photodiode nhạy với dải rộng hơn → bắt được nhiều bức xạ từ ngọn lửa → nhạy hơn. Tuy nhiên, điều này cũng có nghĩa dễ nhiễu từ các nguồn sáng khác phát near-IR.

3. Module — LM393 + Triết Áp

Cấu trúc module tương tự IR obstacle và rain sensor:

VCC
 │
[R pull-up]
 │
 ├──── AOUT (analog — điện áp giảm khi phát hiện lửa)
 │
[Photodiode]
 │
GND

AOUT → LM393 (+)
Triết áp → LM393 (-) (ngưỡng)
LM393 OUT → DOUT

Output logic:

  • Không lửa: Photodiode không nhận nhiều IR → AOUT cao → DOUT HIGH
  • Có lửa: Photodiode nhận nhiều IR → AOUT thấp → DOUT LOW (active LOW)

Triết áp: Điều chỉnh ngưỡng cảm nhận — vặn theo chiều kim đồng hồ để tăng ngưỡng (ít nhạy hơn, cần nhiều IR hơn mới trigger).

4. Góc Phát Hiện — 60° Thông Thường

Flame sensor thông thường có góc phát hiện ~60° (tổng).

         Flame Sensor
              │ ──── 30° ────┐
              │                 Phát hiện được
              │ ──── 30° ────┘

Ngọn lửa ở trực tiếp trước: phát hiện rõ nhất
Ngọn lửa ở góc 45°: phát hiện yếu hơn
Ngọn lửa ở góc >60°: không phát hiện

Hệ thống 3-sensor hoặc 5-sensor: Đặt nhiều sensor ở các góc khác nhau để phủ 180° hoặc 360° — dùng trong robot chữa cháy cạnh tranh để xác định hướng ngọn lửa.

Thông Số Kỹ Thuật

Thông sốGiá trị
Điện áp hoạt động3.3V – 5V
Dòng tiêu thụ~15–20mA
Bước sóng nhạy760nm – 1100nm
Khoảng cách phát hiệnLửa nến: ~80cm; Bật lửa: ~20cm (tùy cường độ)
Góc phát hiện~60°
Ngõ ra analog0V – VCC (thấp = có lửa)
Ngõ ra digitalLOW khi lửa, HIGH khi không (active LOW)
ComparatorLM393

Lưu ý khoảng cách: Ngọn lửa nến (nhỏ) phát hiện đến ~80cm. Ngọn lửa lớn hơn phát hiện xa hơn. Khoảng cách cũng phụ thuộc điều chỉnh triết áp.

Sơ Đồ Chân (Pinout)

        [Photodiode]
     ┌──────────────────┐
     │  Flame Sensor    │
     │  [Triết áp]      │
     │  [LED báo]       │
     │  LM393           │
     └──────────────────┘
      VCC   GND   DOUT   AOUT
ChânChức năng
VCC3.3V – 5V
GNDĐất
DOUTDigital: LOW = lửa, HIGH = không (active LOW)
AOUTAnalog: điện áp thấp = nhiều IR = có lửa

So Sánh Các Loại Flame Sensor

LoạiSensorSố sensorGóc phủ
1-sensor module1 photodiode160°
3-sensor module3 photodiode3~120°
5-sensor module5 photodiode5~180°
MLX90614Thermopile IR1Đo nhiệt độ từ xa — khác loại

3/5-sensor module dùng trong: Robot chữa cháy cạnh tranh — xác định hướng ngọn lửa từ sự khác biệt giữa các sensor.

Kết Nối Phần Cứng

Kết Nối với ESP32 DevKit V1

ESP32 DevKit V1           Flame Sensor Module
─────────────────────     ────────────────────────
3V3  ─────────────────→  VCC
GND  ─────────────────→  GND
GPIO4 (Input) ←──────────  DOUT  (active LOW)
GPIO32 (ADC1) ←──────────  AOUT  (analog)

Cấp 3.3V: an toàn cho GPIO ESP32. DOUT output 3.3V HIGH, 0V LOW.

Kết Nối với Arduino Uno

Arduino Uno               Flame Sensor Module
─────────────────────     ────────────────────────
5V   ─────────────────→  VCC
GND  ─────────────────→  GND
Pin 7 (Input) ←──────────  DOUT
A0 (Analog) ←────────────  AOUT

Code Arduino IDE

Code Phát Hiện Lửa Đơn Giản — Arduino Uno

/*
 * Flame Sensor — Phát hiện ngọn lửa
 * Board: Arduino Uno
 * Kết nối: VCC→5V, GND→GND, DOUT→Pin7, AOUT→A0
 *
 * QUAN TRỌNG: Điều chỉnh triết áp module để đặt ngưỡng nhạy
 * Test: Dùng bật lửa (giữ cách ~20cm) để kiểm tra
 * KHÔNG đưa lửa thật gần module — photodiode có thể hỏng nếu quá nóng
 */

const int DIGITAL_PIN = 7;
const int ANALOG_PIN  = A0;

void setup() {
  Serial.begin(9600);
  pinMode(DIGITAL_PIN, INPUT);
  Serial.println("=== Flame Sensor - Arduino Uno ===");
  Serial.println("DOUT LOW = Phát hiện lửa (active LOW)");
}

void loop() {
  // Đọc digital — LOW = có lửa
  bool flameDetected = (digitalRead(DIGITAL_PIN) == LOW);

  // Đọc analog — thấp = nhiều IR = có lửa
  int analogValue = analogRead(ANALOG_PIN);

  // Phân loại mức độ từ analog
  String flameLevel;
  if (analogValue > 900)      flameLevel = "Không có lửa";
  else if (analogValue > 700) flameLevel = "IR yếu (có thể nhiễu nắng)";
  else if (analogValue > 400) flameLevel = "Lửa yếu / xa";
  else                        flameLevel = "LỬA! Phát hiện rõ";

  // In kết quả
  Serial.print("Digital: ");
  Serial.print(flameDetected ? "CÓ LỬA! " : "Bình thường ");
  Serial.print("| Analog: "); Serial.print(analogValue);
  Serial.print(" | Mức: "); Serial.println(flameLevel);

  // Cảnh báo khi phát hiện
  if (flameDetected) {
    // Thêm: bật còi buzzer, relay bơm nước, gửi cảnh báo...
    Serial.println("!!! CẢNH BÁO LỬA !!!");
  }

  delay(500);
}

Code Robot Chữa Cháy — Arduino Uno (3 Flame Sensor)

/*
 * Robot Chữa Cháy — 3 Flame Sensor xác định hướng lửa
 * Board: Arduino Uno
 * Kết nối:
 *   Sensor trái  DOUT → Pin 4
 *   Sensor giữa DOUT → Pin 5
 *   Sensor phải DOUT → Pin 6
 *   Motor L298N: ENA→Pin9, IN1→Pin2, IN2→Pin3, ENB→Pin10, IN3→Pin7, IN4→Pin8
 *   Quạt/bơm → Pin 11 (bật khi gần lửa)
 *
 * Logic: Tìm hướng lửa → di chuyển về phía lửa → khi gần (cả 3 sensor thấy) → chữa cháy
 */

const int FLAME_L = 4; // Sensor lửa trái
const int FLAME_M = 5; // Sensor lửa giữa
const int FLAME_R = 6; // Sensor lửa phải
const int FAN_PIN = 11; // Quạt / bơm chữa cháy

// Motor L298N
const int ENA = 9, IN1 = 2, IN2 = 3;
const int ENB = 10, IN3 = 7, IN4 = 8;

const int SPEED = 180; // Tốc độ bình thường
const int SLOW  = 100; // Tốc độ chậm khi tiếp cận

void motorCtrl(int leftSpeed, int rightSpeed) {
  analogWrite(ENA, abs(leftSpeed));
  digitalWrite(IN1, leftSpeed > 0 ? HIGH : LOW);
  digitalWrite(IN2, leftSpeed > 0 ? LOW : HIGH);
  analogWrite(ENB, abs(rightSpeed));
  digitalWrite(IN3, rightSpeed > 0 ? HIGH : LOW);
  digitalWrite(IN4, rightSpeed > 0 ? LOW : HIGH);
}

void setup() {
  Serial.begin(9600);
  pinMode(FLAME_L, INPUT);
  pinMode(FLAME_M, INPUT);
  pinMode(FLAME_R, INPUT);
  pinMode(FAN_PIN, OUTPUT);
  for (int p : {ENA, IN1, IN2, ENB, IN3, IN4}) pinMode(p, OUTPUT);
  digitalWrite(FAN_PIN, LOW); // Quạt tắt ban đầu
  Serial.println("=== Fire Fighting Robot ===");
}

void loop() {
  // DOUT LOW = thấy lửa (active LOW)
  bool fL = (digitalRead(FLAME_L) == LOW);
  bool fM = (digitalRead(FLAME_M) == LOW);
  bool fR = (digitalRead(FLAME_R) == LOW);

  Serial.printf("L:%d M:%d R:%d → ", fL, fM, fR);

  if (fL && fM && fR) {
    // Cả 3 sensor thấy lửa → đang gần lửa → CHỮA CHÁY!
    motorCtrl(0, 0);           // Dừng
    digitalWrite(FAN_PIN, HIGH); // Bật quạt/bơm
    Serial.println("CHỮA CHÁY!");
    delay(3000);               // Chữa cháy 3 giây
    digitalWrite(FAN_PIN, LOW);

  } else if (fM && !fL && !fR) {
    // Chỉ sensor giữa thấy → thẳng về phía lửa
    motorCtrl(SLOW, SLOW);
    Serial.println("Tiến vào lửa");

  } else if (fL && !fR) {
    // Lửa bên trái → quay trái
    motorCtrl(-SLOW, SLOW);
    Serial.println("Quay trái tìm lửa");

  } else if (fR && !fL) {
    // Lửa bên phải → quay phải
    motorCtrl(SLOW, -SLOW);
    Serial.println("Quay phải tìm lửa");

  } else {
    // Không thấy lửa → tìm kiếm (quay chậm)
    motorCtrl(-SLOW, SLOW);
    Serial.println("Tìm kiếm lửa...");
  }

  delay(100);
}

Code ESP32 — Flame Detection + Cảnh Báo Serial

/*
 * Flame Sensor — ESP32, đọc analog + digital, phân mức
 * Board: ESP32 DevKit V1
 * Kết nối: VCC→3V3, GND→GND, DOUT→GPIO4, AOUT→GPIO32
 */

const int DIGITAL_PIN = 4;
const int ANALOG_PIN  = 32; // ADC1_CH4

void setup() {
  Serial.begin(115200);
  pinMode(DIGITAL_PIN, INPUT);
  analogSetAttenuation(ADC_11db); // Đọc 0-3.3V
  analogReadResolution(12);       // 12-bit: 0-4095
  Serial.println("=== Flame Sensor - ESP32 ===");
}

String getFlameLevel(int raw) {
  // ESP32 ADC 12-bit, 3.3V ref
  // Analog THẤP = nhiều IR = có lửa
  if (raw > 3500)      return "Không có lửa";
  if (raw > 2500)      return "IR mờ (nắng/đèn ?)";
  if (raw > 1500)      return "Lửa yếu / xa";
  if (raw > 800)       return "Lửa gần!";
  return "LỬA RẤT GẦN!";
}

void loop() {
  bool flameDet = (digitalRead(DIGITAL_PIN) == LOW);
  int  analogVal = analogRead(ANALOG_PIN);

  Serial.printf("ADC: %4d | Mức: %-20s | DOUT: %s\n",
    analogVal,
    getFlameLevel(analogVal).c_str(),
    flameDet ? "CÓ LỬA!" : "OK"
  );

  if (flameDet) {
    // Thêm: bật relay, gửi MQTT, còi...
    Serial.println(">>> PHÁT HIỆN LỬA! <<<");
  }

  delay(300);
}

Kết Quả Mong Đợi

=== Flame Sensor - ESP32 ===
ADC: 3820 | Mức: Không có lửa         | DOUT: OK
ADC: 3810 | Mức: Không có lửa         | DOUT: OK
[Đưa bật lửa lại gần ~30cm]
ADC: 2100 | Mức: Lửa yếu / xa         | DOUT: OK
ADC:  950 | Mức: Lửa gần!             | DOUT: CÓ LỬA!
>>> PHÁT HIỆN LỬA! <<<
ADC:  430 | Mức: LỬA RẤT GẦN!        | DOUT: CÓ LỬA!

Ứng Dụng Thực Tế

Ứng dụngChi tiết
Robot chữa cháy cạnh tranh3–5 sensor xác định hướng, servo/quạt chữa cháy
Phát hiện lửa bếp để lộCảnh báo khi bếp gas bị lửa bùng lớn
Hệ thống tắt gas tự độngPhát hiện lửa bất thường → relay đóng van gas
Phát hiện cháy rừng sớmNhiều sensor kết hợp LoRa (hạn chế — ảnh hưởng nắng)

Lưu Ý Khi Sử Dụng

1. Ánh sáng mặt trời và đèn halogen gây nhiễu

Cả hai phát near-IR mạnh → sensor có thể báo lửa giả. Không triển khai ngoài trời có nắng. Trong nhà: tránh đặt gần cửa sổ ánh nắng trực tiếp hoặc đèn halogen chiếu thẳng vào sensor.

2. DOUT active LOW — logic đảo

DOUT LOW = có lửa. Tương tự rain sensor và IR obstacle. Dùng if (digitalRead(PIN) == LOW) để phát hiện lửa. LED báo trên module sáng khi DOUT LOW (có lửa) — dùng để test nhanh.

3. Không đưa ngọn lửa quá gần sensor

Khoảng cách tốt nhất để test: 10–40cm. Quá gần → nhiệt cao có thể làm hỏng photodiode hoặc vỏ nhựa. KHÔNG đốt module.

4. Điều chỉnh triết áp theo môi trường thực tế

Môi trường có nhiều IR (nắng lọt vào) → giảm độ nhạy (vặn ngược chiều kim đồng hồ). Môi trường tối, cần phát hiện lửa nhỏ → tăng độ nhạy (vặn theo chiều kim đồng hồ). Không có cài đặt cố định “đúng” — tùy môi trường.

5. Không thay thế được cảm biến khói/nhiệt tiêu chuẩn

Module này không đạt tiêu chuẩn an toàn cháy nổ. Không dùng thay thế detector khói/nhiệt chính thống trong công trình. Chỉ dùng cho dự án hobbyist, robot cạnh tranh, và thử nghiệm.

Bài tiếp theo: