Issue with Arduino Code for Motor Control with Limit Switches

Project Description: I am working on an Arduino project to control a motorized door using limit switches and a remote control (433 MHz RF). The motor should open and close the door, stopping when the respective limit switch is triggered.

Problem: When opening the door, the motor sometimes stops immediately without reaching the limit switch. This issue does not occur when closing the door; the motor stops correctly at the limit switch.

Current Setup:

  • Arduino Uno
  • Motor driver connected to pins 8, 9, and 10
  • Limit switches connected to pins 2 and 3
  • RF receiver connected to pin 7
  • Remote control with RF codes
#include <RCSwitch.h>

// Pin definitions
const int motorIn1 = 8;
const int motorIn2 = 9;
const int motorPWM = 10;
const int openLimitSwitch = 2;
const int closeLimitSwitch = 3;
const int toggleButton = 4; // Pin for open/close button
const int rfReceiverPin = 7; // Pin for RF receiver

// Variables
int motorSpeed = 0; // Motor speed (0-255)
const int maxSpeed = 255; // Maximum motor speed
const int slowSpeed = 100; // Slow start and stop speed
const int accelerationDelay = 100; // Delay between speed increments (milliseconds)

bool doorOpening = false;
bool doorClosing = false;
bool doorOpen = false; // Track if the door is open
bool doorClosed = true; // Track if the door is closed

unsigned long debounceDelay = 50; // Debounce delay in milliseconds
unsigned long lastDebounceTimeButton = 0; // Last debounce time for toggle button
int lastButtonState = HIGH; // Last stable state of toggle button

RCSwitch mySwitch = RCSwitch();

// Remote control codes
const unsigned long openCloseCodeA = 2046641; // Actual remote control code for button A
const unsigned long openCloseCodeB = 2046642; // Actual remote control code for button B

void setup() {
  // Set pin modes
  pinMode(motorIn1, OUTPUT);
  pinMode(motorIn2, OUTPUT);
  pinMode(motorPWM, OUTPUT);
  pinMode(openLimitSwitch, INPUT_PULLUP);
  pinMode(closeLimitSwitch, INPUT_PULLUP);
  pinMode(toggleButton, INPUT_PULLUP); // Use internal pull-up resistor

  // Initialize RF receiver
  mySwitch.enableReceive(digitalPinToInterrupt(rfReceiverPin));  // Receiver on interrupt 0 => that is pin #2

  // Initialize serial communication for debugging
  Serial.begin(9600);
  Serial.println("Setup complete. Waiting for commands...");
}

void loop() {
  int currentButtonState = digitalRead(toggleButton);

  // Debounce toggle button
  if (currentButtonState != lastButtonState) {
    lastDebounceTimeButton = millis();
  }
  if ((millis() - lastDebounceTimeButton) > debounceDelay) {
    if (currentButtonState == LOW) {
      handleToggleButton();
    }
  }
  lastButtonState = currentButtonState;

  // Check for RF remote signals
  if (mySwitch.available()) {
    unsigned long rfValue = mySwitch.getReceivedValue();
    Serial.print("Received RF Code: ");
    Serial.println(rfValue);
    handleRFRemote(rfValue);
    mySwitch.resetAvailable();
  }

  // Check limit switches only when motor is moving
  if (doorOpening && digitalRead(openLimitSwitch) == LOW) {
    stopMotor();
    doorOpen = true;
    doorClosed = false;
    doorOpening = false;
    Serial.println("Door is fully open");
  }

  if (doorClosing && digitalRead(closeLimitSwitch) == LOW) {
    stopMotor();
    doorClosed = true;
    doorOpen = false;
    doorClosing = false;
    Serial.println("Door is fully closed");
  }
}

void handleToggleButton() {
  if (doorClosed && !doorOpening) {
    // If the door is closed and not already opening, open the door
    doorOpening = true;
    doorClosing = false;
    openDoor();
  } else if (doorOpen && !doorClosing) {
    // If the door is open and not already closing, close the door
    doorClosing = true;
    doorOpening = false;
    closeDoor();
  }
}

void handleRFRemote(unsigned long rfValue) {
  // Check if the received RF code matches the open/close codes
  if (rfValue == openCloseCodeA || rfValue == openCloseCodeB) {
    Serial.println("RF Code matches open/close command");
    handleToggleButton();
  } else {
    Serial.println("RF Code does not match");
  }
}

void openDoor() {
  Serial.println("Opening door");
  doorOpening = true;
  doorClosing = false;

  // Slow start
  for (motorSpeed = 0; motorSpeed <= slowSpeed; motorSpeed += 5) {
    analogWrite(motorPWM, motorSpeed);
    digitalWrite(motorIn1, HIGH);
    digitalWrite(motorIn2, LOW);
    delay(accelerationDelay); // Adjust this delay to control acceleration speed
  }

  // Max speed
  analogWrite(motorPWM, maxSpeed);
  while (doorOpening) {
    // Keep running the motor until the limit switch is triggered
    analogWrite(motorPWM, maxSpeed);
    digitalWrite(motorIn1, HIGH);
    digitalWrite(motorIn2, LOW);
    if (digitalRead(openLimitSwitch) == LOW) {
      stopMotor();
      doorOpening = false;
      doorOpen = true;
      doorClosed = false;
      Serial.println("Door is fully open");
      break; // Exit the loop
    }
    delay(10); // Check limit switch periodically to avoid endless loop
  }
}

void closeDoor() {
  Serial.println("Closing door");
  doorClosing = true;
  doorOpening = false;

  // Slow start
  for (motorSpeed = 0; motorSpeed <= slowSpeed; motorSpeed += 5) {
    analogWrite(motorPWM, motorSpeed);
    digitalWrite(motorIn1, LOW);
    digitalWrite(motorIn2, HIGH);
    delay(accelerationDelay); // Adjust this delay to control acceleration speed
  }

  // Max speed
  analogWrite(motorPWM, maxSpeed);
  while (doorClosing) {
    // Keep running the motor until the limit switch is triggered
    analogWrite(motorPWM, maxSpeed);
    digitalWrite(motorIn1, LOW);
    digitalWrite(motorIn2, HIGH);
    if (digitalRead(closeLimitSwitch) == LOW) {
      stopMotor();
      doorClosing = false;
      doorClosed = true;
      doorOpen = false;
      Serial.println("Door is fully closed");
      break; // Exit the loop
    }
    delay(10); // Check limit switch periodically to avoid endless loop
  }
}

void stopMotor() {
  analogWrite(motorPWM, 0);
  digitalWrite(motorIn1, LOW);
  digitalWrite(motorIn2, LOW);
  doorClosing = false;
  doorOpening = false;
  Serial.println("Motor stopped");
}

Debug Output:

  • When opening the door, the motor sometimes stops immediately without reaching the limit switch.

Questions:

  1. What could be causing the motor to stop prematurely when opening the door?
  2. Is there an issue with the debouncing logic or the motor control logic?
  3. Are there any suggestions for improving the motor control logic or ensuring the limit switches work correctly?

Thank you for your help!

let me guess, your openSwitch have longest wires?

does it work? afaik interrupt is on pin 2.

#include <RCSwitch.h>
const byte motorIn1 = 8;
const byte motorIn2 = 9;
const byte motorPWM = 10;
const byte openLimitSwitch = 2;
const byte closeLimitSwitch = 3;
const byte toggleButton = 4; // Pin for open/close button
const byte rfReceiverPin = 7; // Pin for RF receiver

const byte debounceDelay = 50; // Debounce delay in milliseconds
const byte maxSpeed = 255; // Maximum motor speed
const byte slowSpeed = 100; // Slow start and stop speed
const byte accelerationDelay = 100; // Delay between speed increments (milliseconds)
const unsigned long openCloseCodeA = 2046641UL; // Actual remote control code for button A
const unsigned long openCloseCodeB = 2046642UL; // Actual remote control code for button B
#define stopMotor  {digitalWrite(motorPWM, 0);Serial.println("Motor stopped");}

byte motorSpeed = 0; // Motor speed (0-255)
bool isOpen = true; // Track if the door is open

RCSwitch mySwitch = RCSwitch();

void setup() {
  pinMode(motorIn1, OUTPUT);
  pinMode(motorIn2, OUTPUT);
  pinMode(motorPWM, OUTPUT);
  pinMode(openLimitSwitch, INPUT_PULLUP);
  pinMode(closeLimitSwitch, INPUT_PULLUP);
  pinMode(toggleButton, INPUT_PULLUP); // Use internal pull-up resistor

  // Initialize RF receiver
  mySwitch.enableReceive(digitalPinToInterrupt(rfReceiverPin));  // Receiver on interrupt 0 => that is pin #2

  // Initialize serial communication for debugging
  Serial.begin(9600);
  Serial.println("Setup complete. Waiting for commands...");
}

void loop() {
  static unsigned long rfValue;
  static bool lastButtonState = HIGH; // Last stable state of toggle button

  bool currentButtonState = digitalRead(toggleButton);
  if ( !currentButtonState && lastButtonState) {
    handleToggleButton();
    lastButtonState = currentButtonState;
  }

  // Check for RF remote signals
  if (mySwitch.available()) {
    rfValue = mySwitch.getReceivedValue();
    Serial.print("Received RF Code: ");
    Serial.println(rfValue);
    handleRFRemote(rfValue);
    mySwitch.resetAvailable();
  }
}

void handleToggleButton() {
  if (isOpen) {
    // If the door is open and not already closing, close the door
    closeDoor();
    isOpen = false;
  } else   {
    // If the door is closed and not already opening, open the door
    openDoor();
    isOpen = true;
  }
}

void handleRFRemote(unsigned long rfValue) {
  // Check if the received RF code matches the open/close codes
  if (rfValue == openCloseCodeA || rfValue == openCloseCodeB) {
    Serial.println("RF Code matches open/close command");
    handleToggleButton();
  } else     Serial.println("RF Code does not match");
}

void openDoor() {
  Serial.println("Opening door");

  digitalWrite(motorIn1, HIGH);
  digitalWrite(motorIn2, LOW);
  // Slow start
  for (motorSpeed = 0; motorSpeed <= slowSpeed; motorSpeed += 5) {
    analogWrite(motorPWM, motorSpeed);
    delay(accelerationDelay); // Adjust this delay to control acceleration speed
  }

  // Max speed
  digitalWrite(motorPWM, 1);
  while (digitalRead(openLimitSwitch));  // Keep running the motor until the limit switch is triggered
  Serial.println("Door is fully open");
  stopMotor;
  delay(10); // Check limit switch periodically to avoid endless loop
}

void closeDoor() {
  Serial.println("Closing door");

  digitalWrite(motorIn1, LOW);
  digitalWrite(motorIn2, HIGH);
  // Slow start
  for (motorSpeed = 0; motorSpeed <= slowSpeed; motorSpeed += 5) {
    analogWrite(motorPWM, motorSpeed);
    delay(accelerationDelay); // Adjust this delay to control acceleration speed
  }

  // Max speed
  digitalWrite(motorPWM, 1);
  while (digitalRead(closeLimitSwitch)) ;// Keep running the motor until the limit switch is triggered
  Serial.println("Door is fully closed");
  stopMotor;
  delay(10); // Check limit switch periodically to avoid endless loop
}

You can wire the limit switches to directly control the motor , this is a better more reliable method - google !

Noise on an un-grounded pin.

If the limit switches are not using shielded wire and filtering they can be subject to spurious problems. See what they use for filtering limit switches with GRBL (yes I know you are not using GRBL)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.