This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
oak:tutorials:oaksmokedetectorplus [2016/03/23 18:07] intheorystudios |
oak:tutorials:oaksmokedetectorplus [2016/03/25 22:14] (current) digistump |
||
|---|---|---|---|
| Line 2: | Line 2: | ||
| ======Oak: Oak Smoke Detector+====== | ======Oak: Oak Smoke Detector+====== | ||
| - | [Photo of Breadboard.png] | + | [[https://s3.amazonaws.com/digispark/images/m/Breadboard.png|{{https://s3.amazonaws.com/digispark/images/t/Breadboard.png}}]] |
| =====Background and Description===== | =====Background and Description===== | ||
| Line 35: | Line 35: | ||
| =====Circuit:===== | =====Circuit:===== | ||
| - | [Image of OakSmokeDetectorWiringDiagram.png] | + | [[https://s3.amazonaws.com/digispark/images/m/OakSmokeDetectorWiringDiagram.png|{{https://s3.amazonaws.com/digispark/images/t/OakSmokeDetectorWiringDiagram.png}}]] |
| The circuit is fairly straight forward. If you haven't already, go ahead and solder the headers onto your new Oak. | The circuit is fairly straight forward. If you haven't already, go ahead and solder the headers onto your new Oak. | ||
| Line 54: | Line 54: | ||
| <code> | <code> | ||
| - | Code to show example of it working | + | //Included Libraries |
| - | </code> | + | #include <SPI.h> |
| + | #include <Wire.h> | ||
| + | #include <Adafruit_GFX.h> | ||
| + | #include <Adafruit_SSD1306.h> | ||
| + | #include "DHT.h" | ||
| - | Explanation of code | + | #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(); | ||
| + | } | ||
| + | </code> | ||
| =====Conclusion:===== | =====Conclusion:===== | ||
| - | Where to go from here, potential uses, etc. | + | The above code will provide for Particle.io several variables to look at. Now you need to do something with it. I signed up for an account on http://www.ifttt.com which allowed me to connect to my Particle.io account and see what values my Oak was sending out. Next I used those values to setup an instant message to my phone which would alert me if the "alarmstate" reaches 1. Then I setup another recipe to message my phone if the Oak Smoke Detector+ goes offline for any reason. |
| + | |||
| + | Finally I setup another account on https://thingspeak.com/. I send the data from ifttt.com over to thingspeak for them to collect and track for me, which shows great graphs of my data. Here is a link to my site with all of the data that my Oak1 is sending out. http://www.intheorystudios.com/oak1/ | ||
| + | |||
| + | In conclusion, I believe that the Oak Smoke Detector+ will be a great addition to your home. If you have any suggestions or additions to this project, please feel free to let me know. I'm at rick@intheorystudios.com and you can also see this project on youtube right here... https://www.youtube.com/watch?v=uedJR77QlKg | ||
| + | |||
| + | |||
| + | Future upgrades to this project may include the ability for multiple Oak Smoke Detectors to communicate. So if one goes off, the others will too. | ||