Things used in this project

Hardware components:
Particle Relay Sheild
×1
Photon new
Particle Photon
×2
Particle ds18b20 Sealed Temperature Sensor
×1
Mfr 25fbf52 4k75 sml
Resistor 4.75k ohm
×1
Mr. Coffee Single Button Coffe Pot
×1
11026 02
Jumper wires (generic)
×6
AC/DC Power Adapter
×1
Software apps and online services:
Q8wtlimqnp04fzhtr9v5
IFTTT Maker service
Google sheets
Google Sheets

Schematics

Relay Shield
The photon is inserted into the relay shield. The wires from the coffee pot are inserted into the relay shield at Relay 1.
Relayshield vlqyvdwjbk
Coffee Maker Used For This Project
Img 0094 utr9gdbaqi
Photon Relay Setup
Img 0092 0a7ha5jj9x
The Final Set Up
Img 0093 fxxyk7mghd
Temperature Sensor Circuit Diagram
The temperature sensor used for this project was the covered temperature sensor. The one seen in the diagram is the uncovered temperature sensor. The wiring is the same for both covered and uncovered. Reisistor is 4.7k ohm. The pins used on the photon are D4 for input (yellow), D5 for power/output (red), and ground (black).
Temp sensor circuit bb 8fpyedf8wn
IFTTT Applets used for Photon with Temperature Sensor
These are the two applets that were used for the temperature sensor photon. One of the apps monitors a variable so that when the coffee reaches a certain threshold the operator will receive a text message notifying that the coffee is ready and give a value for the temperature. The second applet is used to record data from the temperature sensor into a google spreadsheet connected via Google Docs.
Screen shot 2017 04 12 at 7 23 07 pm npusfptotp
IFTTT Applets for Relay control and Text confirmation
These are the applets used to place the do button widgets on the mobile device screen and receive text notifications when events publish.
Ifttt screenshot gzuq1ilvyv
Mobile Device Buttons
These buttons are used by IFTTT to call a function in the code that activates or deactivates the relay and controls power to the coffe pot. Used to start brewing.
Screenshot 2017 04 12 18 35 03 4rhylxkaan
Coffee brewing activation text
These texts are sent by IFTTT when the relay is activated and brewing is started.
Screenshot 2017 04 12 19 27 48 ienrr3hpdc
Text Message Notification: Coffee is Ready!
This picture is from a test run, thus leading to a value lower than the 165.
Img 0097 7yrtui9ncl
Graph from Google Drive
The graph shown is the coffee temperature during about a 5 minute time frame. Google sheets would not allow us to add a horizontal axis.
Screen shot 2017 04 12 at 7 40 00 pm lspr7bz0fp

Code

Temperature Sensor CodeC/C++
The following code for the Temperature sensor uses and includes OneWire from the library.
// This #include statement was automatically added by the Particle IDE.
#include <OneWire.h>

/************************************************************************
This sketch reads the temperature from a 1-Wire device and then publishes
to the Particle cloud. From there, IFTTT can be used to log the date,
time, and temperature to a Google Spreadsheet. Read more in our tutorial
here: https://docs.particle.io/tutorials/topics/maker-kit

This sketch is the same as the example from the OneWire library, but
with the addition of three lines at the end to publish the data to the
cloud.

Use this sketch to read the temperature from 1-Wire devices
you have attached to your Particle device (core, p0, p1, photon, electron)

Temperature is read from: DS18S20, DS18B20, DS1822, DS2438

Expanding on the enumeration process in the address scanner, this example
reads the temperature and outputs it from known device types as it scans.

I/O setup:
These made it easy to just 'plug in' my 18B20 (note that a bare TO-92
sensor may read higher than it should if it's right next to the Photon)

D3 - 1-wire ground, or just use regular pin and comment out below.
D4 - 1-wire signal, 2K-10K resistor to D5 (3v3)
D5 - 1-wire power, ditto ground comment.

A pull-up resistor is required on the signal line. The spec calls for a 4.7K.
I have used 1K-10K depending on the bus configuration and what I had out on the
bench. If you are powering the device, they all work. If you are using parisidic
power it gets more picky about the value.
************************************************************************/
OneWire ds = OneWire(D4);  // 1-wire signal on pin D4

unsigned long lastUpdate = 0;

float lastTemp;
double tempF=0;
int relay_is_active;
int temperature;

void myHandler(const char *event, String data)
  {  float relaystat;
        relaystat = data.toFloat();
        if (relaystat>=1){
        digitalWrite(D5, HIGH);
            digitalWrite (D7, HIGH);
             //  this block of code runs if the command matches one of the above options
   } else if (relaystat<=1){  
       digitalWrite(D5,LOW);
       digitalWrite(D7,LOW);//otherwise temp sensor and led light should be off
   }
  }


void setup() {
  Serial.begin(9600);
  Particle.subscribe("relay_is_active", myHandler,"260057001951353337343731");// subscribing to photon with relay in order to initate data log
  // Set up 'power' pins, comment out if not used!
  //declare output and input pins
  
  pinMode(D5, OUTPUT); // power for temp sensor
  pinMode(D7, OUTPUT);// led light on D7 to verify photon has recieved event from second photon
 // declare initial state of pins to be off
  digitalWrite(D5, LOW);// temp sensor pin
  digitalWrite(D7, LOW);// led
  
  pinMode(D4, INPUT);// data input from temp sensor
}
   
// up to here, it is the same as the address acanner
// we need a few more variables for this example

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;

  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }

  // The order is changed a bit in this example
  // first the returned address is printed

  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  // second the CRC is checked, on fail,
  // print error and just return to try again

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();

  // we have a good address at this point
  // what kind of chip do we have?
  // we will set a type_s value for known types or just return

  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS1820/DS18S20");
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    case 0x26:
      Serial.println("  Chip = DS2438");
      type_s = 2;
      break;
    default:
      Serial.println("Unknown device type.");
      return;
  }

  // this device has temp so let's read it

  ds.reset();               // first clear the 1-wire bus
  ds.select(addr);          // now select the device we just found
  // ds.write(0x44, 1);     // tell it to start a conversion, with parasite power on at the end
  ds.write(0x44, 0);        // or start conversion in powered mode (bus finishes low)

  // just wait a second while the conversion takes place
  // different chips have different conversion times, check the specs, 1 sec is worse case + 250ms
  // you could also communicate with other devices if you like but you would need
  // to already know their address to select them.

  delay(1000);     // maybe 750ms is enough, maybe not, wait 1 sec for conversion

  // we might do a ds.depower() (parasite) here, but the reset will take care of it.

  // first make sure current values are in the scratch pad

  present = ds.reset();
  ds.select(addr);
  ds.write(0xB8,0);         // Recall Memory 0
  ds.write(0x00,0);         // Recall Memory 0

  // now read the scratch pad

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE,0);         // Read Scratchpad
  if (type_s == 2) {
    ds.write(0x00,0);       // The DS2438 needs a page# to read
  }

  // transfer and print the values

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s == 2) raw = (data[2] << 8) | data[1];
  byte cfg = (data[4] & 0x60);

  switch (type_s) {
    case 1:
      raw = raw << 3; // 9 bit resolution default
      if (data[7] == 0x10) {
        // "count remain" gives full 12 bit resolution
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
      celsius = (float)raw * 0.0625;
      break;
    case 0:
      // at lower res, the low bits are undefined, so let's zero them
      if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
      if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
      if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
      // default is 12 bit resolution, 750 ms conversion time
      celsius = (float)raw * 0.0625;
      break;

    case 2:
      data[1] = (data[1] >> 3) & 0x1f;
      if (data[2] > 127) {
        celsius = (float)data[2] - ((float)data[1] * .03125);
      }else{
        celsius = (float)data[2] + ((float)data[1] * .03125);
      }
  }

  // remove random errors
  if((((celsius <= 0 && celsius > -1) && lastTemp > 5)) || celsius > 125) {
      celsius = lastTemp;
  }

  fahrenheit = celsius * 1.8 + 32.0;
  lastTemp = celsius;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");

  // now that we have the readings, we can publish them to the cloud
  String temperature = String(fahrenheit); // store temp in "temperature" string
  Particle.variable("temperature", temperature);// variable is used in order to recieve txt msg using IFTTT
  Particle.publish("temperature_800807745", temperature); // publish to cloud & subscribe to other photon using same event name
  
  delay(5000); // 5 second delay
  
}

 
Relay Control CodeC/C++
This code activates the relay to supply power and turn on the coffee pot. It also listens for a temperature value and deenergizes the relay when the value is reached.
#include "math.h"

/* Function prototypes -------------------------------------------------------*/
int tinkerDigitalRead(String pin);
int tinkerDigitalWrite(String command);
int tinkerAnalogRead(String pin);
int tinkerAnalogWrite(String command);

//This initializes the relay we are using to control power to the coffee pot. Linked to the D3 pin on the Photon.
int relay = D3;



//void myHandler(const char *event, const char *data)
//This function reads the data from the subscribe and checks it against the threshhold temperature value. If the temperature
//is greater than this value the relay is deenergized and the coffee pot is turned off.
void myHandler(const char *event, String data)
 {  float tempinf;
     tempinf = data.toFloat();
     if (tempinf >= 165){
		digitalWrite(D7, HIGH);
		pinMode(relay,OUTPUT);
		digitalWrite(relay, LOW);
		}
		else {
		    digitalWrite(D7, LOW);
		}
}
void setup()
{
	//Setup the Tinker application here

	//Register all the Tinker functions
	Particle.function("digitalread", tinkerDigitalRead);
	Particle.function("digitalwrite", tinkerDigitalWrite);
	Particle.function("analogread", tinkerAnalogRead);
	Particle.function("analogwrite", tinkerAnalogWrite);
    
    Particle.subscribe("temperature_800807745", myHandler,"34003c000347353138383138");	//This will run in a loop
    pinMode(relay,OUTPUT);
    pinMode(D7,OUTPUT);
    //digitalWrite(D7,HIGH);
   
}
//Publishes a zero value to notify another Photon to deenergize the temperature sensor.
/* This function loops forever --------------------------------------------*/
void loop()
{
    if (digitalRead(relay) ==0){
	    Particle.publish ("relay_is_active","0",60);
	    delay(10000);
}
}
//Everything below here is code for the Tinker app. Allows reading data and control of pins from a mobile device.
/*******************************************************************************
 * Function Name  : tinkerDigitalRead
 * Description    : Reads the digital value of a given pin
 * Input          : Pin
 * Output         : None.
 * Return         : Value of the pin (0 or 1) in INT type
                    Returns a negative number on failure
 *******************************************************************************/
int tinkerDigitalRead(String pin)
{
	//convert ascii to integer
	int pinNumber = pin.charAt(1) - '0';
	//Sanity check to see if the pin numbers are within limits
	if (pinNumber< 0 || pinNumber >7) return -1;

	if(pin.startsWith("D"))
	{
		pinMode(pinNumber, INPUT_PULLDOWN);
		return digitalRead(pinNumber);
	}
	else if (pin.startsWith("A"))
	{
		pinMode(pinNumber+10, INPUT_PULLDOWN);
		return digitalRead(pinNumber+10);
	}
	return -2;
}

/*******************************************************************************
 * Function Name  : tinkerDigitalWrite
 * Description    : Sets the specified pin HIGH or LOW
 * Input          : Pin and value
 * Output         : None.
 * Return         : 1 on success and a negative number on failure
 *******************************************************************************/
int tinkerDigitalWrite(String command)
{
	bool value = 0;
	//convert ascii to integer
	int pinNumber = command.charAt(1) - '0';
	//Sanity check to see if the pin numbers are within limits
	if (pinNumber< 0 || pinNumber >7) return -1;

	if(command.substring(3,7) == "HIGH") value = 1;
	else if(command.substring(3,6) == "LOW") value = 0;
	else return -2;

	if(command.startsWith("D"))
	{
		pinMode(pinNumber, OUTPUT);
		digitalWrite(pinNumber, value);
//Once the relay is commanded on this if statement publishes a 1 value, signaling another photon to turn on the temperature
//sensor and begin logging temperature data.
	if (digitalRead(relay) == 1){
	    Particle.publish ("relay_is_active","1",60);
	
	
	}
	    return 1;
	}
	else if(command.startsWith("A"))
	{
		pinMode(pinNumber+10, OUTPUT);
		digitalWrite(pinNumber+10, value);
		return 1;
	}
	else return -3;
}

/*******************************************************************************
 * Function Name  : tinkerAnalogRead
 * Description    : Reads the analog value of a pin
 * Input          : Pin
 * Output         : None.
 * Return         : Returns the analog value in INT type (0 to 4095)
                    Returns a negative number on failure
 *******************************************************************************/
int tinkerAnalogRead(String pin)
{
	//convert ascii to integer
	int pinNumber = pin.charAt(1) - '0';
	//Sanity check to see if the pin numbers are within limits
	if (pinNumber< 0 || pinNumber >7) return -1;

	if(pin.startsWith("D"))
	{
		return -3;
	}
	else if (pin.startsWith("A"))
	{
		return analogRead(pinNumber+10);
	}
	return -2;
}

/*******************************************************************************
 * Function Name  : tinkerAnalogWrite
 * Description    : Writes an analog value (PWM) to the specified pin
 * Input          : Pin and Value (0 to 255)
 * Output         : None.
 * Return         : 1 on success and a negative number on failure
 *******************************************************************************/
int tinkerAnalogWrite(String command)
{
	//convert ascii to integer
	int pinNumber = command.charAt(1) - '0';
	//Sanity check to see if the pin numbers are within limits
	if (pinNumber< 0 || pinNumber >7) return -1;

	String value = command.substring(3);

	if(command.startsWith("D"))
	{
		pinMode(pinNumber, OUTPUT);
		analogWrite(pinNumber, value.toInt());
		return 1;
	}
	else if(command.startsWith("A"))
	{
		pinMode(pinNumber+10, OUTPUT);
		analogWrite(pinNumber+10, value.toInt());
		return 1;
	}
	else return -2;
}

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

Well House Temperature Manager
Easy
  • 283
  • 6

Full instructions

Monitors the temperature of the well house to prevent the well from freezing.

Drink Alert!!! (Beverage Can Monitor)
Easy
  • 343
  • 4

Full instructions

Tired of going to grab a soda only to find they're all gone!? Well now you have an alert system to let you know when you need to refill.

The Food Thief Catcher
Easy
  • 161
  • 4

Work in progress

Are you tired of all of your pesky roommates stealing your food? Me too, thats why we have the Food Thief Catcher!

Temperature Sensor
Easy
  • 401
  • 5

Full instructions

A photon that measures the temperature and humididty with a DHT 22 sensor and communicates the temperature data to another photon.

Motion Activated Room Light
Easy
  • 160
  • 4

Full instructions

With this project, you'll never have to search for the light switch in the dark again.

Alexa Controlled Photon Project Without Alexa Coding
Easy
  • 1,041
  • 13

Full instructions

The Patriot Alexa Smart Home Skill and IoT library allow you to voice control your Photon quickly and easily with no Alexa coding at all.

Add projectSign up / Login
Respect project