Homing Stepper using Accel Library - Direction reversal

I am trying to home a stepper motor using the excel library. It starts moving towards the limit switch but after hitting the limit switch, it does not reverse the direction to reach the destined position. Below is code.

#include <AccelStepper.h>

AccelStepper stepper(1, 7, 6);    
const uint8_t Limit_Switch = A1;  

long initial_homing = -1;
int Limit_Switch_Stat;


void setup()
{
  Serial.begin(9600);
  pinMode(Limit_Switch, INPUT_PULLUP);
  stepper.setMaxSpeed(4000);
  stepper.setAcceleration(600);  // Set Acceleration

  while (digitalRead(Limit_Switch) == HIGH) {
    Home();
  }
}

void Home() {
  stepper.move(initial_homing);  // Set the position to move to
  stepper.setSpeed(600);
  stepper.runSpeed();
  initial_homing--;
  stepper.setCurrentPosition(0);
  Limit_Switch_Stat = digitalRead(Limit_Switch);
  if (Limit_Switch_Stat == HIGH) {
    exit;
  }
  if (Limit_Switch_Stat == LOW) {
    stepper.stop();
    stepper.setCurrentPosition(0);
    stepper.setMaxSpeed(400);
    stepper.setAcceleration(400);  // Set Acceleration
    stepper.setSpeed(-100);
    stepper.moveTo(500);
    stepper.runToPosition();
    stepper.setCurrentPosition(0);
    stepper.stop();
  }
}

void loop()
{

}

Here's the thing: when you're using AccelStepper, you need to make sure you're telling the motor what to do step by step. Right now, it seems like you might be missing some logic after your motor hits the switch.

In your Home() function, you've got a check for the limit switch status. When the limit switch is hit (LOW), you tell the motor to stop, set a new position, but then you immediately tell it to move to position 500 and run there. If the motor is already past the switch, it might not act as you expect.

You might want to add more control after the limit switch is triggered. Here's a simpler idea of what you might do:

  1. Move towards the switch.
  2. When the switch is hit, stop and back up a little.
  3. Then go to your desired position from the backed up spot.

Your code needs to handle all these steps. Right now, after the switch is triggered, you set the current position to 0, but then you move to position 500 immediately without backing up first.

Try something like this instead:

After the limit switch is triggered (when Limit_Switch_Stat == LOW), do these:

  1. Stop the motor.
  2. Set the current position to 0 to recalibrate the position.
  3. Move the motor a small distance away from the switch to give it some space (for example, stepper.move(-50);).
  4. Then tell it to go to the new desired position (stepper.moveTo(some_position);).

And remember, every time you want the motor to move, you have to call stepper.run() or stepper.runSpeed() inside your loop to actually process the motor steps. The AccelStepper library needs this repeated call to step the motor.

In your existing code, after detecting the switch is LOW, you can add a step to move backwards, like this:

if (Limit_Switch_Stat == LOW) {
  stepper.stop(); // Stop the motor
  delay(50); // Short delay to ensure the stop completes
  stepper.setCurrentPosition(0); // Reset position to 0 to consider this the home position
  stepper.move(-50); // Move a small amount back from the switch
  while (stepper.currentPosition() != -50) {
    stepper.run(); // Run until the motor moves back by 50 steps
  }
  stepper.setMaxSpeed(400); // Set a new max speed
  stepper.setAcceleration(400); // Set a new acceleration
  stepper.moveTo(500); // Set the target position to 500
  while (stepper.currentPosition() != 500) {
    stepper.run(); // Run until the motor reaches position 500
  }
  stepper.setCurrentPosition(0); // Reset the position again if needed
  stepper.stop(); // Stop the motor
}

Also, check your loop function, which is currently empty. You need to continuously check if the motor needs to step to reach its target position:

void loop() {
  // This is where you would usually call stepper.run() or 
  // stepper.runSpeed() to actually move the stepper
}

Depending on your setup, you might want to handle the home position logic within the loop() instead of the setup() function, as setup() only runs once when the Arduino starts up.

Just to mention, be cautious when using exit; in your Home() function. The exit command is not really proper in the Arduino environment and doesn't do what it does in other programming environments. If you want to exit a loop or stop a function early, you should use return; instead of exit;. So, in your Home() function, when the limit switch is HIGH, and you want to stop the homing process, you should use return; to exit the function.

Let's clean up the Home() function and integrate it into the main loop. Here’s an example of how you can modify your code:

void loop() {
  // Only run the home function if we're not already at the home position.
  if (digitalRead(Limit_Switch) == HIGH) {
    Home();
  } else {
    // Once homed, you can add additional code here to perform other actions.
  }
  
  // Always call run to keep the stepper moving as needed.
  stepper.run();
}

void Home() {
  // Move towards the limit switch slowly
  stepper.moveTo(initial_homing);
  stepper.setSpeed(600);
  
  // While we haven't hit the limit switch, keep moving
  while (digitalRead(Limit_Switch)) {
    stepper.run();
  }
  
  // We hit the limit switch, so first stop and back up a bit
  stepper.stop();
  delay(50); // Short delay for the stop to take effect
  stepper.setCurrentPosition(0); // Set this position as 0
  stepper.move(-100); // Move back 100 steps from switch
  
  // Move back from the switch
  while(stepper.currentPosition() > -100) {
    stepper.run();
  }
  
  // Now set the desired position to go to after homing
  stepper.setCurrentPosition(0); // Reset position again to 0 if needed
  stepper.setMaxSpeed(400); // Set the target speed for moving towards desired position
  stepper.setAcceleration(400); // Set the acceleration
  // Set the target position after homing
  stepper.moveTo(500); // We want to move to position 500 after homing
  
  // Go to the target position from the backed-up position
  while (!stepper.runToPosition()) { // This will run until the motor reaches the position 500
    // This block will keep on looping until we reach the target position.
  }
  
  // Optional: Set the current position to 0 again if this is your new home/reference position
  stepper.setCurrentPosition(0);

  // Now you are ready to perform other operations, now that the motor is homed.
}

In this updated code, after touching the limit switch, the motor will reverse for 100 steps (backing away from the switch), and then move to the desired position 500 steps away from the home position. The stepper.runToPosition() in the loop will execute until it reaches position 500.

Remember, the loop() function will continue to execute repeatedly. If you want it to stop moving after homing or after performing a set of operations, you need to add logic to prevent the Home() function from being called again or to exit the loop after reaching the desired state.

Finally, you should remove any unnecessary calls to stepper.stop() once you have the movement logic correct, as runToPosition() will handle stopping the motor when the target position is reached.

Thanks for your guidance. Here, I am homring the stepper in the initial setup so that it can be placed at the base position to perform other functions in the loop.
I will try to modify the code as per our guidance and will come back after testing

I tested the code step by step. It worked but with some improvements. I included the code for the "debounce" of the limit switch. The code was amended accordingly.
Connections, soldering etc. were checked but it did not work. It is always rotating in CW direction. Motor is not reversing direction with negative stepping.

Kindly provide some guidance.

#include <AccelStepper.h>

AccelStepper stepper(1, 7, 6);    // direction Digital 8, pulses Digital 9
const uint8_t Limit_Switch = A1;  // for Paint scheme. Bottom Proximity sensor
long initial_homing = -1;
const int numReadings = 40;
int Limit_Switch_Stat;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
float total = 0;                  // the running total
float average = 0.00;                // the average
int average1;
int i;
void setup()
{
  //  Serial.begin(9600);
  pinMode(Limit_Switch, INPUT_PULLUP);
  stepper.setMaxSpeed(4000);
  stepper.setAcceleration(600);  // Set Acceleration
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
  for (i = 0; i < 40; i++) {
    Read();
  }
  while (average1 == 1) {
    Serial.println("Going Home");
    Home();
    Read();
  }
}


void loop() {
  //  // Only run the home function if we're not already at the home position.
  //  if (digitalRead(Limit_Switch) == HIGH) {
  //    Home();
  //  } else {
  //    // Once homed, you can add additional code here to perform other actions.
  //  }
  //
  //  // Always call run to keep the stepper moving as needed.
  //  stepper.run();
}

// ...

void Read() {
  total = total - readings[readIndex];
  readings[readIndex] = digitalRead(Limit_Switch);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;
  Serial.println("Read");
  if (average > 0.50) {
    average1 = 1;
    Serial.println(average1);
  }
  else
    average1 = 0;
}


void Home() {
  // Move towards the limit switch slowly
  Serial.println("In Home");
  stepper.moveTo(initial_homing);
  stepper.setSpeed(600);
  Read();
  // While we haven't hit the limit switch, keep moving
  while (average1 == 1) {
    stepper.run();
    Serial.println("Running");
    return;
  }
  Read();
  if (average1 == 0) {
    // We hit the limit switch, so first stop and back up a bit
    stepper.stop();
    Serial.println("Stopped");
    delay(50); // Short delay for the stop to take effect
    stepper.setCurrentPosition(0); // Set this position as 0
  }
  delay(2000);
  stepper.setMaxSpeed(400); // Set the target speed for moving towards desired position
  stepper.setAcceleration(400); // Set the acceleration
  stepper.setSpeed(400);
  
  stepper.move(-100); // Move back 100 steps from switch

  // Move back from the switch
  while (stepper.currentPosition() > -100) {
    stepper.run();
  }

  //  // Now set the desired position to go to after homing
  //  stepper.setCurrentPosition(0); // Reset position again to 0 if needed
  //  stepper.setMaxSpeed(400); // Set the target speed for moving towards desired position
  //  stepper.setAcceleration(400); // Set the acceleration
  //  delay(1000);
  //  // Set the target position after homing
  //  stepper.moveTo(-300); // Adjust this value based on your requirements
  //
  //  // Go to the target position from the backed-up position
  ////  while (!stepper.runToPosition()) {
  //  while (stepper.isRunning()) {
  //    // This block will keep on looping until we reach the target position.
  //    stepper.run();
  //  }
  //
  //  // Optional: Set the current position to 0 again if this is your new home/reference position
  //  stepper.setCurrentPosition(0);

  // Now you are ready to perform other operations, now that the motor is homed.
}

to HOME a stepper motor, you need to move it one step at a time toward the limit switch until the limit switch becomes active.

when using stepper motors, once the zero-position is known, the limit switch is not longer needed

#include <AccelStepper.h>

AccelStepper stepper (1, 7, 6);    // direction Digital 8, pulses Digital 9

const uint8_t Limit_Switch = A1;

void Home ()
{
    stepper.setSpeed (600);

    while (LOW != digitalRead (Limit_Switch))
        stepper.move (-1);

    stepper.setCurrentPosition(0); // Set this position as 0
}

void setup ()
{
    Serial.begin (9600);
    pinMode (Limit_Switch, INPUT_PULLUP);
    Home ();
}

void loop ()
{
}

Thanks for your guidance. Code is working properly. It wasn't the fault of code. Driver was faulty.

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