LPG gas leak alarm that you can actually trust
- Build Logs
- 30 Jul, 2026
This is the first project in this series where getting it wrong has a consequence beyond a wasted evening. A gas alarm that reads badly is worse than no alarm, because you will trust it. So this build spends more time on what the sensor cannot tell you than on the wiring, which takes about ten minutes.
Try it before you build it
The whole thing runs in your browser — no board, no sensor, nothing to install. Drag the gas slider and watch the threshold logic behave exactly as described below.
One quirk worth knowing before you press play. The simulated sensor starts at 400 ppm, which already reads 907 out of 1023 on the analogue pin — nearly full scale. Let the baseline capture that and no amount of gas can push the reading 150 counts higher, because only 116 counts of headroom remain. The alarm can never trip.
So drag the gas slider to its minimum first, then press play. The baseline settles around 220, and raising the slider to 400 ppm is a rise of nearly 700 — the alarm warns, then latches, as it should.
That is not a simulator bug. It is this article's own advice arriving in person: the threshold is only meaningful against a baseline measured in genuinely clean air. Take the baseline in dirty air and the alarm is deaf — on a bench or in a kitchen.
What you will need
| Part | Qty | Approx. |
|---|---|---|
| MQ6 LPG / Propane Gas Sensor | 1 | ₹141 |
| Arduino Uno R3 (compatible) | 1 | ₹418 |
| 16×2 LCD with I2C | 1 | ₹149 |
| Piezo Buzzer (6-12V) | 1 | ₹32 |
| 1 Channel Relay with Optocoupler | 1 | ₹126 |
Roughly ₹866. MQ6 is the right choice for LPG and propane. If you want a general "is the air bad" reading instead, use the MQ135; for carbon monoxide specifically, the MQ-9.
What an MQ sensor really measures
Inside is a tin dioxide layer and a small heater. Heat the layer and its electrical resistance changes in the presence of reducing gases. You read that resistance as a voltage divider on an analogue pin.
Three consequences follow, and all three are usually ignored.
It is not selective. The MQ6 responds most strongly to LPG and propane, but it also responds to alcohol, smoke, and cooking vapour. Spray deodorant near it and it will alarm. This is a sensor class limitation, not a fault, and it is why commercial detectors cost more.
It needs to be hot to work. The heater draws around 150 mA, and the reading is meaningless until the element reaches temperature — roughly 60 seconds from cold. It also runs warm continuously, which is normal.
The raw number is not PPM. Converting to parts-per-million requires the sensor's resistance in clean air (R0), measured for your individual sensor, plus the log-log curve from the datasheet. Any tutorial printing "PPM" without first measuring R0 is printing a fiction. We will do something more honest instead.
Burn-in: 24 hours before you believe it
A new MQ sensor drifts substantially for the first day or two of continuous power. The datasheet calls for over 24 hours of preheating before calibration, and it genuinely matters — a sensor calibrated in its first hour will read high for a week and then settle somewhere else entirely.
Leave it powered on a bench for a day. Then calibrate.
Wiring
| From | To | Note |
|---|---|---|
| MQ6 VCC / GND | Uno 5V / GND | heater needs 5V |
| MQ6 A0 | Uno A0 | analogue, not D0 |
| LCD SDA / SCL | Uno A4 / A5 | |
| Buzzer + | Uno D8 | via a 100Ω resistor |
| Relay IN | Uno D7 | for an exhaust fan |
Use A0, not the module's D0. The digital pin is just a comparator against the onboard trimpot, giving you one bit and no ability to see a rising trend. The whole value of this build is watching the number move.
The 150 mA heater is close to what an Uno's regulator is comfortable supplying alongside an LCD backlight. If readings wander when the backlight is on, power the board from a proper 5V adapter rather than a laptop port.
Calibrating against your own clean air
Rather than pretend to output PPM, we establish what your kitchen reads normally, and alarm on a meaningful rise above that. It is a much more defensible design.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // some modules are 0x3F
#define GAS_PIN A0
#define BUZZER 8
#define RELAY 7
#define RELAY_ON LOW
#define RELAY_OFF HIGH
int baseline = 0;
const int WARN_RISE = 80; // counts above baseline
const int ALARM_RISE = 150;
void establishBaseline() {
lcd.clear();
lcd.print("Warming up...");
// The heater needs to reach temperature before any reading means anything.
for (int s = 60; s > 0; s--) {
lcd.setCursor(0, 1);
lcd.print(s); lcd.print("s ");
delay(1000);
}
lcd.clear();
lcd.print("Baseline...");
long sum = 0;
const int N = 100;
for (int i = 0; i < N; i++) { sum += analogRead(GAS_PIN); delay(50); }
baseline = sum / N;
}
void setup() {
Serial.begin(9600);
digitalWrite(RELAY, RELAY_OFF); // before pinMode, so no boot pulse
pinMode(RELAY, OUTPUT);
pinMode(BUZZER, OUTPUT);
lcd.init(); lcd.backlight();
establishBaseline();
Serial.print(F("baseline=")); Serial.println(baseline);
}
In the simulation above, shorten that 60-second warm-up to about 3 so it is watchable. On real hardware, leave it — the heater genuinely needs the time.
Alarming like an alarm, not like a sketch
Two design choices matter more than the threshold numbers.
Require the reading to stay high. A single sample above threshold is noise, a cigarette, or someone opening a bottle of nail varnish. Requiring several consecutive seconds removes almost all false alarms without meaningfully delaying a real one.
Latch the alarm. If gas is detected and then disperses, the alarm should keep sounding until a human acknowledges it. Otherwise a leak that happened while you were out leaves no trace at all.
int highCount = 0;
bool latched = false;
const int CONFIRM_SAMPLES = 5; // ~5 seconds
void loop() {
int raw = analogRead(GAS_PIN);
int rise = raw - baseline;
lcd.setCursor(0, 0);
lcd.print("Gas:"); lcd.print(rise); lcd.print(" ");
if (rise > ALARM_RISE) highCount++;
else if (highCount > 0) highCount--;
if (highCount >= CONFIRM_SAMPLES) latched = true;
lcd.setCursor(0, 1);
if (latched) {
lcd.print("** GAS ALARM **");
digitalWrite(RELAY, RELAY_ON); // exhaust fan on
// Chirping pattern carries far better than a constant tone.
tone(BUZZER, 3100); delay(150); noTone(BUZZER); delay(120);
tone(BUZZER, 3100); delay(150); noTone(BUZZER); delay(600);
} else if (rise > WARN_RISE) {
lcd.print("Rising... ");
delay(500);
} else {
lcd.print("Air OK ");
digitalWrite(RELAY, RELAY_OFF);
delay(1000);
}
}
3.1 kHz is roughly where a piezo is loudest and where human hearing is most sensitive — it is what commercial smoke alarms use, and it is a great deal more likely to wake someone than a 500 Hz beep.
To clear a latched alarm you need a button, which is the obvious next addition. Do not clear it automatically.
Where to mount it
This matters as much as the code. LPG is heavier than air, so it pools low: mount the sensor roughly 30 cm off the floor, near but not directly above the appliance. Natural gas (methane) is lighter than air and needs a high mounting instead — if you are on piped gas rather than a cylinder, the MQ6 is the wrong sensor and the wrong height.
Keep it out of the direct path of cooking steam, which will trigger it.
Things that go wrong
Reads high and never settles. Not burnt in. Give it a day of continuous power.
Alarms whenever you cook. Mounted in the steam path, or your baseline was taken with the kitchen already in use. Re-baseline in still, clean air.
Never alarms, whatever you do. The baseline was captured in air that was already dirty, so there is not enough headroom left to reach the threshold. This is the same failure as the simulator's 400 ppm default, and the fix is the same: re-baseline in clean air.
Alarms when you spray anything. Expected. The sensor is not selective — alcohol and aerosols read as gas.
Readings jump when the LCD backlight changes. Supply sag. Use an external 5V adapter.
LCD shows nothing. Wrong I2C address; try 0x3F instead of 0x27, or run a scanner.
Sensor is warm to the touch. Normal. The heater runs continuously by design.
Please read this before you rely on it
Build this, learn from it, and keep it as a second line of defence — but do not let it replace a certified detector. A commercial alarm is independently tested, has a defined sensitivity and response time, fails safe, and carries a certification mark. This build has none of those things, and an MQ6 on a breadboard cannot be verified by you.
That is not a reason to skip the project. Understanding why a certified alarm costs more is one of the more valuable things this build teaches.
Where to take it next
Add a NodeMCU and the alarm can notify your phone when nobody is home — the pattern is in our ESP32-CAM alert build. The relay is already there to drive an exhaust fan; see the door lock build for the flyback-diode rule before you switch anything inductive with it.
Talk to us about sensor choice if you are unsure whether you are dealing with LPG or piped natural gas — it changes both the sensor and where it goes.