Suicide Prevention Gun Safe Locking System

An IoT device that helps prevent gun suicides through safe monitoring, only allowing access to a safe through a request/approval process.

AdvancedShowcase (no instructions)Over 1 day16,100

Things used in this project

Hardware components

Electro Magnetic Lock
×1
Arduino 101
Arduino 101
×1
Switchable Permanent Magnet
×2
Arduino MKR1000
Arduino MKR1000
×1
Arduino MKR Relay Proto Shield
Arduino MKR Relay Proto Shield
×1
Jumper wires (generic)
Jumper wires (generic)
×1
12 Volt power supply
×1
12 Volt to 5 Volt Converter
×1
Aluminum Project Box
×1
Standard LCD - 16x2 White on Blue
Adafruit Standard LCD - 16x2 White on Blue
×1

Software apps and online services

Microsoft Azure
Microsoft Azure
ASP.net Core
SendGrid

Hand tools and fabrication machines

Drill Press
Hand Saw
Screw Driver
Wire Stripper
Wire Crimper

Story

Read more

Schematics

Smart Lock Flow Diagram

This flow diagram helps to visualize all the components of the project and shows how they interact with each other.

Wiring Diagram

Code

Arduino 101 Code

Arduino
This code allows the Arduino 101 to use its accelerometers to measure tampering and this code also controls an LCD screen which displays the different locking states of the device.
/*
 Demonstration sketch for Adafruit i2c/SPI LCD backpack
 using 74HC595 SPI expander
 ( http://www.ladyada.net/products/i2cspilcdbackpack/index.html )

 This sketch prints "Hello World!" to the LCD
 and shows the time.
 
  The circuit:
 * 5V to Arduino 5V pin
 * GND to Arduino GND pin
 * CLK to Digital 2
 * DAT to Digital 3
 * LAT to Digital 4
*/


// include the library code:
#include "Wire.h"
#include "Adafruit_LiquidCrystal.h"
#include "CurieIMU.h"

int RxPin = 5;
int RxValue = 0;
int TxPin = 6;
int Lockout = 0;

// Connect via SPI. Data pin is #3, Clock is #2 and Latch is #4
Adafruit_LiquidCrystal lcd(3, 2, 4);

void setup() {
  // set up the LCD's number of rows and columns: 
  lcd.begin(16, 2);
  pinMode(RxPin, INPUT);
  Serial.begin(9600);
  CurieIMU.begin();

  // Set the accelerometer range to 2G
  CurieIMU.setAccelerometerRange(2);
}

void loop() {
  float ax, ay, az;   //scaled accelerometer values

  // read accelerometer measurements from device, scaled to the configured range
  CurieIMU.readAccelerometerScaled(ax, ay, az);
  /*lcd.setCursor(0, 1);
  lcd.print ("x: ");
  lcd.print (ax,4, " ","y: ",  ay, " ","z: ",  az);*/
  
  if (ax > 1.25 || ay > 1.25 || az > 1.25 || ax < -1.25 || ay < -1.25 || az < -1.25 ){
    digitalWrite (TxPin, HIGH);
    lcd.setCursor(11, 0);
    lcd.print("Alarm");
    delay(5000);
    digitalWrite (TxPin, LOW);
    lcd.setCursor(11, 1);
    lcd.print("Reset");
    delay(2000);
    lcd.setCursor(11, 0);
    lcd.print("     ");
    lcd.setCursor(11, 1);
    lcd.print("     ");
  }
  
  RxValue = digitalRead(RxPin);
  Serial.print(RxValue);
  if (RxValue == 0)
  {
  lcd.setCursor(0, 0);
  lcd.print("Locked  ");

  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  }
  else{
  lcd.setCursor(0, 0);
  lcd.print("Unlocked");
  digitalWrite(TxPin, LOW);
  //lcd.setCursor(0, 1);
  //lcd.print("        ");
  }
  
}

Arduino MKR1000 Code

Arduino
This code allows the MKR1000 to connect to the internet and send a request to the server to get the lock status. This code also receives alarm information from the Arduino 101 and then sends the alarm info to the server so the server can send email alerts to the users. This code communicates the lock status to the Arduino 101 and this code turns the electro magnet off and on using the Arduino Relay shield.
/*
  Web client

 This sketch connects to a website (http://www.google.com)
 using a WiFi shield.

 This example is written for a network using WPA encryption. For
 WEP or WPA, change the WiFi.begin() call accordingly.

 This example is written for a network using WPA encryption. For
 WEP or WPA, change the WiFi.begin() call accordingly.

 Circuit:
 * WiFi shield attached

 created 13 July 2010
 by dlf (Metodo2 srl)
 modified 31 May 2012
 by Tom Igoe
 */


#include <SPI.h>
#include <WiFi101.h>

int EmagPin = 1;
int LcdPin = 2;
int AlrmPin = 6;
int AlrmValue = 0;

char ssid[] = "STANTON-2.4"; //  your network SSID (name)
char pass[] = "STAnton7860";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)
const unsigned long HTTP_TIMEOUT = 10000;  // max respone time from server

int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)
char server[] = "www.cowincrafted.com";    // name address for Google (using DNS)

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiClient client;

char a = 'a';
char b = 'b';
char c = 'c';
char z = 'z';

unsigned long lastConnectionTime = 0;            // last time you connected to the server, in milliseconds
const unsigned long postingInterval = 5000; // delay between updates, in milliseconds


void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to wifi");
  printWiFiStatus();

  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  
}

void loop() {
  AlrmValue = digitalRead(AlrmPin);
  if (AlrmValue == 1)
  {
    Serial.println("Alarm");
    if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET /api/locksapi/1/1 HTTP/1.1");
    client.println("Host: www.cowincrafted.com");
    client.println("Connection: close");
    client.println();
    Serial.println("alarm sent");
    }

    delay(5000);

    Serial.println("Alarm Off");

    if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET /api/locksapi/1/0 HTTP/1.1");
    client.println("Host: www.cowincrafted.com");
    client.println("Connection: close");
    client.println();
    Serial.println("alarm off sent");
    }
  }
  
  //Serial.println("in void loop");
  
  // if there are incoming bytes available
  // from the server, read them and print them:
  while (client.available()) {

     z = a;
     a = b;
     b = c;
     c = client.read();
    
    if(c == ']' && b == '0' )
    {
      Serial.println();
      Serial.println("Unlocked");
      digitalWrite (EmagPin, HIGH);
      digitalWrite (LcdPin, HIGH);
    }
    if(c == ']' && b == '1' )
    {
      Serial.println();
      Serial.println("Locked");
      digitalWrite (EmagPin, LOW);
      digitalWrite (LcdPin, LOW);
    }
    Serial.write(c);
    
  }

  if (millis() - lastConnectionTime > postingInterval) {
    httpRequest();
  }
  //delay(30000);

  // if the server's disconnected, stop the client:
  /*if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting from server.");
    client.stop();

    // do nothing forevermore:
    while (true);
  }*/
}

  // this method makes a HTTP connection to the server:
void httpRequest() {
  // close any connection before send a new request.
  // This will free the socket on the WiFi shield
  client.stop();

  // if there's a successful connection:
  Serial.println("httprequest");

  if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET /api/locksapi/1 HTTP/1.1");
    client.println("Host: www.cowincrafted.com");
    client.println("Connection: close");
    client.println();
    //lastConnectionTime = millis();
  }
  lastConnectionTime = millis();
}

void printWiFiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

// Skip HTTP headers so that we are at the beginning of the response's body
bool skipResponseHeaders() {
  // HTTP headers end with an empty line
  char endOfHeaders[] = "\r\n\r\n";

  client.setTimeout(HTTP_TIMEOUT);
  bool ok = client.find(endOfHeaders);

  if (!ok) {
    Serial.println("No response or invalid response!");
  }

  return ok;
}

Web App Code

This is a ASP.Net Core project created in Visual Studio 2017. It needs to be deployed on a service like Azure and must have a connected SQL Database.

Credits

Jason Cowin

Jason Cowin

3 projects • 11 followers
Mechatronics Degree 2014 - Happily Married in 2015 - Maintain Robots for Work
Amanda Cowin

Amanda Cowin

0 projects • 3 followers
Bachelors degree in applied management. I am happily married since 2015 -I am the project coordinator for the projects my husband does here.
Jordan Stanton

Jordan Stanton

1 project • 4 followers
Brittany K Stanton

Brittany K Stanton

0 projects • 3 followers
David Peterson

David Peterson

0 projects • 1 follower
Alex Cowin

Alex Cowin

0 projects • 1 follower
Zippady doo da

Comments