Flame Detection with an Infrared Sensor
| Difficulty | Beginner |
|---|---|
| Category | Sensors |
| Supported boards | Arduino Uno R3 and compatible ATmega328P boards |
| Time needed | 35 minutes |
| Prerequisites | Read a Push Button |
| Tested board | Not yet verified |
| Tested on | Not yet verified |
| Arduino IDE version | Not yet verified |
| Library | Not yet verified |
What it does
The black teardrop on the end of the board is a photodiode filtered to respond to infrared, roughly in the band a flame emits most strongly. Point it at a fire and an LM393 comparator on the board pulls its output pin low.
It is not a smoke detector and it is not a heat sensor. It is a sensor for light of a particular colour, and a flame happens to produce a lot of it. So does the sun, and so does an incandescent bulb, which is most of what you need to know about where it will and will not work.
Before you begin
Required parts and tools
- An Arduino Uno or compatible board.
- One flame detection module. This is Siratek product 2901, marked
HL-01on the board. - Three female-to-male jumper wires.
Three pins, not four
This is the thing to check before you write any code. The Siratek board has a three-pin header, silkscreened DO GND VCC. There is no AO.
That makes it different from the soil moisture, gas and sound modules, which all give you an analog pin as well. Here the sensitivity trimmer on the board is your only control, and there is no way to see the underlying level from the Arduino.
Four-pin versions of this sensor exist and are worth buying if you want the analog reading. If yours has four pins, treat the extra one as AO and read it with analogRead(); everything else below still applies.
Low means fire
The comparator’s output is active low: DO sits HIGH normally and goes LOW when flame is detected.
This catches people, because “detected” instinctively reads as HIGH. Name the states in your code and the problem disappears, which is what the example below does.
Setting the trimmer, without an analog pin
With no AO to measure, the procedure is mechanical:
- Power the board and look at the indicator LED that follows
DO. - With no flame present, turn the trimmer until that LED just goes out.
- Back it off a little further, so ordinary room light cannot trip it.
- Test with a real flame at the distance you care about, and adjust.
Do this with the room lit as it will normally be. Setting it in the dark and then switching a lamp on will trigger it.
Range, and what else it sees
Expect something under a metre for a candle, less at an angle: the sensor has a cone of view of around 60 degrees and is much less sensitive off-axis.
It will also respond to direct sunlight, an incandescent or halogen bulb, and a hot soldering iron at close range. It will not see a flame through glass that blocks infrared, and it will not see smoke at all.
What this sensor is honestly for
It is a component for learning and for hobby projects. It is not a fire alarm.
A real fire alarm is a certified device that is tested, powered independently, audible from anywhere in the building, and designed to fail safely. This module is none of those things: it sees one direction, it can be fooled by sunlight, and if the Arduino crashes it reports nothing at all.
Build the project. Enjoy it. Keep a proper smoke alarm on the ceiling.
Pin reference
| Pin or label | Connect to | Purpose | Notes |
|---|---|---|---|
DO |
Uno D2 |
Detection output | LOW means flame |
GND |
Uno GND |
Ground | |
VCC |
Uno 5V |
Power | 3.3 V also works |
Wiring steps
- Unplug the USB cable.
GNDtoGND.VCCto5V.DOtoD2.- Plug the USB cable back in. The power LED should light at once.
Software and libraries
No library is required. Use plain INPUT; the comparator drives the pin both ways.
Minimal working example
// Siratek: flame detection on an active-low module.
const int flamePin = 2;
const int ledPin = 13;
// This board pulls the pin LOW when it sees flame.
const int FLAME_DETECTED = LOW;
int lastState = HIGH;
void setup() {
pinMode(flamePin, INPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.println("Siratek: flame sensor ready.");
}
void loop() {
int state = digitalRead(flamePin);
if (state != lastState) {
lastState = state;
bool flame = (state == FLAME_DETECTED);
digitalWrite(ledPin, flame);
Serial.println(flame ? "FLAME" : "clear");
}
}
Naming the constant is what keeps this readable. if (digitalRead(flamePin) == LOW) is correct and tells a future reader nothing; FLAME_DETECTED tells them everything, and it is the one line to change if you swap in a board that works the other way round.
Not reacting to a flicker
A candle flickers, something passes in front of the sensor, and a single reading catches the wrong moment. For anything that sounds an alarm, require the condition to persist.
// Siratek: only report flame that has been present continuously.
const int flamePin = 2;
const int buzzerPin = 8;
const int FLAME_DETECTED = LOW;
const unsigned long mustPersist = 1000; // milliseconds
unsigned long firstSeen = 0;
bool alarming = false;
void setup() {
pinMode(flamePin, INPUT);
pinMode(buzzerPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
bool flame = (digitalRead(flamePin) == FLAME_DETECTED);
if (flame) {
if (firstSeen == 0) {
firstSeen = millis();
} else if (!alarming && millis() - firstSeen >= mustPersist) {
alarming = true;
digitalWrite(buzzerPin, HIGH);
Serial.println("FLAME held for one second");
}
} else {
firstSeen = 0;
if (alarming) {
alarming = false;
digitalWrite(buzzerPin, LOW);
Serial.println("clear");
}
}
}
This is the same idea as debouncing a button, applied to a sensor: a reading has to mean something for a while before it counts. It is worth keeping for any detector that triggers something noticeable.
Expected result
The indicator LED on the board, and the Arduino’s pin 13, both follow the flame. A lighter held twenty or thirty centimetres away should trigger it reliably once the trimmer is set.
Move the flame off to one side and detection falls away quickly. That cone is narrow, and it is the main thing to plan around when mounting the sensor.
Troubleshooting
| Symptom | Likely cause | Check or fix |
|---|---|---|
| Reports flame constantly | Trimmer too sensitive, or sunlight | Reset the trimmer in normal room light |
| Logic looks inverted | The board is active low | LOW means flame; use the named constant |
| Never detects anything | Trimmer backed off too far | Turn it back until the LED just goes out, then slightly more |
| No power LED | VCC or GND not connected |
Check both |
| Detects only very close | Normal, plus trimmer setting | Under a metre is typical for a candle |
| Misses a flame to one side | Cone of view is about 60 degrees | Aim it, or use more than one |
| Triggers when a lamp is switched on | Incandescent bulbs emit infrared | Reposition, or reduce sensitivity |
Looking for AO and not finding it |
This board has three pins | Use the trimmer, or buy the four-pin version |
| Triggers on a brief flicker | Single reading caught a moment | Require the state to persist |
| Reports nothing after a crash | The Arduino has stopped | Why this is not a fire alarm |
Next steps
- Easier first: Read a Push Button, the same
digitalRead()with no comparator. - Related products: the MQ-2 gas sensor for smoke and gas, and an active buzzer for an alert.
- Next project: a bench alarm that combines flame and gas detection, with the limits of both written on it.
Sources and attribution
All text, wiring guidance and code in this tutorial are original Siratek work.
- The three-pin
DO GND VCCheader and theHL-01board marking were read from the Siratek product photographs for item 2901, which is why this tutorial treats the analog output as absent rather than optional.
Detection range and the cone of view are given as typical figures that depend on the trimmer setting, the flame and the angle. The statement that this module is not a substitute for a certified fire alarm is a deliberate limitation of scope. No third-party tutorial text, diagrams, photographs or code has been reproduced here.

