Jason SvistunDennis Svistun
Published © GPL3+

Smart Mail

Being smart about your mail means not looking like an idiot checking an empty mailbox several times a day. Smart Mail makes your mail smart.

BeginnerFull instructions provided8 hours1,208
Smart Mail

Things used in this project

Hardware components

Photon
Particle Photon
×2
Breadboard (generic)
Breadboard (generic)
×2
Fremo Q-02 3200 mAh External Battery Pack Power Bank
×1
Resistor 221 ohm
Resistor 221 ohm
×1
LED (generic)
LED (generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

Maker service
IFTTT Maker service
Google Sheets
Google Sheets

Story

Read more

Schematics

IR Proximity Sensor Circuit

This is a very simple circuit diagram showing how to wire the IR Proximity Sensor to the first Particle Photon.

LED Indicator Circuit

A simple circuit diagram of the setup of the second Particle Photon which has a red LED (we ended up using a yellow colored LED since it was easier to see light up) that turns off whenever the Mailbox door is opened. This Photon is subscribed to the publications made by the IR Proximity Sensor Circuit.

Code

IR Proximity Camera/Sensor Code

C/C++
Check "Operation of the Code" for details on how it works.
// -----------------------------------------
// Publish and Console with IR Sensors
// -----------------------------------------
// This app will publish an event when your mailbox is opened.
// It will publish a different event when the mailbox is closed.

// Start by declaring which pins everything is plugged into.

int boardLed = D7; // This is the LED that is already on your device.
// On the Core, it's the LED in the upper right hand corner.
// On the Photon, it's next to the D7 pin.

int IRSensor = A0; // This is where your IR Sensor is plugged in. The other side goes to Vin due to voltage requirements (at least 4.5 V)

// The following values get set up when your device boots up and calibrates:
int intactValue; // This is the average value that the IR Sensor reads when the mailbox is closed.
int brokenValue; // This is the average value that the IR Sensor reads when the mailbox is opened.
int beamThreshold; // This is a value halfway between the mailbox opened and the mailbox closed. 

bool beamBroken = false; // This flag will be used to mark if we have a new status or not. It will be used in the loop.

char resultstr[64];

// Start with the setup function.

void setup() {
  pinMode(boardLed,OUTPUT); // The on-board LED is output.
  pinMode(IRSensor,INPUT);  // The IR Sensor pin is input (reading the IR Sensor).
  Particle.variable("result", resultstr, STRING);


  // Since everyone sets up their mailbox detection system differently, we are also going to start by calibrating our IR Sensor.
  // This one is going to require some input from the user!

  // First, the D7 LED will go on to tell you to open your mailbox to a position where you would consider the mailbox being opened.
  digitalWrite(boardLed,HIGH);
  delay(2000);

  // Then, the D7 LED will go off.
  digitalWrite(boardLed,LOW);
  delay(500);

  // Now take some readings...
  int open_1 = analogRead(IRSensor); // read IR Sensor
  delay(2000); // wait 2 seconds
  int open_2 = analogRead(IRSensor); // read IR Sensor
  delay(3000); // wait 3 seconds
  int open_3 = analogRead(IRSensor); // read IR Sensor
  delay(4000); // wait 4 seconds
  int open_4 = analogRead(IRSensor); // read IR Sensor
  delay(5000); // wait 5 seconds
  int open_5 = analogRead(IRSensor); // read IR Sensor
  delay(6000); // wait 6 seconds
  int open_6 = analogRead(IRSensor); // read IR Sensor
  delay(6000); // wait 6 seconds
  int open_7 = analogRead(IRSensor); // read IR Sensor
  delay(6000); // wait 6 seconds
  int open_8 = analogRead(IRSensor); // read IR Sensor
  delay(6000); // wait 6 seconds

  // Now flash to let us know that you've taken the readings...
  digitalWrite(boardLed,HIGH);
  delay(100);
  digitalWrite(boardLed,LOW);
  delay(100);
  digitalWrite(boardLed,HIGH);
  delay(100);
  digitalWrite(boardLed,LOW);
  delay(100);

  // Now the D7 LED will go on to tell you to close your mailbox...
  digitalWrite(boardLed,HIGH);
  delay(2000);

  // The D7 LED will turn off...
  digitalWrite(boardLed,LOW);

  // ...And now take more readings.
  int closed_1 = analogRead(IRSensor); // read IR Sensor
  delay(2000); // wait 2 seconds
  int closed_2 = analogRead(IRSensor); // read IR Sensor
  delay(3000); // wait 3 seconds
  int closed_3 = analogRead(IRSensor); // read IR Sensor
  delay(4000); // wait 4 seconds
  int closed_4 = analogRead(IRSensor); // read IR Sensor
  delay(5000); // wait 5 seconds
  int closed_5 = analogRead(IRSensor); // read IR Sensor
  delay(6000); // wait 6 seconds
  int closed_6 = analogRead(IRSensor); // read IR Sensor
  delay(6000); // wait 6 seconds
  int closed_7 = analogRead(IRSensor); // read IR Sensor
  delay(6000); // wait 6 seconds
  int closed_8 = analogRead(IRSensor); // read IR Sensor
  delay(6000); // wait 6 seconds

  // Now flash the D7 LED on and off three times to let us know that we're ready to go!
  digitalWrite(boardLed,HIGH);
  delay(100);
  digitalWrite(boardLed,LOW);
  delay(100);
  digitalWrite(boardLed,HIGH);
  delay(100);
  digitalWrite(boardLed,LOW);
  delay(100);
  digitalWrite(boardLed,HIGH);
  delay(100);
  digitalWrite(boardLed,LOW);


  // Now we average the "closed" and "open" values to get an idea of what the analog value reading will be with the mailbox closed and open.
  intactValue = (open_1+open_2+open_3+open_4+open_5+open_6+open_7+open_8)/8;
  brokenValue = (closed_1+closed_2+closed_3+closed_4+closed_5+closed_6+closed_7+closed_8)/8;

  // Let's also calculate the value between the mailbox closed and mailbox open.
  beamThreshold = (intactValue+brokenValue)/2;

}


// Now for the loop.

void loop() {
  /* In this loop function, we're going to check to see if the mailbox has been opened.
  When the status of the mailbox changes, we'll send a Particle.publish() to the cloud
  so that if we want to, we can check from other devices when the mailbox is opened or closed.

  We'll also turn the D7 LED on when the mailbox is opened.
  */

  if (analogRead(IRSensor)>beamThreshold) {

    /* If you are above the threshold, we'll assume the mailbox is closed.
    If the mailbox was closed before, though, we don't need to change anything.
    We'll use the beamBroken flag to help us find this out.
    This flag monitors the current status of the mailbox.
    After the mailbox is opened, it is set TRUE
    and when the mailbox is reclosed, it is set to FALSE.
    */

    if (beamBroken==true) {
        // If the mailbox was opened before, then this is a new status.
        // We will send a publish to the cloud.

        // Send a publish to your devices...
        Particle.publish("Mailbox_Status","Closed",60,MY_DEVICES);
        // And flash the on-board LED on and off.
        digitalWrite(boardLed,HIGH);
        delay(500);
        digitalWrite(boardLed,LOW);

        // Finally, set the flag to reflect the current status of the mailbox.
        beamBroken=false;
    }
    else {
        // Otherwise, this isn't a new status, and we don't have to do anything.
    }
  }

  else {
      // If you are below the threshold, the mailbox is probably open.
      if (beamBroken==false) {

        // Send a publish...
        Particle.publish("Mailbox_Status","Open",60,MY_DEVICES);
        // And flash the on-board LED on and off.
        digitalWrite(boardLed,HIGH);
        delay(500);
        digitalWrite(boardLed,LOW);

        // Finally, set the flag to reflect the current status of the mailbox.
        beamBroken=true;
      }
      else {
          // Otherwise, this isn't a new status, and we don't have to do anything.
      }
  }
  delay(1000);
  
  int data1 = analogRead(IRSensor);
  int data2 = beamBroken;
 sprintf(resultstr, "{\"data1\":%d, \"data2\":%d}", data1, data2);
 delay(1000);
 
}

LED Notification Code

C/C++
Check "Operation of the Code" for details on how this code works.
// -----------------------------------------
// Publish, Console, and Communicate with Additional Photon Particles
// -----------------------------------------
// This app will publish an event when a publish is made by an additional photon, triggering an LED.

// Start by declaring the pin of the LED.

int led = D0; // This is the LED that is used to signal an event has been published by an additional photon.

void setup()
{
  pinMode(led,OUTPUT); // The LED is output.
  digitalWrite(led,LOW);
}

void loop()
{
  Particle.subscribe("Mailbox_Status", myHandler); // This line of code subscribes to published events sent from another particle.
  delay(1000);
}

void myHandler(const char *event, const char *data) // This line of code is used to handle events and data associated with the published events subscribed to.
{
  if ((data)="Open"){
    digitalWrite(led,HIGH);
    delay(500);
    digitalWrite(led,LOW);
    delay(500);
    digitalWrite(led,HIGH);
    delay(500);
    digitalWrite(led,LOW);
    delay(500);
    digitalWrite(led,HIGH);
    delay(500);
    digitalWrite(led,LOW);
  }
  else {
  }
  delay(6000);
}

Google Spreadsheet and Published Events Plot/Graph Code

C/C++
The data collected from the photon, such as the analog values and status of the mailbox over a period of set time, was collected and then graphed. The information would then be sent and collected from the photon to the Google Spreadsheet. Lines 22, 29, and 179-181 from the "IR Proximity Camera/Sensor Code" are used to allow the collected data to be sent to the Google Spreadsheet. The code used in the Google Spreadsheet is pasted below.
function collectData() {
  var  sheet = SpreadsheetApp.getActiveSheet();

  var response = UrlFetchApp.fetch("https://api.spark.io/v1/devices/YOUR PHOTON DEVICE ID/result?access_token=YOUR PARTICLE ACCOUNT ACCESS TOKEN");

  try {
    var response = JSON.parse(response.getContentText()); // parse the JSON the Core API created
    var result = unescape(response.result); // you'll need to unescape before your parse as JSON
  
    try {
      var p = JSON.parse(result); // parse the JSON you created
      var d = new Date(); // time stamps are always good when taking readings
      sheet.appendRow([d, p.data1, p.data2]); // append the date, data1 to the sheet
    } catch(e)
    {
      Logger.log("Unable to do second parse");
    }
  } catch(e)
  {
    Logger.log("Unable to returned JSON");
  }
}

Credits

Jason Svistun

Jason Svistun

1 project • 2 followers
Dennis Svistun

Dennis Svistun

1 project • 1 follower

Comments