Raspberry PI connected Wireless Smoke Alarm

My Brief

Build a smoke alarm that sends an email and text message when it goes off.

The Device

After a fe

w days of investigation into possible solutions, I opted to build one using a Raspberry PI and a cheap smoke alarm, linked by radio signal.

When the Smoke Alarm is triggered, it will send a signal using the radio transmitter to its receiver, which is connected to the Raspberry PI. When the Raspberry detects a constant signal for more 10 seconds, it then sends me an email and text message.

The end result

This video demonstrates it working. The first blip is a false alarm. The second lasts for more than 10 seconds and sends the messages.

Equipment Used

The Raspberry PI

I decided to use the Raspberry PI micro-computer because it's nice and small (credit card sized), doesn't require a lot of power and is really simple to program. It also contains general-purpose input/output (GPIO) pins that can be configured to receive signals from external devices (the radio receiver).

The Smoke Alarm

I tried a few smoke alarms before settling on the Aico Ei100L. Ideally I wanted the radio transmitter to be powered using the alarm's battery. The transmitter sleeps at a low voltage; but once up and running none of the other alarms had enough power for it, and the alarm to work properly. The Aico was perfect, as uses very basic electronics and two 9v batteries.Raspberry PI connected Wireless Smoke Alarm

Radio Gear

I was trying to build the system on a budget, so I ended up buying a cheap AM Radio Transmitter/Receiver from Maplin. I later found out I might have been wiser buy a slightly better system, as I found myself constantly trying to resolve interference issues. It was sensitive to other electronics, which apparently this is quite common with these cheap components.

I had originally planned on powering the receiver using its power output, but it ended up with its power supply, as even the Raspberry caused interference issues.

99% of the interference issues were resolved once it was placed in its case and the software fixed the rest.

Items used:

  • 1 x Smoke Alarm Aico Ei100L
  • 1 x Raspberry PI
  • 2 x Cases
  • 2 x Power Supplies
  • 1 x Radio transmitter and receiver
  • Cables and other electronics

Electronics

Transmitter Circuit

Software

I programmed the software using Python 3. I'm a C# developer by trade, and found Python simple to learn. Although, if you are prototyping on Windows machine, watch out for case sensitive code.

Receiving the Signal

To check for an input from the radio receiver I used the Python's RPi.GPIO module.

As mentioned above, I didn't want the system to send messages until it had received a signal for at least 10 seconds. This would allow me to test the battery each month and stop if from sending false alarms when I burn my toast! To do this I added a timing loop and signal counter. If the signal received 20 times in a 10 second period, the messages are sent. The count of 20 stops the system from sending messages when there's receiver interference.

To ensure the system doesn't need resetting once it's triggered, I've encompassed the logic in an infinite loop.

def listen(self):
		
	print("Listening for Signal")
			
	while True:

		fire = False

		while fire == False:                                
					
			time.sleep(0.5)

			number = self.checkForSignal()
			
			if (number == 1):
				start = time.time()
				counter = 0;

				while True:
						
					number = self.checkForSignal()
					counter += number
					elapsed = time.time()-start
					
					time.sleep(0.1)

					if (elapsed < 10):
						continue						

					if (counter > 20):
						fire = True
					else:
						print('False alarm')																			
						 
					break
						   
			else:
				counter = 0            

		self.sendEmail()
		self.sendSms()

Sending the SMS Text message

The Raspberry can be connected to a GPRS modem, but they're expensive. After reading Matt Hawkins' post, I ended up using Text Local's SMS web service instead. Simple to use, cheap and there's no monthly renewal fee!

def sendSms(self):

	values = {'test'    : 0,
		  'uname'   : self.smsUsername,
		  'hash'    : self.smsHash,
		  'message' : self.smsMessage,
		  'from'    : self.smsSender,
		  'selectednums' : (self.smsNumbers) }

	url = 'http://www.txtlocal.com/sendsmspost.php'
	postdata = urllib.urlencode(values)
	binary_data = postdata.encode('ascii')
	req = urllib2.Request(url, binary_data)

	print('Attempt to send SMS ...')

	try:
		response = urllib2.urlopen(req)
		response_url = response.geturl()
		if response_url == url:
			print('SMS sent!')	
			
	except urllib.error.URLError as e:
		print('Send failed!')
		print(e.reason)

Sending the email

For this I connected my Gmail account's SMTP server.

def sendEmail(self):
	print('Sending Email')

	subject = "Smoke Detected Possible Fire"
	text = self.smsMessage
	
	message = """\From: %s\nTo: %s\nSubject: %s\n\n%s
		""" % (self.emailFrom, ", ".join(self.emailTo), subject, text)
	
	try:
		server = smtplib.SMTP(self.smtpServerHost, self.smtpServerPort)

		if (self.smtpTls == True):
			server.ehlo()
			server.starttls()
			
		server.login(self.smtpUsername, self.smtpPassword)
		server.sendmail(self.emailFrom, [self.emailTo], message)
		server.close()
		print('Successfully sent the mail')
		
	except smtplib.SMTPException as e:
		print(e)
		print("Failed to send mail")

Full Code

import time
import random
import smtplib
import RPi.GPIO as GPIO
import urllib
import urllib2
import os
import ConfigParser 

class SmokeDetector:
    
	def __init__(self):
		GPIO.setmode(GPIO.BOARD)
		GPIO.setup(11, GPIO.IN)
		
		config = ConfigParser.ConfigParser()
		config.read("config.cfg")
		self.smsMessage = config.get('alerter', 'smsMessage')
		self.smsUsername = config.get('alerter', 'smsUsername')
		self.smsSender = config.get('alerter', 'smsSender')
		self.smsHash = config.get('alerter', 'smsHash')
		self.smsNumbers = config.get('alerter', 'smsNumbers')		
		self.smtpUsername = config.get('alerter', 'smtpUsername')
		self.smtpPassword = config.get('alerter', 'smtpPassword')
		self.smtpServerHost = config.get('alerter', 'smtpServerHost')
		self.smtpServerPort = config.get('alerter', 'smtpServerPort')
		self.smtpTls = config.getboolean('alerter', 'tls')
		self.emailFrom = config.get('alerter', 'from')
		self.emailTo = config.get('alerter', 'to')

	def listen(self):
		
		print("Listening for Signal")
                
		while True:

			fire = False

			while fire == False:                                
						
				time.sleep(0.05)

				number = self.checkForSignal()
				
				if (number == 1):
					start = time.time()
					counter = 0;

					while True:
							
						number = self.checkForSignal()
						counter += number
						elapsed = time.time()-start
						
						time.sleep(0.1)

						if (elapsed < 10):
							continue
							

						if (counter > 20):
							fire = True
						else:
							print('False alarm')																			
							 
						break
							   
				else:
					counter = 0            

			self.sendEmail()
			self.sendSms()
			
	def sendEmail(self):
		print('Sending Email')

		subject = "Smoke Detected Possible Fire"
		text = self.smsMessage
		
		message = """\From: %s\nTo: %s\nSubject: %s\n\n%s
		""" % (self.emailFrom, ", ".join(self.emailTo), subject, text)
		try:
			server = smtplib.SMTP(self.smtpServerHost, self.smtpServerPort)

			if (self.smtpTls == True):
				server.ehlo()
				server.starttls()
Raspberry PI connected Wireless Smoke Alarm schematic
			server.login(self.smtpUsername, self.smtpPassword)
			server.sendmail(self.emailFrom, [self.emailTo], message)
			server.close()
			print('Successfully sent the mail')
		except smtplib.SMTPException as e:
			print(e)
			print("Failed to send mail")
		
	def sendSms(self):
	
		values = {'test'    : 0,
			  'uname'   : self.smsUsername,
			  'hash'    : self.smsHash,
			  'message' : self.smsMessage,
			  'from'    : self.smsSender,
			  'selectednums' : (self.smsNumbers) }

		url = 'http://www.txtlocal.com/sendsmspost.php'
		postdata = urllib.urlencode(values)
		binary_data = postdata.encode('ascii')
		req = urllib2.Request(url, binary_data)

		print('Attempt to send SMS ...')

		try:
			response = urllib2.urlopen(req)
			response_url = response.geturl()
			if response_url == url:
				print('SMS sent!')	
				
		except urllib.error.URLError as e:
			print('Send failed!')
			print(e.reason)
		
	def checkForSignal(self):
		return GPIO.input(11);	
		
sa = SmokeDetector()
sa.listen()

Starting system on boot

To get the code running on boot I created a Cron job to run my script file.

Testing the device

I've tested the device over two floors, with a distance of 12 metres between the alarm and Raspberry. It would go further, if the transmitter and receiver aerials were extended.

The device has been running now for 10 days without any false alarms.

 

For more detail: Raspberry PI connected Wireless Smoke Alarm


About The Author

Ibrar Ayyub

I am an experienced technical writer holding a Master's degree in computer science from BZU Multan, Pakistan University. With a background spanning various industries, particularly in home automation and engineering, I have honed my skills in crafting clear and concise content. Proficient in leveraging infographics and diagrams, I strive to simplify complex concepts for readers. My strength lies in thorough research and presenting information in a structured and logical format.

Follow Us:
LinkedinTwitter

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top