Things used in this project

Hardware components:
Photon new
Particle Photon
×2
relay 5v
×1
honeywell magnetic Contact Switch
×2
386 00
DHT11 Temperature & Humidity Sensor
×1
Amazon echo dot
Amazon Alexa Echo Dot
×1
Software apps and online services:
Gawd2jnp51w1h1ccsulo
IFTTT Amazon Alexa service
Mobicle 1024
ControlEverything.com Mobicle
Hackster
ThingSpeak API

Schematics

Project Bread Board
Screen shot 2017 04 10 at 9 44 06 pm ppsrw6kfyy
Project Schematic
Screen shot 2017 04 10 at 9 43 57 pm ozopfaar6k
Schematic 2
Screen shot 2017 04 10 at 9 34 26 pm jp6w09rvrm

Code

GarageDoorArduino
Garage Door Code to wifi remote access
// This #include statement was automatically added by the Particle IDE.
#include "PietteTech_DHT/PietteTech_DHT.h"
// Code inspired by Prof. John Macalpine

 /*                           +-----+
 *                 +----------| USB |----------+
 *                 |          +-----+       *  |
 *  DHT11 V(in) -->| [ ] VIN           3V3 [ ] |<-- Relay VCC
 *                 | [ ] GND           RST [ ] |
 *                 | [ ] TX           VBAT [ ] |
 *                 | [ ] RX  [S]   [R] GND [ ] |<-- Relay GND
 *                 | [ ] WKP            D7 [ ] |
 *                 | [ ] DAC +-------+  D6 [ ] |
 *   Opensensor -->| [*] A5  |   *   |  D5 [ ] |
 * Closedsensor -->| [*] A4  |Photon |  D4 [*] |<-- DHT111 AM2301 Sensor
 *                 | [*] A3  |       |  D3 [ ] |
 *                 | [ ] A2  +-------+  D2 [ ] |
 *                 | [ ] A1             D1 [ ] |
 *                 | [ ] A0             D0 [*] |<-- Garage Door Switch Relay
 *                 |                           |
 *                  \    []         [______]  /
 *                   \_______________________/
 *
 *
 */

const String key = "HM51Z16VGAII6IX5"; //write key

//--------------Begin DHT------------------
// Example testing sketch for various DHT humidity/temperature sensors


#define DHTPIN D4     // what pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11		// DHT 11 

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor


//declaration
void dht_wrapper(); // must be declared before the lib initialization

// Lib instantiate
PietteTech_DHT DHT(DHTPIN, DHTTYPE, dht_wrapper);
// globals
unsigned int DHTnextSampleTime;	    // Next time we want to start sample
bool bDHTstarted;		    // flag to indicate we started acquisition
int n;                              // counter

//---------------End DHT-------------------


unsigned int particleinterval = 100;
unsigned int particlefuncinterval = 10000;
unsigned int ubiinterval = 15000;
unsigned int dhtinterval = 5000;

int garageDoorFunction(String command);

int rssival = 0;
int doorstatus = 1;
int doorcounter = 0;
int closedsensorpin = A4;
int opensensorpin = A5; 
const int open = 0;
const int closed = 1;

// Define the pins we're going to call pinMode on
int led = D6;  // You'll need to wire an LED to this one to see it blink.
int led2 = D7; // This one is the built-in tiny one to the right of the USB jack


double analog1 = 0;
double analog2 = 0;
double analog1raw = 0;
double analog2raw = 0;
double garagetemp = 70;
double readtemp = 70;
double garagehumid = 0;


char publishString[40];
char doorpublishstring[40];
char doorstatusstring[40];

SYSTEM_MODE(SEMI_AUTOMATIC); //allows for control of Spark.connect() and Spark.process()

// This routine runs only once upon reset
Timer task50ms(50, dodoor);
Timer task10sec(10000,dopublish);
Timer task15sec(15000,updateThingspeak);
Timer taskdht(5000, readdht);

void setup() {
    task50ms.start();
    task10sec.start();
    task15sec.start();
    taskdht.start();
    
    pinMode(led, OUTPUT);
    pinMode(led2, OUTPUT);
    pinMode(A0, INPUT);
    pinMode(A1, INPUT);
    Serial1.begin(230400);   // open serial over USB
    //ip = {"IP:", WiFi.localIP()};
    //String ip = WiFi.localIP();

    Particle.function("GarageDoor", garageDoorFunction);
    Particle.variable("analog1", &analog1, DOUBLE);  //variables update automatically. Max 4 per particle
    Particle.variable("doorcounter", doorcounter);
    //Particle.variable("doorstatus", &doorstatus, INT); //variables are viewable on mobicle 
    Particle.variable("doorstatus", doorstatusstring, STRING); //variables are viewable on mobicle 
    Particle.variable("garagetemp", &garagetemp, DOUBLE); //variables are viewable on mobicle
    Particle.variable("garagehumid", &garagehumid, DOUBLE); //variables are viewable on mobicle
    
    pinMode(opensensorpin, INPUT_PULLUP);
    pinMode(closedsensorpin, INPUT_PULLUP);

    pinMode(D0, OUTPUT);

    //Do DHTINIT
    pinMode(DHTPIN, INPUT_PULLUP); //sensor needs pullup resistor.
	//End DHTINIT

//-------------Begin UBIDOTS---------------
//    request.hostname = "things.ubidots.com";
//    request.port = 80;
//    request.path = "/api/v1.6/variables/"VARIABLE_ID"/values?token="TOKEN;
//--------------End UBIDOTS----------------
}

// This wrapper is in charge of calling
// mus be defined like this for the lib work
void dht_wrapper() {
    DHT.isrCallback();
}

void loop() {
    if (Particle.connected() == false){
            Particle.connect();
    }
    analog1raw = analogRead(A0);
    analog1 = (analog1 *63 +analog1raw *3.3/4095)/64;
    analog2raw = analogRead(A1);
    analog2 = (analog2 *63 +analog2raw *3.3/4095)/64;

    doDht();
}

void dopublish(){
    rssival = WiFi.RSSI();
    sprintf(publishString,"%d",rssival);
                
    Particle.publish("RSSI",publishString);
}

void readdht() {
    if (!bDHTstarted) {		// start the sample
    Serial.print("\n");
    Serial.print(n);
    Serial.print(": Retrieving information from sensor: ");
    DHT.acquire();
    bDHTstarted = true;
    }
}

void dodoor() {
    
        digitalWrite(led, !digitalRead(led));   // Turn ON the LED pins
        digitalWrite(led2, !digitalRead(led2));
    
        int opensense = digitalRead(opensensorpin);
        int closedsense = digitalRead(closedsensorpin);


        if (opensense == LOW) // high,0 = open door, low,1 = closed door
        {  
            if (doorstatus == closed) //check the previous state, if closed, then generate an event
            {
                strcpy(doorpublishstring, "Open");
                Particle.publish("ON",doorpublishstring); // Publishing Open Event for second Photon
                doorcounter++;
            }
            doorstatus = open;
            strcpy(doorstatusstring, "Open"); //update particle variable.
        } 
        else if (closedsense == LOW)
        {
            if (doorstatus == open) //check the previous state, if closed, then generate an event
            {
                strcpy(doorpublishstring, "Closed");
                Particle.publish("OFF",doorpublishstring); //Publishing Close Event for second Photon
                doorcounter++;
            }
            doorstatus = closed;
            strcpy(doorstatusstring, "Closed");  //update particle variable.
        }
            else 
            {  //if door is neither closed or open, it is in "limbo" 
                strcpy(doorstatusstring, "Limbo");  //update particle variable.
            }
}


/*******************************************************************************
 * Function Name  : garageDoor
 * Description    : based on door status, opens or closes the door
 * Input          : analog 5 - digital input.
 * Output         : digital 1 - relay to blip and open or close the door
 * Return         : Value of the pin (0 or 1) in INT type
                    Returns a negative number on failure
 *******************************************************************************/
int garageDoorFunction(String sesame)
{
    if(sesame.startsWith("C"))
	{
		if (doorstatus == open)
		{
	        pinMode(0, OUTPUT);
		    digitalWrite(0, 1);
		    delay(250);
		    digitalWrite(0, 0);
		return 1;
		}
	}
	else if (sesame.startsWith("O"))
		{
        if (doorstatus == closed)
		{
	        pinMode(0, OUTPUT);
		    digitalWrite(0, 1);
		    delay(250);
		    digitalWrite(0, 0);
		return 2;
		}
	}
	else if (sesame.startsWith("X"))
		{
        if (doorstatus == closed){
            return 999;
        } else
        return 123;
		}
	return -1;
	
}



/*******************************************************************************
 * Function Name  : updateThingspeak
 * Description    : sends variables to ts
 * Input          : doorstatus global variables
 * Output         : sends data to ts
 * Return         : void
                    
 *******************************************************************************/
bool updateThingspeak() 
{
    //delay (2000);
    static int count = 0;
    Serial.println(count++);
    int rssival = WiFi.RSSI();
    //sprintf(publishString,"%d",rssival);
    //bool success = Particle.publish("RSSI",publishString);
    
    //sprintf(publishString, "%1.4f", checkbattery());

      bool success = Particle.publish("thingSpeakWrite_All", +
     "{ \"1\": \"" + String(rssival) + "\"," +
       "\"2\": \"" + String(garagetemp) + "\"," +
       "\"3\": \"" + String(garagehumid) + "\"," +
       "\"4\": \"" + String(doorstatus) + "\"," +
       "\"5\": \"" + String(doorcounter) + "\"," +
       //"\"6\": \"" + String(analog1) + "\"," +
       //"\"7\": \"" + String(analog2) + "\"," +
       "\"k\": \"" + key + "\" }", 60, PRIVATE);
    return success; //if sent, then turn of the send flag, otherwise let it try again.
    
}

/*******************************************************************************
 * Function Name  : getDht
 * Description    : gets temp and humidity
 * Input          : 
 * Output         : 
 * Return         : void
                    
 *******************************************************************************/
void doDht() {
    if (!DHT.acquiring()) {		// has sample completed?

	    // get DHT status
	    int result = DHT.getStatus();

	    Serial.print("Read DHT sensor: ");
	    switch (result) {
		case DHTLIB_OK:
		    Serial.println("OK");
		   	garagehumid = DHT.getHumidity();
            // Read temperature as Celsius
	        //garagetemp = DHT.getCelsius();
            // Read temperature as Farenheit
	        garagetemp = DHT.getFahrenheit();
	        break;
		case DHTLIB_ERROR_CHECKSUM:
		    Serial.println("Error\n\r\tChecksum error");
		    break;
		case DHTLIB_ERROR_ISR_TIMEOUT:
		    Serial.println("Error\n\r\tISR time out error");
		    break;
		case DHTLIB_ERROR_RESPONSE_TIMEOUT:
		    Serial.println("Error\n\r\tResponse time out error");
		    break;
		case DHTLIB_ERROR_DATA_TIMEOUT:
		    Serial.println("Error\n\r\tData time out error");
		    break;
		case DHTLIB_ERROR_ACQUIRING:
		    Serial.println("Error\n\r\tAcquiring");
		    break;
		case DHTLIB_ERROR_DELTA:
		    Serial.println("Error\n\r\tDelta time to small");
		    break;
		case DHTLIB_ERROR_NOTSTARTED:
		    Serial.println("Error\n\r\tNot started");
		    break;
		default:
		    Serial.println("Unknown error");
		    break;
	    }


        /*
	    Serial.print("Humidity (%): ");
	    Serial.println(DHT.getHumidity(), 2);

	    Serial.print("Temperature (oC): ");
	    Serial.println(DHT.getCelsius(), 2);

	    Serial.print("Temperature (oF): ");
	    Serial.println(DHT.getFahrenheit(), 2);
        
	    Serial.print("Temperature (K): ");
	    Serial.println(DHT.getKelvin(), 2);

	    Serial.print("Dew Point (oC): ");
	    Serial.println(DHT.getDewPoint());

	    Serial.print("Dew Point Slow (oC): ");
	    Serial.println(DHT.getDewPointSlow());
        */
        
	    n++;  // increment counter
	    bDHTstarted = false;  // reset the sample flag so we can take another
	}

	//Serial.println(Time.timeStr());
}
Garage Photon 2 SubscribeArduino
Code for subscription of an event from 1st Photon
//Code For subscribing the event from first photon

int led = D7;

void setup() {
    
    pinMode(led, OUTPUT);
    digitalWrite(led, LOW);
    Particle.subscribe("ON",anything, "200040000147353138383138"); // Recieving Open Event
    Particle.subscribe("OFF",anything2, "200040000147353138383138"); // Recieving Close Event
}
void anything(const char *event, const char *data)
{
    digitalWrite(led, HIGH);
}
void anything2(const char *event, const char *data)
{
    digitalWrite(led, LOW);
}
void loop() {

}
PIETTETECH_DHT CodeArduino
Code For DHT Sensor
it is already in Build.particle library
/*
 * FILE:        PietteTech_DHT.cpp
 * VERSION:     0.4
 * PURPOSE:     Spark Interrupt driven lib for DHT sensors
 * LICENSE:     GPL v3 (http://www.gnu.org/licenses/gpl.html)
 *
 * S Piette (Piette Technologies) scott.piette@gmail.com
 *      January 2014        Original Spark Port
 *      October 2014        Added support for DHT21/22 sensors
 *                          Improved timing, moved FP math out of ISR
 *      September 2016      Updated for Particle and removed dependency
 *                          on callback_wrapper.  Use of callback_wrapper
 *                          is still for backward compatibility but not used
 *
 *                          is still for backward compatibility but not used
 * ScruffR
 *      February 2017       Migrated for Libraries 2.0
 *                          Fixed blocking acquireAndWait()
 *                          and previously ignored timeout setting
 *
 * Based on adaptation by niesteszeck (github/niesteszeck)
 * Based on original DHT11 library (http://playgroudn.adruino.cc/Main/DHT11Lib)
 *
 *
 * With this library connect the DHT sensor to the following pins
 * Spark Core: D0, D1, D2, D3, D4, A0, A1, A3, A5, A6, A7
 * Particle  : any Pin but D0 & A5
 * See docs for more background
 *   https://docs.particle.io/reference/firmware/photon/#attachinterrupt-
 */

 /*
     Timing of DHT22 SDA signal line after MCU pulls low for 1ms
     https://github.com/mtnscott/Spark_DHT/AM2302.pdf

   - - - -            -----           -- - - --            ------- - -
          \          /     \         /  \      \          /
           +        /       +       /    +      +        /
            \      /         \     /      \      \      /
             ------           -----        -- - --------
  ^        ^                ^                   ^          ^
  |   Ts   |        Tr      |        Td         |    Te    |

     Ts : Start time from MCU changing SDA from Output High to Tri-State (Hi-Z)
          Spec: 20-200us             Tested: < 65us
     Tr : DHT response to MCU controlling SDA and pulling Low and High to
          start of first data bit
          Spec: 150-170us            Tested: 125 - 200us
     Td : DHT data bit, falling edge to falling edge
          Spec: '0' 70us - 85us      Tested: 60 - 110us
          Spec: '1' 116us - 130us    Tested: 111 - 155us
     Te : DHT releases SDA to Tri-State (Hi-Z)
          Spec: 45-55us              Not Tested
  */

#include "PietteTech_DHT.h"

#if !defined(word)
  // Thanks to Paul Kourany for this word type conversion function
uint16_t word(uint8_t high, uint8_t low) {
  uint16_t ret_val = low;
  ret_val += (high << 8);
  return ret_val;
}
#endif

/*
 * NOTE:  callback_wrapper is only here for backwards compatibility with v0.3 and earlier
 *        it is no longer used or needed
 */
PietteTech_DHT::PietteTech_DHT(uint8_t sigPin, uint8_t dht_type, void(*callback_wrapper)()) {
  begin(sigPin, dht_type);
  _firstreading = true;
}

/*
 * NOTE:  callback_wrapper is only here for backwards compatibility with v0.3 and earlier
 *        it is no longer used or needed
 */
void PietteTech_DHT::begin(uint8_t sigPin, uint8_t dht_type, void(*callback_wrapper)()) {
  _sigPin = sigPin;
  _type = dht_type;

  pinMode(sigPin, OUTPUT);
  digitalWrite(sigPin, HIGH);
  _lastreadtime = 0;
  _state = STOPPED;
  _status = DHTLIB_ERROR_NOTSTARTED;
}

int PietteTech_DHT::acquire() {
  // Check if sensor was read less than two seconds ago and return early
  // to use last reading
  unsigned long currenttime = millis();
  if (!_firstreading && ((currenttime - _lastreadtime) < 2000)) {
    // return last correct measurement, (this read time - last read time) < device limit
    return DHTLIB_ACQUIRED;
  }

  if (_state == STOPPED || _state == ACQUIRED) {
    /*
     * Setup the initial state machine
     */
    _firstreading = false;
    _lastreadtime = currenttime;
    _state = RESPONSE;

#if defined(DHT_DEBUG_TIMING)
    /*
     * Clear the debug timings array
     */
    for (int i = 0; i < 41; i++) _edges[i] = 0;
    _e = &_edges[0];
#endif

    /*
     * Set the initial values in the buffer and variables
     */
    for (int i = 0; i < 5; i++) _bits[i] = 0;
    _cnt = 7;
    _idx = 0;
    _hum = 0;
    _temp = 0;

    /*
     * Toggle the digital output to trigger the DHT device
     * to send us temperature and humidity data
     */
    pinMode(_sigPin, OUTPUT);
    digitalWrite(_sigPin, LOW);
    if (_type == DHT11)
      delay(18);                  // DHT11 Spec: 18ms min
    else
      delayMicroseconds(1500);    // DHT22 Spec: 0.8-20ms, 1ms typ
    pinMode(_sigPin, INPUT);        // Note Hi-Z mode with pullup resistor
                                    // will keep this high until the DHT responds.
    /*
     * Attach the interrupt handler to receive the data once the DHT
     * starts to send us data
     */
    _us = micros();
    attachInterrupt(_sigPin, &PietteTech_DHT::_isrCallback, this, FALLING);

    return DHTLIB_ACQUIRING;
  }
  else
    return DHTLIB_ERROR_ACQUIRING;
}

int PietteTech_DHT::acquireAndWait(uint32_t timeout) {
  acquire();
  uint32_t start = millis();
  while (acquiring() && (timeout == 0 || ((millis() - start) < timeout))) Particle.process();
  if (acquiring())
  {
    _status = DHTLIB_ERROR_RESPONSE_TIMEOUT;
  }
  return getStatus();
}

/*
 * NOTE:  isrCallback is only here for backwards compatibility with v0.3 and earlier
 *        it is no longer used or needed
 */
void PietteTech_DHT::isrCallback() { }

void PietteTech_DHT::_isrCallback() {
  unsigned long newUs = micros();
  unsigned long delta = (newUs - _us);
  _us = newUs;

  if (delta > 6000) {
    _status = DHTLIB_ERROR_ISR_TIMEOUT;
    _state = STOPPED;
    detachInterrupt(_sigPin);
    return;
  }
  switch (_state) {
  case RESPONSE:            // Spec: 80us LOW followed by 80us HIGH
    if (delta < 65) {      // Spec: 20-200us to first falling edge of response
      _us -= delta;
      break; //do nothing, it started the response signal
    } if (125 < delta && delta < 200) {
#if defined(DHT_DEBUG_TIMING)
      *_e++ = delta;  // record the edge -> edge time
#endif
      _state = DATA;
    }
    else {
      detachInterrupt(_sigPin);
      _status = DHTLIB_ERROR_RESPONSE_TIMEOUT;
      _state = STOPPED;
#if defined(DHT_DEBUG_TIMING)
      *_e++ = delta;  // record the edge -> edge time
#endif
    }
    break;
  case DATA:          // Spec: 50us low followed by high of 26-28us = 0, 70us = 1
    if (60 < delta && delta < 155) { //valid in timing
      _bits[_idx] <<= 1; // shift the data
      if (delta > 110) //is a one
        _bits[_idx] |= 1;
#if defined(DHT_DEBUG_TIMING)
      *_e++ = delta;  // record the edge -> edge time
#endif
      if (_cnt == 0) { // we have completed the byte, go to next
        _cnt = 7; // restart at MSB
        if (++_idx == 5) { // go to next byte, if we have got 5 bytes stop.
          detachInterrupt(_sigPin);
          // Verify checksum
          uint8_t sum = _bits[0] + _bits[1] + _bits[2] + _bits[3];
          if (_bits[4] != sum) {
            _status = DHTLIB_ERROR_CHECKSUM;
            _state = STOPPED;
          }
          else {
            _status = DHTLIB_OK;
            _state = ACQUIRED;
            _convert = true;
          }
          break;
        }
      }
      else _cnt--;
    }
    else if (delta < 10) {
      detachInterrupt(_sigPin);
      _status = DHTLIB_ERROR_DELTA;
      _state = STOPPED;
    }
    else {
      detachInterrupt(_sigPin);
      _status = DHTLIB_ERROR_DATA_TIMEOUT;
      _state = STOPPED;
    }
    break;
  default:
    break;
  }
}

void PietteTech_DHT::convert() {
  // Calculate the temperature and humidity based on the sensor type
  switch (_type) {
  case DHT11:
    _hum = _bits[0];
    _temp = _bits[2];
    break;
  case DHT22:
  case DHT21:
    _hum = word(_bits[0], _bits[1]) * 0.1;
    _temp = (_bits[2] & 0x80 ?
      -word(_bits[2] & 0x7F, _bits[3]) :
      word(_bits[2], _bits[3])) * 0.1;
    break;
  }
  _convert = false;
}

bool PietteTech_DHT::acquiring() {
  if (_state != ACQUIRED && _state != STOPPED)
    return true;
  return false;
}

int PietteTech_DHT::getStatus() {
  return _status;
}

float PietteTech_DHT::getCelsius() {
  DHT_CHECK_STATE;
  return _temp;
}

float PietteTech_DHT::getHumidity() {
  DHT_CHECK_STATE;
  return _hum;
}

float PietteTech_DHT::getFahrenheit() {
  DHT_CHECK_STATE;
  return _temp * 9 / 5 + 32;
}

float PietteTech_DHT::getKelvin() {
  DHT_CHECK_STATE;
  return _temp + 273.15;
}

/*
 * Added methods for supporting Adafruit Unified Sensor framework
 */
float PietteTech_DHT::readTemperature() {
  acquireAndWait();
  return getCelsius();
}

float PietteTech_DHT::readHumidity() {
  acquireAndWait();
  return getHumidity();
}

// delta max = 0.6544 wrt dewPoint()
// 5x faster than dewPoint()
// reference: http://en.wikipedia.org/wiki/Dew_point
double PietteTech_DHT::getDewPoint() {
  DHT_CHECK_STATE;
  double a = 17.271;
  double b = 237.7;
  double temp_ = (a * (double)_temp) / (b + (double)_temp) + log((double)_hum / 100);
  double Td = (b * temp_) / (a - temp_);
  return Td;
}

// dewPoint function NOAA
// reference: http://wahiduddin.net/calc/density_algorithms.htm
double PietteTech_DHT::getDewPointSlow() {
  DHT_CHECK_STATE;
  double a0 = (double) 373.15 / (273.15 + (double)_temp);
  double SUM = (double)-7.90298 * (a0 - 1.0);
  SUM += 5.02808 * log10(a0);
  SUM += -1.3816e-7 * (pow(10, (11.344*(1 - 1 / a0))) - 1);
  SUM += 8.1328e-3 * (pow(10, (-3.49149*(a0 - 1))) - 1);
  SUM += log10(1013.246);
  double VP = pow(10, SUM - 3) * (double)_hum;
  double T = log(VP / 0.61078); // temp var
  return (241.88 * T) / (17.558 - T);
}
Thingspeak IntergrationJSON
{
    "event": "thingSpeakWrite_",
    "url": "https://api.thingspeak.com/update",
    "requestType": "POST",
    "form": {
        "api_key": "{{k}}",
        "field1": "{{1}}",
        "field2": "{{2}}",
        "field3": "{{3}}",
        "field4": "{{4}}",
        "field5": "{{5}}",
        "field6": "{{6}}",
        "field7": "{{7}}",
        "field8": "{{8}}",
        "latitude": "{{a}}",
        "longitude": "{{o}}",
        "elevation": "{{e}}",
        "status": "{{s}}"
    },
    "mydevices": true,
    "noDefaults": true,
    "location": true
}

Credits

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

AquaNiner Pet Hydration Monitor
Intermediate
  • 382
  • 14

Full instructions

Using two Photons, IFTTT and ThingSpeak, get notifications for when your furry friend needs water and monitor how much they're drinking.

Hot Shot Hoops
Intermediate
  • 530
  • 13

Full instructions

No need to keep track of the number of baskets you make when shooting hoops. Hot Shot Hoops does the work for you.

Hot Shot Hoops

Team IOT Basketball

Temperature Mirror
Intermediate
  • 381
  • 8

Full instructions

The Temperature Mirror incorporates a digital display to allow its user to readily view time, temperature, humidity, and light.

Temperature Mirror

MEGR3171 Team 49

Pet Feeder
Intermediate
  • 414
  • 7

Full instructions

Automated pet food dispenser to feed our pets when we are not at home by using an IoT device.

Teacher Tracker
Intermediate
  • 176
  • 4

Full instructions

If you want to know when a professor comes back to his/her office so you can ask annoying questions then this an option

LightAlert
Intermediate
  • 138
  • 4

Full instructions

As the great Terry Crews once said "that's 49 cents of milk spilt over the table! Somebody's gonna drink that!" But instead... electricity.

ProjectsCommunitiesContestsLiveAppsBetaFree StoreBlogAdd projectSign up / Login
Respect project
Feedback