Michael FinlayJohn L.
Created November 17, 2017

WiFi Tripwire Alarm System

Use a photon with a PIR sensor as a motion sensor to publish data. Another photon will have a buzzer, rumble pad and LED to wake you up.

BeginnerShowcase (no instructions)5 hours44
WiFi Tripwire Alarm System

Things used in this project

Hardware components

Photon
Particle Photon
×2
PIR Motion Sensor (generic)
PIR Motion Sensor (generic)
×1
Buzzer
Buzzer
×1
LED (generic)
LED (generic)
×3
LilyPad Vibe Board
SparkFun LilyPad Vibe Board
×1
2AA Battery Holder for RTC
UDOO 2AA Battery Holder for RTC
×2
Micro-USB to USB Cable (Generic)
Micro-USB to USB Cable (Generic)
×1
Breadboard (generic)
Breadboard (generic)
×2
Perf+ 2
Crowd Supply Perf+ 2
×2
Case
×2

Software apps and online services

ThingSpeak API
ThingSpeak API

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Drill

Story

Read more

Schematics

Sender Circuit

This is the diagram showing what parts are present and to what pins they are connected to on the sender photon.

Receiver Circuit

This is the diagram showing what parts are present and to what pins they are connected to on the receiver photon.

Code

PIR-Sender

C/C++
This is the trip-wire code, it publishes a status when the IR sensor sees movement.
int read = A0;
int val;
int lite = D0;
bool beamBroken = true; // This flag will be used to mark if we have a new status or now. We will use it in the loop.

void setup() {
    pinMode(read,INPUT);
    pinMode(lite,OUTPUT);
}

void loop() {
    digitalWrite(lite,HIGH);
    val = 0;
    for(int i = 0; i < 100; i ++) {
        int rval = analogRead(read);
        if (rval > val) {
            val = rval;
        }
        delay(10);
    }
    if (val > 4000) {
        if (beamBroken==true) {
            // If the beam was broken before, then this is a new status.
            // We will send a publish to the cloud and turn the LED on.

            // Send a publish to your devices...
            Particle.publish("beamStatus","motion",60);
            // Finally, set the flag to reflect the current status of the beam.
            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 beam is probably broken.
        if (beamBroken==false) {

            // Send a publish...
            Particle.publish("beamStatus","clear",60);
            // Finally, set the flag to reflect the current status of the beam.
            beamBroken=true;
        }
        else {
          // Otherwise, this isn't a new status, and we don't have to do anything.
        }
    }

}

Receiver-graph

C/C++
Subscribes to the PIR code and activates a buzzer, rumble pad and LED when the PIR is triggered. Also counts triggers and sends that data to thing speak to graph.
int Buzzer = D0; // Setting the buzzer to a pin to power it
int motlite = D1;
int lite = D2;
int rumble = D3;
int Count = 0; // This variable will keep track of how many times the system has been triggered for graphing sake
#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000) // Define 1 day limit for time synchronization
unsigned long lastSync = millis();
char data[800] = ""; // Initialize the data buffer
TCPClient client; // Initialize the TCP client library
String server = "api.thingspeak.com"; // ThingSpeak Server
String WriteAPIKey = "CB15VBG2IIREP78N"; // Replace YOUR-CHANNEL-WRITEAPIKEY with your channel write API key
String ChannelID = "366003"; // Replace YOUR-CHANNEL-ID with your channel ID
/* Collect data once every 15 seconds and post data to ThingSpeak channel once every 2 minutes */
unsigned long lastConnectionTime = 0; // Track the last connection time
unsigned long lastUpdateTime = 0; // Track the last update time
const unsigned long postingInterval = 120L * 1000L; // Post data every 2 minutes
const unsigned long updateInterval = 15L * 1000L; // Update once every 15 seconds
size_t state = 0; // Keep note of first time the updateData() is called

void setup() {
// Here we are going to subscribe to your buddy's event using Particle.subscribe
  Particle.subscribe("beamStatus", myHandler);
  pinMode(Buzzer,OUTPUT);
  pinMode(motlite,OUTPUT);
  pinMode(lite,OUTPUT);
  pinMode(rumble,OUTPUT);
}

void myHandler(const char *event, const char *data)
{
    digitalWrite(lite,HIGH);
  /* Particle.subscribe handlers are void functions, which means they don't return anything.
  They take two variables-- the name of your event, and any data that goes along with your event.
  In this case, the event will be "buddy_unique_event_name" and the data will be "intact" or "broken"

  Since the input here is a char, we can't do
     data=="intact"
    or
     data=="broken"

  chars just don't play that way. Instead we're going to strcmp(), which compares two chars.
  If they are the same, strcmp will return 0.
  */

  if (strcmp(data,"clear")==0) {
    // if your buddy's beam is intact, then turn your board LED off
    delay(5000); // keep the buzzer going for 5 seconds to make sure it wakes you up!
    digitalWrite(Buzzer,LOW);
    digitalWrite(motlite,LOW);
    digitalWrite(rumble,LOW);
  }
  else if (strcmp(data,"motion")==0) {
    // if your buddy's beam is broken, turn your board LED on
    digitalWrite(Buzzer,HIGH);
    digitalWrite(motlite,HIGH);
    digitalWrite(rumble,HIGH);
    Count ++;
    String net = String(Count);
    Particle.publish("Triggers",net,60,PRIVATE);
  }
  else {
    // if the data is something else, don't do anything.
    // Really the data shouldn't be anything but those two listed above.
  }
      // If update time has reached 15 seconds, then update the data buffer
    if (millis() - lastUpdateTime >= updateInterval) {
      updateData();
  }
    // If last time synchronization is more than one day
    if (millis() - lastSync > ONE_DAY_MILLIS) {
    // Request time synchronization from the Particle Cloud
    Particle.syncTime();
    lastSync = millis();
  }
}

// Update the data buffer
void updateData(){
    /* CSV format to bulk update
   *  This function uses the absolute timestamp as it uses the "time_format=absolute" parameter. If your device does not have a real-time clock, 
   *  you can also provide the relative timestamp in seconds using the "time_format=relative" parameter.
   */
    if(state==0){
        strcpy(data,"write_api_key="+WriteAPIKey+"&time_format=absolute&updates=");
    }
    strcat(data,String(Time.local())); // Absolute time stamp
    strcat(data,"%2C"); // URL encoding for ","
    strcat(data,String(Count)); // Mock data to post to field1
    strcat(data,"%2C%7C"); // URL encoding for ",|". End with | at the end of a message
    state = 1; 
    // If posting interval time has reached 2 minutes, then update the ThingSpeak channel with your data
    if (millis() - lastConnectionTime >= postingInterval) {
        state = 0;
        size_t len = strlen(data);
        data[len-3] = '\0'; // Remove the | from the last message
        httpRequest(data); // Call httpRequest to send the data to ThingSpeak
        data[0] = '\0'; // Reinitialise the data buffer
    }
    lastUpdateTime = millis(); // Update the last update time
}

// Update the ThingSpeakchannel with data
void httpRequest(char* csvBuffer) {
     /* CSV format to bulk update
      * This function posts the data to ThingSpeak server
   */
    // Compute the data buffer length
    String data_length = String(strlen(csvBuffer)+1);
    // Close any connection before sending a new request
    client.stop();
    // POST data to ThingSpeak
    if (client.connect(server, 80)) {
        client.println("POST /channels/"+ChannelID+"/bulk_update HTTP/1.1");
        client.println("Host: "+server);
        client.println("User-Agent: mw.doc.bulk-update (Particle Photon)");
        client.println("Connection: close");
        client.println("Content-Type: application/x-www-form-urlencoded");
        client.println("Content-Length: "+data_length);
        client.println();
        client.println(csvBuffer);
    }
    else {
        Particle.publish("Failure","Failed to update ThingSpeak channel");
    }
    delay(1000); // Wait to receive the response
    client.parseFloat();
    String resp = String(client.parseInt());
    Particle.publish("Response code",resp); // Print the response code. 202 indicates that the server has accepted the response
    lastConnectionTime = millis(); // Update the last conenction time
}

Credits

Michael Finlay

Michael Finlay

1 project • 1 follower
John L.

John L.

1 project • 1 follower

Comments