Jonathan Caleb DoshJames Freeman
Published © GPL3+

StoveTec

Never have to turn back a few minutes into a long trip again. StoveTec will notify you if your stove or oven is on when you leave the house.

BeginnerFull instructions provided2 hours1,158
StoveTec

Things used in this project

Hardware components

Photon
Particle Photon
×2
Arduino BME/BMP 280 Pressure Temperature Sensor
×2
Jumper wires (generic)
Jumper wires (generic)
Some generic jumper wires eliminate the need to cut or strip additional wire. We used 8. You may need more or less based on how you wish to orient your sensors.
×8

Software apps and online services

Maker service
IFTTT Maker service
IFTTT is used to construct and monitor a geofence around your residence. When you exit the area a particle function will be called to check the on/off status of the stove. Base on the result of that function a separate applet within the app decide whether or not to send a notification to your phone.
ThingSpeak API
ThingSpeak API
Spy on your roommate's cooking habits with a handy real-time graph!

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
You may need to solder your sensors to their mounts to improve performance.

Story

Read more

Schematics

Circuit Diagram for Particle/BMP280

This circuit diagram applies to BOTH sensors used in the system.

Code

Particle 1 Code

Plain text
Flash this code to Particle 1 (the master particle that processes the on/off Boolean for the entire stove).
//Particle 1 Code  


// This #include statement was automatically added by the Particle IDE.
#include "ThingSpeak/ThingSpeak.h"

/***************************************************************************
  This is a library for the BME280 humidity, temperature & pressure sensor
  Designed specifically to work with the Adafruit BME280 Breakout
  ----> http://www.adafruit.com/products/2650
  These sensors use I2C or SPI to communicate, 2 or 4 pins are required
  to interface.
  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!
  Written by Limor Fried & Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
  This file was modified by Markus Haack (https://github.com/mhaack)
  in order to work with Particle Photon & Core.
  Then further modified by Mac McAlpine https://github.com/macsboost
  And also by James Freeman
 ***************************************************************************/
 
//#include "Adafruit_BME280/Adafruit_Sensor.h"
#include "Adafruit_BME280/Adafruit_BME280.h"

#define BME_SCK D4
#define BME_MISO D3
#define BME_MOSI D2
#define BME_CS D5

#define SEALEVELPRESSURE_HPA (1013.25)

//This Sketch measure differential pressure across the air filter in the house HVAC

/*                                    +-----+
 *                          +----------| USB |----------+
 *                          |          +-----+       *  |
 *                          | [ ] VIN           3V3 [ ] |
 *                          | [ ] GND           RST [ ] |
 *                          | [ ] TX           VBAT [ ] |
 *                          | [ ] RX  [S]   [R] GND [ ] |
 *                          | [ ] WKP            D7 [*] |
 *                          | [ ] DAC +-------+  D6 [*] |
 *                          | [ ] A5  |   *   |  D5 [*] |
 *                          | [ ] A4  |Photon |  D4 [*] |P1 PWR
 *                          | [ ] A3  |       |  D3 [*] |P2 PWR
 *                          | [ ] A2  +-------+  D2 [*] |
 *                      P1  | [*] A1             D1 [*] |SCL BME 0x76
 *                      P2  | [*] A0             D0 [*] |SDA BME 0x76
 *                          |                           |
 *                           \    []         [______]  /
 *                            \_______________________/
 *
 *
 */

/*
   This sample code demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
   It requires the use of SoftwareSerial, and assumes that you have a
   230400-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/


Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);




Timer timer(14232, checkEnvironment); // call this function every 10 seconds
Timer timer2(9901, serialDebug); // call this function every 10 seconds
Timer timer3(10123, stovestatus);
Timer timer4(10233, checkEnvironment2);

int caladdress = 0;
double stoveTemp = 0;
double Temp=0;
double baro = 0;
double humidity = 0;
int onoroff=0; //the on/off status of the stove
int onoroff2=0; //the on/off status of the second sensor only
int danger=0;



//ApplicationWatchdog wd(5000, System.reset); //5 second application watchdog
SYSTEM_MODE(SEMI_AUTOMATIC);



ApplicationWatchdog wd(60000, System.reset);


void setup() {
  Serial.begin(230400);
  Serial.println(F("BME280 test"));

  /*if (!bme.begin(0x76)) {  //0x76 is the i2c address of the sensor
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }*/
  
  
  Particle.publish("DEBUG", "starting...");

  if (bme.begin(0x76)) {  //0x76 is the i2c address of the sensor
    Particle.publish("DEBUG", "starting the environment timer...");
    timer.start(); //initialize timer
    timer2.start();//initialize timer2
    timer3.start();//initialize timer2
    timer4.start();
  }
  else {
    Particle.publish("WARN", "Could not find a valid BMP280 sensor, check wiring!");
  }

  Particle.publish("DEBUG", "started!");
 
  Particle.connect(); 
  Particle.variable("bme280temp", stoveTemp);
  Particle.variable("Stv2:2on0off", onoroff2);
  Particle.variable("bme280baro", baro);
  Particle.variable("bme280humid", humidity);
  Particle.variable("Stv1:1on0off", onoroff);
  Particle.variable("DANGER", danger);
  Particle.function("checkStove", checkStove);
  Particle.subscribe("environment/temperature2", myHandler, "400038001747343338333633"); //third field is the second particles access token
  Serial.begin(9600);
  
  
 
 
     
 
}

void loop() {
    digitalWrite(D7,!digitalRead(D7)); //blink D7
    wd.checkin(); //watchdog checkin
    
    if (System.buttonPushed() > 2000) { //trigger a wifi disconnect if you hold for over 2 seconds.
        //RGB.color(255, 255, 0); // YELLOW
        if (Particle.connected() == false) {  //if not connected, delay, 5000ms before attempting reconnect.  without delay was causing gps to fail.
            Serial.println("Connecting to wifi");
		    Particle.connect();
		    delay(1000);
        } else {
            //Particle.disconnect();
            WiFi.off();
            delay(1000);
        }   
   
    }
    

    
    
}
//this function runs regularly to determine whether the stove top is hot in real time.   
void stovestatus(){
    if (stoveTemp>=78 or onoroff2==1){
        onoroff=1;
        Particle.publish("The stove is on",int(onoroff));
     
    }
    else{
        onoroff=0;
        Particle.publish("the stove is off", int(onoroff));
        
    }
}
//IFTTT calls this function only when the user leaves the geofence defined by the app.  If the user leaves the house AND the stove or oven is hot the user will be notified.   
int checkStove(String check)  {
    if (onoroff==1){
         danger=1;
         return 1;
        }else{
         danger=0;
         return 0;
        }
        
    
}

void serialDebug() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" *C");

    Serial.print("Pressure = ");

    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");

    Serial.print("Approx. Altitude = ");
    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
    Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");

    Serial.println();
}

void checkEnvironment() {

  Particle.publish("RSSI", String(WiFi.RSSI()));
  //Particle.publish("DEBUG", "checking the environment...");
  stoveTemp = cToF(bme.readTemperature());
  Particle.publish("environment/temperature", String(stoveTemp));  //publish the temperature of the stove every ten seconds
  Particle.publish("Temperature 1",String(stoveTemp),PUBLIC);  //this publish function is caught by thingspeak.  Be sure to set up your webhook to catch this event name.
  delay(30000);
} 

  


void checkEnvironment2() {

  baro = pToHg(bme.readPressure());
  Particle.publish("environment/pressure", String(baro));
  Particle.publish("environment/altitude", String(bme.readAltitude(SEALEVELPRESSURE_HPA)));
  humidity = bme.readHumidity();
  Particle.publish("environment/humidity", String(humidity));

 
}


//this fuction processes the information published by sensor 2
void myHandler(const char *event,const char *data){
    onoroff2=int(*data)-48;
    if (onoroff2==1){
        Particle.publish("The stove is ON", int (onoroff2));
    }else{
        Particle.publish("The stove is OFF", int (onoroff2));    
    }
}



float cToF(float c) {
  return c * 9/5 + 32;
}

float pToHg(float p) {
  return p/3389.39;
}

Particle 2 Code

Plain text
Flash this code to Particle 2 (the secondary particle that passes data to Particle 1 for processing)
//Particle 2 Code

// This #include statement was automatically added by the Particle IDE.
#include "Adafruit_BME280/Adafruit_BME280.h"

/***************************************************************************
  This is a library for the BME280 humidity, temperature & pressure sensor
  Designed specifically to work with the Adafruit BME280 Breakout
  ----> http://www.adafruit.com/products/2650
  These sensors use I2C or SPI to communicate, 2 or 4 pins are required
  to interface.
  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!
  Written by Limor Fried & Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
  This file was modified by Markus Haack (https://github.com/mhaack)
  in order to work with Particle Photon & Core.
  Then further modified by Mac McAlpine https://github.com/macsboost
  And also by James Freeman
 ***************************************************************************/
 
//#include "Adafruit_BME280/Adafruit_Sensor.h"
#include "Adafruit_BME280/Adafruit_BME280.h"

#define BME_SCK D4
#define BME_MISO D3
#define BME_MOSI D2
#define BME_CS D5

#define SEALEVELPRESSURE_HPA (1013.25)

//This Sketch measure differential pressure across the air filter in the house HVAC

/*                                    +-----+
 *                          +----------| USB |----------+
 *                          |          +-----+       *  |
 *                          | [ ] VIN           3V3 [ ] |
 *                          | [ ] GND           RST [ ] |
 *                          | [ ] TX           VBAT [ ] |
 *                          | [ ] RX  [S]   [R] GND [ ] |
 *                          | [ ] WKP            D7 [*] |
 *                          | [ ] DAC +-------+  D6 [*] |
 *                          | [ ] A5  |   *   |  D5 [*] |
 *                          | [ ] A4  |Photon |  D4 [*] |P1 PWR
 *                          | [ ] A3  |       |  D3 [*] |P2 PWR
 *                          | [ ] A2  +-------+  D2 [*] |
 *                      P1  | [*] A1             D1 [*] |SCL BME 0x76
 *                      P2  | [*] A0             D0 [*] |SDA BME 0x76
 *                          |                           |
 *                           \    []         [______]  /
 *                            \_______________________/
 *
 *
 */

/*
   This sample code demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
   It requires the use of SoftwareSerial, and assumes that you have a
   230400-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/


Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);

Timer timer(14232, checkEnvironment); // call this function every 10 seconds
Timer timer2(9901, serialDebug); // call this function every 10 seconds
Timer timer3(10123, stovestatus);
Timer timer4(10233, checkEnvironment2);

int caladdress = 0;
double stoveTemp2 = 0;
double Temp=0;
double baro = 0;
double humidity = 0;
int onoroff2=0;
int danger2=0;


//ApplicationWatchdog wd(5000, System.reset); //5 second application watchdog
SYSTEM_MODE(SEMI_AUTOMATIC);



ApplicationWatchdog wd(60000, System.reset);


void setup() {
  Serial.begin(230400);
  Serial.println(F("BME280 test"));

  /*if (!bme.begin(0x76)) {  //0x76 is the i2c address of the sensor
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }*/
  
  
  Particle.publish("DEBUG", "starting...");

  if (bme.begin(0x76)) {  //0x76 is the i2c address of the sensor
    Particle.publish("DEBUG", "starting the environment timer...");
    timer.start(); //initialize timer
    timer2.start();//initialize timer2
    timer3.start();//initialize timer2
    timer4.start();
  }
  else {
    Particle.publish("WARN", "Could not find a valid BMP280 sensor, check wiring!");
  }

  Particle.publish("DEBUG", "started!");
 
  Particle.connect(); 
  Particle.variable("bme280temp", stoveTemp2);
  Particle.variable("bme280baro", baro);
  Particle.variable("bme280humid", humidity);
  Particle.variable("Stv:2on0Off", onoroff2);
  Particle.variable("DANGER", danger2);
  Particle.function("checkStove", checkStove);


  
}

void loop() {
    digitalWrite(D7,!digitalRead(D7)); //blink D7
    wd.checkin(); //watchdog checkin
    
    if (System.buttonPushed() > 2000) { //trigger a wifi disconnect if you hold for over 2 seconds.
        //RGB.color(255, 255, 0); // YELLOW
        if (Particle.connected() == false) {  //if not connected, delay, 5000ms before attempting reconnect.  without delay was causing gps to fail.
            Serial.println("Connecting to wifi");
		    Particle.connect();
		    delay(1000);
        } else {
            //Particle.disconnect();
            WiFi.off();
            delay(1000);
        }   
   
    }
    
    
}

void stovestatus(){
    if (stoveTemp2>=78){
        onoroff2=1;
        Particle.publish("The stove is on",int(onoroff2));
     
    }
    else{
        onoroff2=0;
        Particle.publish("The stove is off", int(onoroff2));
        
    }
}

int checkStove(String check)  {
    if (stoveTemp2>=78){
         danger2=1;
         return 1;
        }else{
         danger2=0;
         return 0;
        }
        
    
}

void serialDebug() {
    Serial.print("Temperature = ");
    Serial.print(bme.readTemperature());
    Serial.println(" *C");

    Serial.print("Pressure = ");

    Serial.print(bme.readPressure() / 100.0F);
    Serial.println(" hPa");

    Serial.print("Approx. Altitude = ");
    Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
    Serial.println(" m");

    Serial.print("Humidity = ");
    Serial.print(bme.readHumidity());
    Serial.println(" %");

    Serial.println();
}

void checkEnvironment() {

  Particle.publish("RSSI", String(WiFi.RSSI()));
  //Particle.publish("DEBUG", "checking the environment...");
  stoveTemp2 = cToF(bme.readTemperature());
  Particle.publish("environment/temperature2", int (onoroff2), PUBLIC);  //publishes the on/off status read by sensor 2 to be caught by a subcribe fuction of particle 1.  
  
 
  
}

void checkEnvironment2() {

  baro = pToHg(bme.readPressure());
  Particle.publish("environment/pressure", String(baro));
  Particle.publish("environment/altitude", String(bme.readAltitude(SEALEVELPRESSURE_HPA)));
  humidity = bme.readHumidity();
  Particle.publish("environment/humidity", String(humidity));

 
}


float cToF(float c) {
  return c * 9/5 + 32;
}

float pToHg(float p) {
  return p/3389.39;
}

Credits

Jonathan Caleb Dosh

Jonathan Caleb Dosh

1 project • 0 followers
Junior Mechanical Engineering Student Expected Graduation Spring 2018 UNC Charlotte
James Freeman

James Freeman

1 project • 1 follower
Thanks to John McAlpine and My roommate Steve.

Comments