Mark Lewis
Published © CC BY-NC-ND

Automatic Door Opener with Presence Detection

A simple add-on to a regular door the provides automatic operation based on voice command, smartphone command or presence detection.

AdvancedFull instructions provided12 hours1,096

Things used in this project

Hardware components

Photon
Particle Photon
×1
Argon
Particle Argon
×1
linear actuator
×1
relay module - 2 channel
×1
Relay Module - 1 channel
×1
Drive Motor and wheel
×1
Command strips
×6
Rechargeable 6000 mAh 12VDC battery (optional)
×1
Bike cable and sleeve
×1
12V to 3.3V convertor
×1
Mounting pins .25 x 3"
×2
Panel Mount 12V power connector
×1
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
×1
ac adaptor - usb
×1
spring 0.02Dia .25 x 2.5
×1
Switch Replacement Magnet, Omron Magnetic Proximity Sensor
Switch Replacement Magnet, Omron Magnetic Proximity Sensor
×1

Software apps and online services

Blynk
Blynk
Amazon Alexa service
IFTTT Amazon Alexa service

Hand tools and fabrication machines

RAISE N2 3D Printer

Story

Read more

Custom parts and enclosures

Cover

Door Bracket

Base

Motor Mount

Slider

Motor Cover

End Cap

End Cap 1

Schematics

Schematic

Code

Door Opener (Proton)

C/C++
// This #include statement was automatically added by the Particle IDE.
#include <blynk.h>
SYSTEM_THREAD(ENABLED);
/*
 * Project AutoDoor
 * Description:
 * Author:Mark Lewis
 * Date: 10/1/2019
 */

char auth[] = "your_auth_token_here";

int rlBar = D0;
int ocWheel = D1;
int motorPower = D2;
int closeSensor = D4;
int DOWNTIME = 17000;
int OPENTIME = 3000;
int CLOSETIME = 4500;
int OFFSETTIME = 1000;
int lastData;
int oStatus;
int doorStatus = 0;
int autoDoor = 0;
int autoClose = 0;


BLYNK_WRITE(V0) {
  int blynkOpendoor = param[0].asInt();
    if (blynkOpendoor ==1){
        oDoor();
    }
}
BLYNK_WRITE(V1) {
  int blynkClosedoor = param[0].asInt();  
    if (blynkClosedoor == 1){
        cDoor();
    }
}
BLYNK_WRITE(V2) {
  int blynkShutdoor = param[0].asInt();
    if (blynkShutdoor ==1){
        sDoor();
    }
}
BLYNK_WRITE(V3) {
  int blynkDowntime = param[0].asInt();
  DOWNTIME = (blynkDowntime *1000);
  EEPROM.put(30, DOWNTIME);
}
BLYNK_WRITE(V4) {
  int blynkOpentime = param[0].asInt();
  OPENTIME = (blynkOpentime * 1000);
  EEPROM.put(40, OPENTIME);
}
BLYNK_WRITE(V5) {
  int blynkClosetime = param[0].asInt();
  CLOSETIME = (blynkClosetime*1000);
  EEPROM.put(50, CLOSETIME);
}

BLYNK_WRITE(V6) {
  int blynkOffsettime = param[0].asInt();
  OFFSETTIME = (blynkOffsettime*1000);
  EEPROM.put(60, OFFSETTIME);
}
  BLYNK_WRITE(V7) {
  int blynkautoClose = param[0].asInt();
  autoClose = blynkautoClose;
  EEPROM.put(70, autoClose);
}
void setup() {
 
  pinMode(rlBar, OUTPUT);
  pinMode(ocWheel, OUTPUT);
  pinMode(motorPower, OUTPUT);
  pinMode(closeSensor,INPUT_PULLUP);

  Particle.function("openDoor", openDoor);
  Particle.function("closeDoor", closeDoor);
  Particle.function("shutDoor", shutDoor);
  Particle.function("lockDoor", lockDoor);
  Particle.function("unlockDoor", unlockDoor);
  Particle.subscribe("let_the_dog_out", myHandler);
  
  EEPROM.get(30, DOWNTIME);
  EEPROM.get(40, OPENTIME);
  EEPROM.get(50, CLOSETIME);
  EEPROM.get(60, OFFSETTIME);
 
  Blynk.begin(auth);
}

void loop() {

  Blynk.run();
  oStatus = digitalRead(closeSensor);
  if (autoClose ==1 && oStatus == 0) {
      sDoor();
      delay(CLOSETIME);
  }
}

void oDoor()  {
  Particle.publish("is_the_door_open","yes", MY_DEVICES);
  digitalWrite( rlBar, HIGH);
  delay (DOWNTIME);
  digitalWrite( ocWheel, HIGH);
  digitalWrite( motorPower, HIGH);
  delay (OPENTIME);
  digitalWrite( motorPower, LOW);
  doorStatus = 1;
  
}

void cDoor()  {
  Particle.publish("is_the_door_open","no", MY_DEVICES);
  digitalWrite( ocWheel, LOW);
  digitalWrite( motorPower, HIGH);
  delay (OFFSETTIME);
  digitalWrite( rlBar, LOW); 
  delay (CLOSETIME);
  digitalWrite( motorPower, LOW);
  doorStatus = 0;
}
// used when the door has been opened manually
void sDoor()  {
  Particle.publish("is_the_door_open","no", MY_DEVICES);
  digitalWrite( rlBar, HIGH);
  delay (DOWNTIME);  
  digitalWrite( ocWheel, LOW);
  digitalWrite( motorPower, HIGH);
  delay (OFFSETTIME);
  digitalWrite( rlBar, LOW); 
  delay (CLOSETIME);
  digitalWrite( motorPower, LOW);
  doorStatus =0;
}
void lDoor(){
    autoDoor = 0;
}
void uDoor(){
    autoDoor = 1;
}

void myHandler(const char *event, const char *data)
{
    if (strcmp(data,"open")==0)  {
       if (autoDoor == 1){
           oDoor();
           delay (OPENTIME);
        }
   }
    if  (strcmp(data,"close")==0) {  
       if (autoDoor == 1){
           cDoor();
           delay (CLOSETIME);
       }   
   }
    if  (strcmp(data,"shut")==0) {  
       sDoor();
       delay ((OPENTIME + CLOSETIME));
   }
}

//Invoked by alexa 
int openDoor(String Command) {
    oDoor();
    return 1;
}
//Invoked by alexa
int closeDoor(String Command) {
    cDoor();
    return 1;
}
int shutDoor(String Command) {
    sDoor();
    return 1;
}
int lockDoor(String Command) {
    lDoor();
    return 1;
}
int unlockDoor(String Command) {
    uDoor();
    return 1;
}

BLE Detector (Argon)

C/C++
/*
 * Project Detect
 * Description: Check the proximity of a Tile device. Send a message when the device arrives or leaves.
 * Author: Mark Lewis
 * Date: 11/2/2019
 */

#include "Particle.h"

// Enable thread (optional)
//SYSTEM_THREAD(ENABLED);

#define TILE_UUID      0xfeed
#define SCAN_TIMEOUT_10MS 800

int8_t lastRSSI;
int bestRSSI;
int THRESHOLD = -40;
int DELAYNUM = 6;
int DELAYTIME = 3000;
system_tick_t lastSeen = 0;
int doorStatus = 1;
int delayCount = 0;


// For logging
SerialLogHandler logHandler(115200, LOG_LEVEL_ERROR, {
    { "app", LOG_LEVEL_TRACE }, 
});


// Find advertising devices
void scanResultCallback(const BleScanResult *scanResult, void *context) {

    // Collect the uuids / Mac info
    BleUuid uuids[4];
    int uuidsAvail = scanResult->advertisingData.serviceUUID(uuids,sizeof(uuids)/sizeof(BleUuid));
    BleAddress addr = scanResult->address;
    
    // Loop over all available UUIDs
    for(int i = 0; i < uuidsAvail; i++){
        // Get only Tile UUID's and RSSI 
        if( uuids[i].shorted() == TILE_UUID ) {
            Log.trace("UUID: %x", uuids[i].shorted());
            Log.trace("MAC: %02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
            Log.trace("RSSI: %dBm", scanResult->rssi);
            
            // you could descriminte here by specific tile UUID
           
            lastSeen = millis();
            lastRSSI = scanResult->rssi;
            
            //keep the best RSSI Value for the Tiles 
            if (lastRSSI > bestRSSI){
                bestRSSI = lastRSSI;
            }
            
        }
    }
}    

void doorOpen(){    
        //open door if needed
    Serial.printlnf("Checking if door needs to be opened - Door Status= %i", doorStatus);    
    if (doorStatus == 0){
           Serial.println("Sending Open Door Command");
           Particle.publish("let_the_dog_out","open");
    }
}

void doorClose(){
    // close door if needed
    Serial.printlnf("Checking if door needs to be closed - Door Status= %i", doorStatus);    
    if (doorStatus == 1){
         Serial.println("Sending Open Door Command");
         Particle.publish("let_the_dog_out","close");
    }

}


// Track the open /close status so the system does not continually try to open a door already open
void myHandler(const char *event, const char *data){

    Log.trace(event);
    Log.trace(data);
   
    if (strcmp(data,"yes")==0){
        digitalWrite(D6, HIGH);
        digitalWrite(D5, LOW);
        doorStatus = 1;
        Log.trace("the door is open");
    }
     if (strcmp(data,"no")==0){
        digitalWrite(D5, HIGH);
        digitalWrite(D6, LOW); 
        doorStatus = 0;
        Log.trace("the door is closed");  
     }
     
}

void setup() {

    Particle.subscribe("is_the_door_open", myHandler);
    Serial.begin(9600);
    // Set LED pins
    pinMode(D7,OUTPUT);
    pinMode(D6,OUTPUT);
    pinMode(D5,OUTPUT);

    // Set timeout for BLE to 500ms
    BLE.setScanTimeout(SCAN_TIMEOUT_10MS);

}

void loop() {

 
    bestRSSI = -100; // Reset RSSI to a nominal value
    Log.trace("scan start.");
    BLE.scan(scanResultCallback, NULL);
    Serial.printlnf("Best RSSI = %i", bestRSSI);
    Serial.println();
    if (bestRSSI >= THRESHOLD){
        doorOpen();
        delayCount=0;
    }
    if (bestRSSI<= THRESHOLD){
        delayCount++;
        if (delayCount > DELAYNUM){ // delays "not found" for "x" number of cycles before closing door
            doorClose();
        }
    }
    Particle.process(); // good houskeeping only
    delay(DELAYTIME);
  

}

Credits

Mark Lewis

Mark Lewis

3 projects • 2 followers

Comments