The forward and reverse problem of the two automatic doors with DC motors and limit switch sensors

I have an Arduino project to create two automatic doors. I use DC motors and limit switch sensors to control the doors' forward and reverse rotation (opening and closing). The open and close positions both have limit switches and initially the two doors are closed, with each one triggering its respective limit switch.

I want the effect to be that when someone approaches, the first door opens and waits for 10 seconds before closing. If someone approaches again during this time, the door will open again. Once the first door is closed, the second door will open. While the second door operates, any approach to the first door will have no effect. When the second door is fully open and reaches its limit switch, an ultrasonic sensor will measure the distance and store the value. Then the second door will close. After the second door is fully closed, an LED ring light will reflect the measured distance value in the number of lit LEDs. Then it will wait for someone to approach the first door again.

However, after writing the code and testing, some problems have arisen:

  1. The first door's limit switch A0 is in the triggered state, but when someone approaches, the door does not open. The door only opens if someone approaches and activates the limit switch again.
  2. When the door reaches limit switch A1, it waits 2 seconds before beginning to close. But as soon as it leaves limit switch A1, the door opens again. The door needs to maintain the triggered state of limit switch A1 to close. When the door is closing, it also does not react if someone approaches.
  3. When the first door returns to limit switch A0, the second door opens. But when it reaches the limit switch B1/C, the door does not stop. The door only stops if limit switch A0 is not triggered, and then limit switch B1/C can be triggered to stop the second door.
  4. When the second door returns to limit switch B0, the door does not stop.

The Arduino code is provided below, and I hope you guys can help me please.

#include <Adafruit_NeoPixel.h>

int switchAPin = 2;   // door open
int switchBPin = 3;   // door close
int motorPin1 = 4;
int motorPin2 = 5;
int trigPin = 7;      // HC-SR04 trigPin
int echoPin = 8;      // HC-SR04 echoPin
int miniFanPin = 9;
int motor12vPin1 = 11;
int motor12vPin2 = 12;
int GarbagetrigPin = A2; // The seconnd HC-SR04 trigPin
int GarbageechoPin = A3; // The seconnd HC-SR04 echoPin
int limitSwitchB0 = A4; // The second door open
int limitSwitchB1 = A5; // The second door open
int limitSwitchC = A5; // The second door open
int ledPIN = 10;
int ledCount = 16; // amount of LED

// HC-SR04 max/min distance
const int minDistance = 0;
const int maxDistance = 50; // in cm

Adafruit_NeoPixel ledRing = Adafruit_NeoPixel(ledCount, ledPIN, NEO_GRB + NEO_KHZ800);

int storedDistance = 0;
bool buttonPressed = false;

bool motorRunning = false;
bool motorDirection = true;
bool miniFanRunning = false;

bool motor12vRunning = false;
bool motor12vDirection = true;

void setup() {
  pinMode(switchAPin, INPUT_PULLUP);
  pinMode(switchBPin, INPUT_PULLUP);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(miniFanPin, OUTPUT);
  pinMode(motor12vPin1, OUTPUT);
  pinMode(motor12vPin2, OUTPUT);
  pinMode(limitSwitchB0, INPUT);
  pinMode(limitSwitchB1, INPUT_PULLUP);
  pinMode(limitSwitchC, INPUT_PULLUP);
  pinMode(limitSwitchA1, INPUT);
  pinMode(GarbagetrigPin, OUTPUT);
  pinMode(GarbageechoPin, INPUT);
  ledRing.begin();
  ledRing.show(); // set LED RING
  ledRing.setBrightness(15); // set lumenn 50 (0-255)
}

void loop() {
  int delayTime = 80; // each light delay time in ms
  int tailLength = 8;
  int maxBrightness = 255;

  if (digitalRead(switchAPin) == LOW) {
    if (motorRunning && !motorDirection && miniFanRunning) { // motor run opposite
      // Stop the motor and the minifan
      digitalWrite(miniFanPin, LOW);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      motorRunning = false;
      miniFanRunning = false;
      delay (2000);

      // 12vmotor forward
      digitalWrite(motor12vPin1, HIGH);
      digitalWrite(motor12vPin2, LOW);
      motor12vRunning = true;
      motor12vDirection = true;

      // the motor and the minifan still stopped when 12v is running
      digitalWrite(miniFanPin, LOW);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      motorRunning = false;
      miniFanRunning = false;
    
      while (digitalRead(switchAPin) == LOW) {
        delay(10);
      }
    } else if (!motorRunning){

    // detected people around
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    
    long duration = pulseIn(echoPin, HIGH);
    long distance = duration / 29 / 2;
    
    if (distance < 30) {
      // start the motor and the minifan
      digitalWrite(miniFanPin, HIGH);
      miniFanRunning = true;
      digitalWrite(motorPin1, HIGH);
      digitalWrite(motorPin2, LOW);
      motorRunning = true;
      motorDirection = true;
     }
    }
    while (digitalRead(switchAPin) == LOW) {
      delay(10);
    }
  } else if (digitalRead(switchBPin) == LOW) { // Stop the motor when arrive switch B
    if (motorRunning) {
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      motorRunning = false;

    // wait 2 second
    delay(2000);
    
    // motor run opposite
    digitalWrite(motorPin1, LOW);
    digitalWrite(motorPin2, HIGH);
    motorRunning = true;
    motorDirection = false;

    while (digitalRead(switchBPin) == LOW) {
      delay(10);
    }
   }
  } else if (motorRunning && !motorDirection) { // motor run opposite
    
    // detected people around
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    long duration = pulseIn(echoPin, HIGH);
    long distance = duration / 29 / 2;
    if (distance < 30) {
      // motor run forward
      digitalWrite(motorPin1, HIGH);
      digitalWrite(motorPin2, LOW);
      motorRunning = true;
    }}

  // Read limit switch state
  int limitSwitchB0Value = analogRead(limitSwitchB0);
  int limitSwitchB1Value = analogRead(limitSwitchB1);
  int limitSwitchCValue = analogRead(limitSwitchC);

  if (motor12vRunning && motor12vDirection) {
    digitalWrite(miniFanPin, LOW);
    digitalWrite(motorPin1, LOW);
    digitalWrite(motorPin2, LOW);
    motorRunning = false;
    miniFanRunning = false;

  // check limit switch B1 or C
   if (limitSwitchB1Value < 100 || limitSwitchCValue < 100) {
      buttonPressed = true;
    digitalWrite(motor12vPin1, LOW);
    digitalWrite(motor12vPin2, LOW);
    motor12vRunning = false;      
      digitalWrite(miniFanPin, LOW);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      motorRunning = false;
      miniFanRunning = false;   

  // Measure distance
  long duration, distance;
  digitalWrite(GarbagetrigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(GarbagetrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(GarbagetrigPin, LOW);
  duration = pulseIn(GarbageechoPin, HIGH);
  distance = (duration / 2) / 29.1; // in cm

  if (buttonPressed) {
  storedDistance = distance;
  }
    delay (2000);
    digitalWrite(motor12vPin1, LOW);
    digitalWrite(motor12vPin2, HIGH);
    motor12vRunning = true;
    motor12vDirection = false;  
      digitalWrite(miniFanPin, LOW);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      motorRunning = false;
      miniFanRunning = false;  
  }
} // check limit switch B0
  else if (limitSwitchB0Value < 100) {
    if (motor12vRunning && !motor12vDirection) {   
      digitalWrite(miniFanPin, LOW);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      motorRunning = false;
      miniFanRunning = false;

  // Lights the LED RING according to the stored distance value
  int lightedLeds = map(storedDistance, minDistance, maxDistance, 0, ledCount);
  for (int i = 0; i < ledCount; i++) {
    if (i < lightedLeds) {
      ledRing.setPixelColor(i, ledRing.Color(0, 255, 0));
    } 
  }
  ledRing.show();

  delay(100);
    motor12vRunning = false;
    }
  }
}

Why are you using analogRead to read a limit switch? What sort of switches are they? How are they wired that they give analog signals?

Why do some of the limit switches share the same pin?

int limitSwitchB1 = A5; // The second door open
int limitSwitchC = A5; // The second door open

The procedural blocking nature of this code is going to kill it. You should write this as a non-blocking state machine.

3 Likes

Plus 1 for a state machine.

Start by drawing a state diagram, which means every possible state the system can be in. For example, one state would be both doors closed. Another would be one closed other open. Then join the states with lines showing what has to happen to get from one state to another.

However, you are trying to do a complicated system in one go, you need to break it into smaller chunks and get a simple version working before moving to the full project.

4 Likes

Here

The door is open already. Do you mean the 10 second timer should start over again?

If you can tell us without then having to kill is what is this all about?

The distance to what?

+1 for state machine approach. I recommend trying to code something much simpler whilst you wrap your mind around it, like just opening, pausing then closing one door based on

which isn't clear at all how you detect that.

Here's a tutorial, you may want to read through a few - it's the same stuff, but multiple perspectives can help:

a7

1 Like

You have started multiple topics with the same subject. You should post one topic and use both Chinese and English.

您已使用同一主題啟動了多個主題。 您應該發佈一個主題並使用中文和英文。

@rayli_kwong ,

Your other topic on the same subject deleted.

Please do not duplicate your questions as doing so wastes the time and effort of the volunteers trying to help you as they are then answering the same thing in different places.

Please create one topic only for your question and choose the forum category carefully. If you have multiple questions about the same project then please ask your questions in the one topic as the answers to one question provide useful context for the others, and also you won’t have to keep explaining your project repeatedly.

Repeated duplicate posting could result in a temporary or permanent ban from the forum.

Could you take a few moments to Learn How To Use The Forum

It will help you get the best out of the forum in the future.

Thank you.

Typical application for a good flow chart so that ALL possibilities are covered.
Then write code to cover all the above.

As it stands, I for one can see quite a few possibilities not thought of.

I understood OP meant « if someone is detected during the time the door is moving to a close » otherwise indeed it’s weird but it seems reasonable that the door should stay open if someone stands there (extended timeout)

1 Like

You may find these resources useful

showing how to use state diagrams; and

with some simple examples of state machines

Yes, I know. I am just trying to delete the Chinese version. Sorry about that.

+1 for state machine

Also describe all parts physical and in software.
Variables with saved state states and timers are parts.
The timer part has complexity more than countdown.
The state of each door is more than limit switch state.
When all the parts are defined then interactions can be described in terms of those definitions.
I see implications arise that are not well defined.
The plan is not finished and some degree of X-Y problem results.

When all steps are defined as parts and interactions, a state machine may be written to implement those steps.

Yes, THX. I could almost say of course. The reference was to me not even ambiguous, but now I see it is, cough!, to me, ambiguous, and your interpretation seems correct.

That's a nice thing about computer programs. And here a reminder that when describing code in natural language, one must go lengths in order to avoid confusion, pesky questions and failed implementations.

Which is why soon enough natural language fails, and we bring out intermediate representations of systems and processes that become successively less imprecise.

I'm just damn curious - so far I'm unable to keep from wondering, and have considered some kind of airlock for cats or maybe a prison. :expressionless:

a7

indeed ambiguous. a good state machine drawing would help clarify!

The X-Y is about supposed to mixed with description of is.
To me, I wonder is missing parts are assumed known.
I've done that myself and had to clarify before I could correct.

I have lived where in season an anteroom kept heat in the house from being lost. Same goes for AC. The cost may be an issue when it happens often. IDK about automatic doors in a prison!

1 Like

Our airlocks on all doors leading to the great world of the outdoors are for the the four-footed members of the family.

a7

1 Like

I could see where little kids would also be a reason.

After much hard work, the following code is the effect I want, although many flaws remain. Thank you for your valuable opinions.

#include <Adafruit_NeoPixel.h>
#include <Arduino.h>
#include <FastLED.h>

int switchAPin = A2;   // door open
int switchBPin = A3;   // door close
int motorPin1 = 5;
int motorPin2 = 6;
int trigPin = 10;      // HC-SR04 trigPin
int echoPin = 11;      // HC-SR04 echoPin
int miniFanPin = 9;
int motor12vPin1 = 7;
int motor12vPin2 = 8;
int GarbagetrigPin = 12; // The seconnd HC-SR04 trigPin
int GarbageechoPin = 13; // The seconnd HC-SR04 echoPin
int limitSwitchB0 = A4; // The second door open
int limitSwitchB1 = A5; // The second door open
int limitSwitchC = A5; // The second door open
int ledPIN = 4;
int ledCount = 16; // amount of LED
int PIR_SENSOR = A0;
int LIGHT_SENSOR = A1;
int LED_PIN = 3;

// HC-SR04 max/min distance
const int minDistance = 0;
const int maxDistance = 50; // in cm

Adafruit_NeoPixel ledRing = Adafruit_NeoPixel(ledCount, ledPIN, NEO_GRB + NEO_KHZ800);

int storedDistance = 0;
bool buttonPressed = false;

bool motorRunning = false;
bool motorDirection = true;
bool miniFanRunning = false;

bool motor12vRunning = false;
bool motor12vDirection = true;

void setup() {
  pinMode(switchAPin, INPUT_PULLUP);
  pinMode(switchBPin, INPUT_PULLUP);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(miniFanPin, OUTPUT);
  pinMode(motor12vPin1, OUTPUT);
  pinMode(motor12vPin2, OUTPUT);
  pinMode(limitSwitchB0, INPUT);
  pinMode(limitSwitchB1, INPUT_PULLUP);
  pinMode(limitSwitchC, INPUT_PULLUP);
  pinMode(GarbagetrigPin, OUTPUT);
  pinMode(GarbageechoPin, INPUT);
  ledRing.begin();
  ledRing.show(); // set LED RING
  ledRing.setBrightness(15); // set lumenn 50 (0-255)
  pinMode(LED_PIN, OUTPUT);

}
void loop(){
  unsigned long previousMillis = 0;
  const long interval = 30000; // 1 minute in milliseconds

  int pirValue = analogRead(PIR_SENSOR);
  int lightValue = analogRead(LIGHT_SENSOR);
  Serial.print("PIR: ");
  Serial.print(pirValue);
  Serial.print(", Light: ");
  Serial.println(lightValue);

  if (pirValue > 0 && lightValue > 1010) {
    digitalWrite(LED_PIN, HIGH);
    previousMillis = millis(); 
  } else {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      digitalWrite(LED_PIN, LOW); 
    }
  }
      

{
    // Detected people around
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);   
    long duration = pulseIn(echoPin, HIGH);
    long distance = duration / 29 / 2;  
    
    // Output the distance to the serial monitor
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.println(" cm");
    // If people are detected within 10 cm and the motor is not running
    if ((distance < 10) && (!motorRunning)) {
        // Start the motor and the mini fan
        digitalWrite(miniFanPin, HIGH);
        miniFanRunning = true;
        digitalWrite(motorPin1, HIGH);
        digitalWrite(motorPin2, LOW);
        motorRunning = true;
        motorDirection = true;
        // Output a message to the serial monitor
        Serial.println("Motor and mini fan started.");
    } else {
        // Output a message to the serial monitor
        Serial.println("No one detected within 10 cm.");
    }
    // Add a delay to slow down the loop
    delay(100);
}
  if (digitalRead(switchBPin) == LOW) { // Stop the motor when arrive switch B
    if (motorRunning) {
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      motorRunning = false;

    // wait 2 second
    delay(2000);
    
    // motor run opposite
    digitalWrite(motorPin1, LOW);
    digitalWrite(motorPin2, HIGH);
    motorRunning = true;
    motorDirection = false;

    while (digitalRead(switchBPin) == LOW) {
      delay(10);
    }
   }
  } else if (motorRunning && !motorDirection) { // motor run opposite
    
    // detected people around
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    long duration = pulseIn(echoPin, HIGH);
    long distance = duration / 29 / 2;
    if (distance < 30) {
      // motor run forward
      digitalWrite(motorPin1, HIGH);
      digitalWrite(motorPin2, LOW);
      motorRunning = true;
    }
   }
   if (digitalRead(switchAPin) == LOW) {
    if (!motorDirection && miniFanRunning) { // motor run opposite
      // Stop the motor and the minifan
      digitalWrite(miniFanPin, LOW);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      motorRunning = false;
      motorDirection = true;
      miniFanRunning = false;
      delay (2000);

      // 12vmotor forward
      digitalWrite(motor12vPin1, HIGH);
      digitalWrite(motor12vPin2, LOW);
      motor12vRunning = true;
      motor12vDirection = true;

      // the motor and the minifan still stopped when 12v is running
      Serial.println("Motor and mini fan stopped, 12V motor running forward");
    } 

      Serial.println("Switch A is pressed");
    
  }

  // Read limit switch state
  int limitSwitchB0Value = analogRead(limitSwitchB0);
  int limitSwitchB1Value = analogRead(limitSwitchB1);
  int limitSwitchCValue = analogRead(limitSwitchC);

  if (motor12vRunning && motor12vDirection) {
    motorRunning = true;
    
  // check limit switch B1 or C
   if (limitSwitchB1Value < 100 || limitSwitchCValue < 100) {
      buttonPressed = true;
    digitalWrite(motor12vPin1, LOW);
    digitalWrite(motor12vPin2, LOW);
    motor12vRunning = false;      

  // Measure distance
  long duration, distance;
  digitalWrite(GarbagetrigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(GarbagetrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(GarbagetrigPin, LOW);
  duration = pulseIn(GarbageechoPin, HIGH);
  distance = (duration / 2) / 29.1; // in cm

  if (buttonPressed) {
  storedDistance = distance;
  }
    delay (2000);
    digitalWrite(motor12vPin1, LOW);
    digitalWrite(motor12vPin2, HIGH);
    motor12vRunning = true;
    motor12vDirection = false;
  }
} // check limit switch B0
  else if (limitSwitchB0Value < 100) {
    if (motor12vRunning && !motor12vDirection) {
      digitalWrite(motor12vPin1, LOW);
      digitalWrite(motor12vPin2, LOW);
      motor12vRunning = false;
      motorRunning = false;

  // Lights the LED RING according to the stored distance value
  int lightedLeds = map(storedDistance, minDistance, maxDistance, 0, ledCount);
  for (int i = 0; i < ledCount; i++) {
    if (i < lightedLeds) {
      ledRing.setPixelColor(i, ledRing.Color(0, 127, 0));
    } 
  }
  ledRing.show();

  // Turn off the LEDs after 2 seconds
  delay(2000); // Wait for 2 seconds
  digitalWrite(LED_PIN, LOW);
  for (int i = 0; i < ledCount; i++) {
  ledRing.setPixelColor(i, ledRing.Color(0, 0, 0)); // Turn off all LEDs
  }  
  ledRing.show();

  delay(100);
    motor12vRunning = false;
    }
  }
}

Thanks for stopping by.

Good luck with the flaws.

a7

2 Likes

As long as you're okay with it then yes of course use it.
There is not time for everything right now.

But I suggest that as ideas come to mind, just write something down for each and keep it. Your unconscious mind, the back part, may imagine and work and at some point you may have enough to frame a new version of how it should be. If there comes sufficient time and perhaps your skills have also developed, you may want to make a new sketch that works in a new way and those notes may help.

1 Like

Whole purpose of a flowchart....