Oak Smoke Detector+

Today I went to work to make a better smoke detector.

And since I just received my new Kickstarter Digistump Oaks, I thought, what better time to play.

Check the YouTube video in the links.

 

This is a really simple project. The only key point to remember is that the MQ-135 needs a burn-in period of about 12 hours to report the proper readings.

Getting the Oak up and running the first time was a bit of a challenge while they are working the bugs out but as soon as I had the process down, it was not bad at all. You can find the instructions to setting up your Oak for the first time in the links above.

This little project watches the DHT22 for the Temp and Humidity, as well as the MQ-135 for air quality. Once the AQ goes above 600, it sets off the alarm.

Some future additions to this project include adding the ability for it to text message you when an alarm happens, and to set off the other detectors in the house.

*Update to the code which allows partical.io see a variable and then reports it to ifttt.com. I have mine setup to text me with an alert. Very cool!

*Second Update. Just finished another round of edits which allow the Oak to report the temperature and air quality readings up to Particle.io, then to ifttt.com then finally I have thingspeak gather the data and present it in some nice graphs. Click here to see it... Oak1 Status

There is also a edit which allows the oak to detect if the MQ-135 sensor is running high on boot because it hasn't warmed up yet. This edit will make sure it doesn't alarm until the sensor starts to show normal (roughly 15-20 minutes).

And here is the link to the YouTube video. Other links are viewable when you click on the article title at the top.

 

Oak Smoke Detector 1

Oak Smoke Detector 2

Oak Smoke Detector Wiring Diagram

Oak Pinout

Arduino Sketch

/*
* Oak Smoke Detector+
* From This email address is being protected from spambots. You need JavaScript enabled to view it.
*
* Because of a fire at my house where the existing (6 month old) smoke detectors didn't even go off, I decided to build a better set of detectors which do far more than just detect smoke.
* This design features the mighty Oak with its built in wifi and Particle.io ability to communicate with the world.
* It includes a MQ-135 air quality sensor which not only senses smoke but also other harmful fumes and gases.
* It also has a DHT-22 temperature and humidity sensor to give constant feedback to the state of the enviroment.
* And it has an alarm which goes off when a specified threashold is reached.
* All of this data can then be pulled from the Oak into Particle.io where it can be accessed by ifttt.com, thingspeak.com or any other monitoring site including one you create yourself.
* I currently have mine populating several graphs from thingspeak.com which can be viewed here... http://www.intheorystudios.com/oak1
* And when the alarm threashold is reached, I get a text message on my phone from ifttt.com
* I love the Oak and how quickly I was able to bring this design to life.
* Thanks Digistump!
*/

//Included Libraries
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "DHT.h"

#define OLED_RESET 4 //Not really used but I left it in. My 4 pin display doesn't have this abiltiy
Adafruit_SSD1306 display(OLED_RESET);
#define DHTPIN 5 //DHT-22 data pin
#define DHTTYPE DHT22 //Just specifing that we are using a DHT-22 and not the DHT-11

//Proably not needed but I left it in from the example code I used
#if (SSD1306_LCDHEIGHT != 32)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

int speakerOut = 6; //pinout on the Oak for the red speaker wire.
int alertLevel = 400; //threashold for the MQ-135. Keep in mind that the MQ-135 needs a burn-in period before it can give proper readings.
int alertState = 0; //Indicates if the MQ-135 has crossed the threashold
double currentTempF = 0; //Current temperature in fahrenheit from the DHT-22
double currentTempC = 0; //Current temperature in celsius from the DHT-22
double currentH = 0; //Current humidity from the DHT-22
double currentHI = 0; //Current heat index from the DHT-22
double currentAQ = 0; //Current air quality reading from the MQ-135
int startedNow = 0; //Simple variable to track how long the Oak has been running for the purposes of eliminating a false-positve because the MQ-135 requires a warm up period
int AQHighOnStart = 0; //0 is normal and 1 indicates that the MQ-135 was over the set threashold on start which tells the code to not sound the alarm until the MQ-135 goes under the threashold

//Initialize the DHT-22
DHT dht(DHTPIN, DHTTYPE);

void setup() {
Serial.begin(9600);
pinMode(speakerOut, OUTPUT); //Setting the digital pin for the speaker

//Tells Particle.io about these variables you want to monitor. Be carful not to make your variable name larger than 12 characters. Particle.io doesn't like that.
Particle.variable("alert", alertState);
Particle.variable("currentTempF", currentTempF);
Particle.variable("currentTempC", currentTempC);
Particle.variable("currentH", currentH);
Particle.variable("currentHI", currentHI);
Particle.variable("currentAQ", currentAQ);

//Starting the DHT-22 sensor
dht.begin();

//Starting the display
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.display();
delay(2000);
display.clearDisplay();
}

void loop() {
//If startedNow = -1, just ignore it from now on. That means that the MQ-135 is in a good state and the system can move along normally.
//If startedNow = 0 or greater, start/continue the count-up to indicate that the system just started
if (startedNow != -1)
{
startedNow++;
}

// Read humidity (percent)
float h = dht.readHumidity();
// Read temperature as Celsius
float t = dht.readTemperature();
// Read temperature as Fahrenheit
float fa = dht.readTemperature(true);
// Read the air quality of the MQ-135 from the Oak analog pin
float aq = analogRead(A0);

// Check if any reads failed and exit early (to try again)
if (isnan(h) || isnan(t) || isnan(fa)) {
Serial.println("Failed to read from DHT sensor :-(");
return;
}

//Calculating the heat index from the temperature in fahrenheit and the humidity
float hi = dht.computeHeatIndex(fa, h);

//Populate out variables with the latest values
currentTempF = fa;
currentTempC = t;
currentH = h;
currentAQ = aq;
currentHI = hi;

//Set the display defaults
display.setTextSize(1);
display.setTextColor(WHITE);

//Prepare the display with our data
display.setCursor(0, 0);
display.print("Humidity: ");
display.print(h);
display.println(" %");
display.setCursor(0, 8);
display.print("Temp: ");
display.print(t);
display.println("\t C");
display.setCursor(0, 16);
display.print("Temp: ");
display.print(fa);
display.println("\t F");
display.setCursor(0, 24);
display.print("AQ: ");

// Check to see if the current air quality reading is above our set threashold
if (aq > alertLevel)
{
// Check to see of the system just started which would indicate a false-positive
if (startedNow < 1000)
{
// The reading was past our threashold on start so its a false-positive
AQHighOnStart = 1;
}

if (AQHighOnStart == 0)
{
// If this isn't the start of the Oak, then the air quaility really is above our threashold so SOUND THE ALARM!
display.println("ALERT!");
}
else
{
// If we are above the threashold but the Oak just started so the MQ-135 hasn't warmed up yet, go a head and just send out the value to the display with the message of Alert Start.
display.print("Alert Start: ");
display.println(aq);
}
}
else
{
// This should be our normal air quality value being displayed
display.println(aq);
startedNow = -1;
AQHighOnStart = 0;
alertState = 0;
}
// Show everything on the display
display.display();


// This area is set apart from the upper alarm area so the Alarm message is displayed while the alarm is going off. Otherwise the alarm would go off but not message would be displayed.
if (aq > alertLevel)
{
// This can be monitored by ifttt.com so you get a message on your phone when this value is 1.
alertState = 1;

// Sound the alarm for 10 iterations
for (int i = 0; i < 10; i++) {
digitalWrite(speakerOut, HIGH);
delay(500);
digitalWrite(speakerOut, LOW);
delay(500);
}
}

// Wait a couple of seconds and clear the display so you can do it all over again
delay(2000);
display.clearDisplay();
}