JaumeBolito2
Published © CC BY-NC-SA

Touchless Door Opener

Touchless door handle mechanism that can be used in every door just replacing the standard handle. Very useful for people with disabilities.

AdvancedWork in progressOver 8 days9,497

Things used in this project

Hardware components

door handle
3d printed
×2
Stepper Motor
Digilent Stepper Motor
One for each side
×2
Proximity Sensor
Proximity Sensor
One for each side
×2
gears
3d printed
×2
door plate
3d printed
×2
Arduino Nano R3
Arduino Nano R3
or Arduino MKR wifi for smart functions
×1
LED (generic)
LED (generic)
Shows the status of the door, one for each side of the door
×2
batterie 18650
×4
wireless charger
×1
wheel
can be 3d printed
×1
housing cyber door truck
3d printed
×1
DC motor (generic)
×1
Dual H-Bridge motor drivers L298
SparkFun Dual H-Bridge motor drivers L298
×1
BOOSTXL-ULN2003 ULN2003A Dual Stepper Motor BoosterPack
Texas Instruments BOOSTXL-ULN2003 ULN2003A Dual Stepper Motor BoosterPack
×2

Software apps and online services

Fusion
Autodesk Fusion
Arduino IDE
Arduino IDE

Hand tools and fabrication machines

prusa mk3

Story

Read more

Schematics

Option with two steppers works!

an important target is achieved because using the two 28BYJ-48 steppers, this automatic door handle can be very affordable

new schema with Arduino Nano

alternative with switch

in this schema shows the alternative using a switch to detect the closed door.

Video with last stand

Code

New Code

Arduino
Happy to welcome my nephew Óscar to this project. He studies Mathematics at the university of Madrid, and will support me on this and hopefully also on future projects.
#define DOOR_CLOSED 0
#define DOOR_OPENING 1
#define DOOR_OPENING_OUTSIDE 4
#define DOOR_OPENED 2
#define DOOR_CLOSING 3

#define MOTOR_CLOSING -1
#define MOTOR_STOPPED 0
#define MOTOR_OPENING 1

String stateNames[] = {"Closed", "Opening", "Opened", "Closing"};

//Stepper pins
const int STEP1 = 4;
const int STEP2 = 5;
const int STEP3 = 6;
const int STEP4 = 7;

//Stepper parameters
int motorSpeed = 5000;
int stepCounter = 0;

const int numSteps = 4;
//We use one phase rotation for the stepper
const int stepsLookup[4] = {B1000, B0100, B0010, B0001};

//Time that the stepper takes to open the door(in ms)
const int doorOpeningTime = 3000;
//Time that the door waits before closing
const int doorWaitTime = 2000;

//Number of steps of motor1
const int steps = 700;

//Maximum hand distance to open door
const int handDistance = 5;
//Distance to the wall at which the door motor stops
const int wallDistance = 20;
//Distance at which the closing door stops to avoid hitting user
const int blockDistance = 20;

//Door's inside ultrasonic sensor
int TRIG1 = 3;
int ECO1 = 2 ;
float distance1;

//Door's outside ultrasonic sensor
int TRIG2 = 11;
int ECO2 = 12;
float distance2;

//Door opener motor
int IN1 = 8;      // IN1 de L298N to pin digital 8
int IN2 = 9;      // IN2 de L298N to pin digital 9
int ENA = 10;      // ENA de L298N to pin digital 10

int refreshRate = 100;

//Parameters for sampling the outside sensor
const int subSampleSize = 5;
const int sampleSize = 3;
const float varThreshold = 1.5;

int subSampleIndex = 0;
int sampleIndex = 0;

int sample[sampleSize];

float sampleVariance = 0;
float subSampleMax = 0;

//int that represents the current state of the door
int doorState = DOOR_CLOSED;

//Detect when the user retires his hand from the sensor
bool handInSensor;

void setup() {
  //We initialize all pins
  pinMode(TRIG1, OUTPUT);
  pinMode(ECO1, INPUT);

  pinMode(STEP1, OUTPUT);
  pinMode(STEP2, OUTPUT);
  pinMode(STEP3, OUTPUT);
  pinMode(STEP4, OUTPUT);
  
  pinMode(IN1, OUTPUT);   // pin 8 output
  pinMode(IN2, OUTPUT);   // pin 9 output 
  pinMode(ENA, OUTPUT);   // pin 10 output
  Serial.begin(9600);
}
void demagnetize(){
  //Stop the stepper from drawing current
  digitalWrite(STEP1, LOW);
  digitalWrite(STEP2, LOW);
  digitalWrite(STEP3, LOW);
  digitalWrite(STEP4, LOW);
}
//Stepper
void opening(){
  stepCounter++;
  if(stepCounter >= numSteps) stepCounter = 0;
  setOutput(stepCounter);
}
void closing(){
  stepCounter--;
  if(stepCounter < 0) stepCounter = numSteps - 1;
  setOutput(stepCounter);
}

void setOutput(int step){
  digitalWrite(STEP1, bitRead(stepsLookup[step], 0));
  digitalWrite(STEP2, bitRead(stepsLookup[step], 1));
  digitalWrite(STEP3, bitRead(stepsLookup[step], 2));
  digitalWrite(STEP4, bitRead(stepsLookup[step], 3));
}

int getDistance(int TRIG, int ECO){
  digitalWrite(TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG, HIGH);    // Ultrasonic sensor routine
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);
  int duration = pulseIn(ECO, HIGH);
  return duration / 58.2;
}

//Control the motor
void doorMotor(int rotDirection){
  if(rotDirection == MOTOR_CLOSING){
    Serial.println ("Door motor closing...");  
    digitalWrite(ENA, HIGH);
    digitalWrite(IN1, HIGH);  // IN1 a 1
    digitalWrite(IN2, LOW); // IN2 a 0
  }else{
    if(rotDirection == MOTOR_STOPPED){
      Serial.println ("Door motor stopping...");  
      digitalWrite(ENA, LOW); // ENA en 0 DC Motor off
      digitalWrite(IN1, LOW); // IN1 a 0
      digitalWrite(IN2, LOW); 
    }else{
      if(rotDirection == MOTOR_OPENING){
        Serial.println ("Door motor opening...");  
        digitalWrite(ENA, HIGH);
        digitalWrite(IN1, LOW); // IN1 a 0
        digitalWrite(IN2, HIGH);  // IN2 a 1
      }
    }
  } 
}

void loop() {
  //Read the distance of both sensors
  distance1 = getDistance(TRIG1, ECO1);
  distance2 = getDistance(TRIG2, ECO2);

  //We compute the max value of the subSample
  if(distance2 > subSampleMax){
    subSampleMax = distance2;
  }
  subSampleIndex++;

  if(subSampleIndex % subSampleSize == 0){
    sample[sampleIndex] = subSampleMax;
    sampleIndex++;

    Serial.println(subSampleMax);

    subSampleMax = 0;
    subSampleIndex = 0;
  }

  if(sampleIndex % sampleSize == 0 && subSampleIndex % subSampleSize == 0){
    sampleIndex = 0;

    int mean = 0;
    for(int i = 0; i < sampleSize; i++){
      mean += sample[i];
    }
    mean /= sampleSize;

    sampleVariance = 0;
    for(int i = 0; i < sampleSize; i++){
      sampleVariance += pow(sample[i] - mean, 2);
    }
    sampleVariance /= sampleSize;

    Serial.print("variance: ");
    Serial.println(sampleVariance);
  }
  
  //Print the door state
  Serial.print ("Door state: ");
  Serial.println (stateNames[doorState]);

  //Refresh rate of sensors
  delay(refreshRate);

  //Manage changes of door state
  switch(doorState){
    case DOOR_CLOSED:
      //The door is closed and awaits input
      if(distance1 <= handDistance && distance1 > 0){
        //We detected a hand in the inside sensor, so the door starts to open and we register that it was opened from the inside
        for(int i = 0; i < steps; i++){
          opening();
          delayMicroseconds(motorSpeed);
        }
        demagnetize();

        //And start the door's motor
        doorState = DOOR_OPENING;
        doorMotor(MOTOR_OPENING);
        //The user's hand starts in the sensor
        handInSensor = true;

        Serial.println("Pomo abierto");
      }else{
        if(distance2 <= handDistance && distance2 > 0){
          //We detected a hand in the inside sensor, so the door starts to open and we register that it was opened from the inside
          for(int i = 0; i < steps; i++){
            opening();
            delayMicroseconds(motorSpeed);
          }
          demagnetize();
  
          //And start the door's motor
          doorState = DOOR_OPENING_OUTSIDE;
          doorMotor(MOTOR_OPENING);
  
          Serial.println("Pomo abierto");
        }
      }
      break;
    case DOOR_OPENING:
      if(distance1 > wallDistance){
        //We detect when the user takes his hand away(so the inside sensor doesnt mix up the hand with the wall)
        handInSensor = false;
      }
      if(distance1 <= wallDistance && distance1 > 0 && !handInSensor){
        Serial.println("Wall");
        
        //If the inside sensor detects that the door has reached the wall it stops the motor
        doorMotor(MOTOR_STOPPED);
        doorState = DOOR_OPENED;
      }
      break;
    case DOOR_OPENING_OUTSIDE:
      if(distance1 <= wallDistance && distance1 > 0){
        Serial.println("Wall");
        
        //If the inside sensor detects that the door has reached the wall it stops the motor
        doorMotor(MOTOR_STOPPED);
        doorState = DOOR_OPENED;
      }
      break;
    case DOOR_OPENED:
      //For now we just wait some time with the door closed, later on we can use the outside sensor to detect when the user crosses the door
      delay(doorWaitTime);

      doorMotor(MOTOR_CLOSING);
      doorState = DOOR_CLOSING;
      break;
    case DOOR_CLOSING:   
      if(sampleVariance < varThreshold){
        doorState = DOOR_CLOSED;
        doorMotor(MOTOR_STOPPED);

        for(int i = 0; i < steps; i++){
          closing();
          delayMicroseconds(motorSpeed);
        }
        demagnetize();
      }
      break;
    default:  
      break;
    }
 }

old code

Arduino
#include <Stepper.h>

Stepper motor1(2048, 4, 6, 5, 7);

int TRIG = 10;
int ECO = 9 ;
int DURATION;
int DISTANCE;
int IN1 = 2;      // IN1 de L298N to pin digital 2
int IN2 = 3;      // IN2 de L298N to pin digital 3
int ENA = 11;      // ENA de L298N to pin digital 11

void setup() {
 
  pinMode(TRIG, OUTPUT);
  pinMode(ECO, INPUT);
  pinMode(IN1, OUTPUT);   // pin 2 output
  pinMode(IN2, OUTPUT);   // pin 3 output 
  pinMode(ENA, OUTPUT);   // pin 11 output
  Serial.begin(9600);
  motor1.setSpeed(3);   // Stepper for door handle
  
}
  

void loop() {
  if (Serial.available()){     // system waits after you introduce a value of steps for the handle steppers
    
  digitalWrite(TRIG, HIGH);    // Ultrasonic sensor routine
  delay(1);
  digitalWrite(TRIG, LOW);
  DURATION = pulseIn(ECO, HIGH);
  DISTANCE = DURATION / 58.2;
  Serial.println (DISTANCE);      // end of Ultrasonic Sensor routine (shows the detected distance)
  delay(200);
  
  if (DISTANCE <= 100 && DISTANCE >=0){   //IF Distance ist between 0 and 100cm then is true and handle starts      
  int steps = Serial.parseInt();
  Serial.println(steps);            // handle stepper moves to the number of steps introduced
  motor1.step(steps);
  
  delay(5000);               //wait for 5 seconds
  
  digitalWrite(ENA, HIGH);  // DC door motor  (turns cw)
  digitalWrite(IN1, LOW); // IN1 a 0
  digitalWrite(IN2, HIGH);  // IN2 a 1
  delay(3000);      // wait for 3 seg.

  digitalWrite(ENA, LOW); // ENA en 0 DC Motor off
  delay(2000);      // wait for 2 seg.

  digitalWrite(ENA, HIGH);  // DC door motor  (turns ccw)
  digitalWrite(IN1, HIGH);  // IN1 a 1
  digitalWrite(IN2, LOW); // IN2 a 0
  delay(3000);      // wait for 3 seg

  digitalWrite(ENA, LOW); //  DC Motor off
  delay(2000);      // wait for 2 seg.
  }
 }
 }

Credits

Jaume

Jaume

2 projects • 8 followers
I am an engineer who likes design, art and 3d printing, I am the founder of 3dthinks.
Bolito2

Bolito2

0 projects • 2 followers

Comments