Go Back

The Maplin Smoke Alarm Shield for Arduino


Maplin are stocking some nice stuff to attach to your Arduino these days and the subject of this article is going to be the bunny on the left which, although it is a smoke shield, detects other gasses too.


It's made by Linksprite and it is unbelievably simple to work

as it consists of an MQ2 smoke detector unit wired up to put 5V to the heater and comparator and an analogue output voltage is put out by the MQ2 whenever it detects an excess of noxious particles in the air. It also has an on-board LED and all in all it very nearly makes a functioning smoke alarm for you when you slip it onto an UNO.

Maplin code: N98DG.

It's an SnO2 type sensor, otherwise known as tin dioxide or stannic oxide and what happens is that the stretched SnO2 wires inside are heated and when they come into contact with a combustible gas the resistivity drops. The denser the particles, the more the drop. Which means you can set it to detect the merest whiff of smoke such as somebody having a crafty cigarette where they shouldn't be.

So, let's shove one of these into an Uno, add a couple of buttons and a loudspeaker and see what happens. Here's how to wire the hardware after you've plugged the shield into the Arduino:






Signal to pin

Switch S1 up there is the button that's going to work the test mode and switch S2 is the one that's going to allow reset in the event that whatever has upset it has cleared. In the event that what has upset it is a raging conflagration then it won't of course be the alarm that's cleared off. It will be me. At rapid velocity.


There's also a loudspeaker. Use an 8 ohm one and put a 100 ohm resistor in series. Your Arduino wil send too much current otherwise.

This article uses the Linksprite shield, but there are more out there. The supplied code will work for them all providing you pay attention to the pin outs. If you are unsure about the pinouts on your particular shield e-mail your make and model number of the shield you have to

[email protected] or use the autoform on the home page.

Why does the drawing above show a 15k resistor when the text says 10k? I put it down to temporary colour blindness on my part. A more important question is what is that resistor doing there? It stops floating voltages at the pin. We need these pins to be at a reliable 0 Volts for this to work. Due to various factors semiconductor pins never are at 0V unless they are tied to a ground terminal, but you can't tie them directly because then when you send a signal to them that goes there as well and causes a short circuit. So you introduce a 10k which causes floating voltage to drop to 0 and high signals to go through at slightly under 5V to the pin. None of this is of course any good if you don't have any code to slap your Arduino with. Here comes some, either copy and paste it or download it as a text file by clicking the button on the left.


unsigned long timethen=0;

int LEDtime =5000;

boolean alarmon=false;

void setup() {

 // initialize serial communications at 9600 bps:


 pinMode(7, OUTPUT);digitalWrite(7,1);  



void loop() {

if (millis()>=86400000) {asm volatile ("  jmp 0");}

if (millis()-timethen>LEDtime){

  if (digitalRead(7)==HIGH){digitalWrite(7,0);}



 // read the analog in value:

int  sensorValue = analogRead(A0);            

if (sensorValue>26){alarmon=true;}

if (digitalRead(3)==1){LEDtime=5000;noTone (4);alarmon=false;}

if (digitalRead(2)==1|| alarmon==true){alarm();}

if (digitalRead(2)==00&&alarmon==false){LEDtime=5000;}





void alarm(){

LEDtime=500; tone (4,4000,100);

delay(100);tone (4,8000,100);




Smoke Alarm

Those of you who've trawled through other pages on this website will know to fear when the large cup of tea and packet of cigs appears because we are about to go into a lengthy explanation of something that will probably contain a tangental rant about something that's currently bothering me. Or it may even be an an intangential rant about something that's bothering me. Here they come:


Now usually when you make something you do it to a design brief which your customer will keep constantly changing. Behind the customer's back we call this an ID 10 T request (as he or she won't pay us if we say it to his/her face). So, what our ID10T wants at the moment is a smoke alarm that can be tested and reset when the smoke has cleared. So that's what we solder and code up for leaving ourselves plenty of wriggle room so that when the next ID10T comes in we can accommodate it.

So let's go through this code bit by bit and find out how it achieves what's wanted currently. First of all we need to set up three global variables:


unsigned long timethen=0;

int LEDtime =5000;

boolean alarmon=false;


Going from top to bottom of these variables we have first the variable timethen which has been declared as an unsigned long. Longs are variables that hold numeric data, and an unsigned long can hold any value from 0 to 4,294,967,295 which is 2 to the power of 32 minus 1. That's because it's a 32 bit (or 4 byte) variable without a bitsign and if that last sentence is as helpful to you as an anvil is to a man who has just fallen off a cargo ship in the middle of the Indian Ocean here it is in plain English:


The bigger the number of bits a variable has the bigger the number it can store. This is because it stores them as a binary number. For instance if we have two bits, we can have as a minimum 00 and as a maximum 11.  00 in binary is equal to decimal 0 and 11 is equal to decimal 3, because every time you move a column left you move by a power of two. Two to the zeroth power is 1 (as is anything to the zeroth power), two to the first is 2, to the second is four (2x2) to the third is 8 (2x2x2) and to the fourth 16 (2x2x2x2) and so on; it turns out that when you do this with twos each column going to the left is double its neighbour on the right. Four bits gets 1111 as a maximum which equals 15 in decimal because (1x8) +(1x4)+(1*2)+(1*1) and similarly 1010 would be 10 in decimal (1*8)+(0*4)+(1*2)+(0*1).

4,294,967,296 is two the thirty-second power but, because we have to cater for a zero, we always have two to whatever power minus one. Drunk that cup of tea yet? I'd get another if I were you.


The variable timethen (the 32 bit variable that started me off on the above) is going to be used to measure run time. Why? Because we are forestalling ID10T  requests here. That variable is going to be used to make an LED come on for five seconds and then go off for another five to visually indicate that the unit is working.


Here's a caveat with long variables: don't use them if you don't have to because if you sprinkle them about willy-nilly you'll find yourself running out of memory.


The second variable we have here is named LEDtime and is an int. An int can store a range of -32,768 to 32,767 because it's 16 bits. LEDtime is going to be used to control the LED blink rate.


Thirdly there is a Boolean variable. Boolean variables are named after George Boole, the man who inflicted Boolean algebra on the world. Booleans can either be 0 (false) or 1 (true). The variable in this sketch is named alarmon and it's going to change state between true (if the alarm's going) and false(if it's not).


There are three functions in this sketch. Two of them have got to be there whether we like it or not, and the third is called from either of the other two. The first one that's got to be there is the setup. This runs once, when power is applied or a reset is carried out, and then not again until next power-up or reset. It goes like this:


void setup() {

 // initialize serial communications at 9600 bps:


 pinMode(7, OUTPUT);digitalWrite(7,1);  



Alright then let's do line by line:


void setup() {

 // initialize serial communications at 9600 bps:


Whenever you see // at the beginning of a line it's a REM statement (REMark) which has been put there by the programmer so that anybody following on and developing the code knows what  the next bit is supposed to be doing. It's ignored by compilers and never reaches your Arduino.




This line opens serial communications between your Arduino and computer. It isn't actually necessary, but it's a handy way to see what's going on at the input/output stages when you've got a bug. The 9600 in brackets is the baud rate (how fast the data transfers).


 pinMode(7, OUTPUT);digitalWrite(7,1);  


There are in fact two commands on this line:


 pinMode(7, OUTPUT);


which sets pin 7 to an output mode; we need to do this to supply current to drive the LED. By default all pins are input and do not source current so well. Our LED wil not be shiny if we leave pin 7 as input.




This sets the pin to be on and thus drives current to the LED making it shine. It's equally valid to put digitalWrite(7,HIGH);  but it's more typing and I'm lazy.


Over the page we go then and the second function we've got to have is explored.