Problem with Gantry System Coding (IF and WHILE LOOPS)

Hello,

This is my first time ever learning a coding language so if I have missed something important could you please clarify.

I am designing a XY gantry system with 3 Stepper motors and Limit Switches.

I have have tested all my wiring so I’m positive the code is causing the error.

The problem is that the code is reading the Y-limit switches as LOW when Ive set them to HIGH.

The problem is first experienced in ‘void homeFunction()’ but only with the yright_switch & yleft_switch NOT the X.

The code homes the X-STEPPER fine but will only run the Y-STEPPER when BOTH limit switches are pressed (LOW) BUT it should be when they are unpressed (HIGH). Im defining them as initially (HIGH) through INPUT_PULLUP. I hope this makes sense.

I think the problem is to do with the IF statement but i am unsure and cannot troubleshoot well due to my inexperience.

I have attached the code with comments
Thanks,

Edward

Gantry_System.ino (4.24 KB)

Welcome to the forum. It is much better to post your code using code tags so people can easily see it like this: This is all explained in the sticky post at the top of the forum about how to post.

#include <Stepper.h>

const int stepsPerRevolution = 400;  // change this to fit the number of steps per revolution typically 200 or 400
int motSpeed = 100; //rpm
int dt = 200; //delay time between steps
int homedt = 10; //delay time for homing function
bool homeFlag = false; //intial homing position is false
bool endFlag = false; //final position is false
int location [] = {0, 0}; //Location matrix


// Define the Pins used
#define xleft_switch 22 // Pin 22 connected to limit switch 
#define xright_switch 23
#define yleft_switch 24
#define yright_switch 25
#define ybottom_switch 26

// StepperMotor Setup
Stepper myStepperY(stepsPerRevolution, 8, 9, 10, 11);// initialize the stepper library on pins 8 through 11:
Stepper myStepperX(stepsPerRevolution, 4, 5, 6, 7);


void setup()
{
  Serial.begin(9600);  // Start the Serial monitor with speed of 9600 Bauds

  //define pins initial input as high
  pinMode(xleft_switch, INPUT_PULLUP);
  pinMode(xright_switch, INPUT_PULLUP);
  pinMode(yleft_switch, INPUT_PULLUP);
  pinMode(yright_switch, INPUT_PULLUP);
  pinMode(ybottom_switch, INPUT_PULLUP);


  myStepperY.setSpeed(motSpeed);
  myStepperX.setSpeed(motSpeed);

}


void loop()
{
  homeFunction(); //excute home function

  if (homeFlag == true) //if home function is true begin stepping function
  {
    beginStepping();
  }

  if (endFlag == 1) //if stepping function is complete begin homing function.
  {
    homeFunction();
  }
}

void homeFunction()
{ Serial.print("Gantry is Homing . . . . . . . . . . . ");

  if (!digitalRead(xright_switch) && !digitalRead(yleft_switch) && !digitalRead(yright_switch)) // if all three limit switches are already pressed then home function complete
  {
    homeFlag = true; //currently at home position
    Serial.println("Homing Completed, Current Location [0,0]");
    Serial.println("");
  }

  while (digitalRead(xright_switch)) //while x-right limit switch is unpressed, step +x. Stop stepping once the x-right limit switch is pressed.
  {
    myStepperX.step(stepsPerRevolution);
    delay(homedt);
  }

  Serial.println("Homing X Completed");
  Serial.println("");

  while (digitalRead(yright_switch)); //while y-right limit switch is unpressed, step -y. 
  {
    myStepperY.step(-stepsPerRevolution);
    delay(homedt);
  }
  while (digitalRead(yleft_switch)); //while y-left limit switch is unpressed, step -y. 
  {
    myStepperY.step(-stepsPerRevolution);
    delay(homedt);
  }
  Serial.println("Homing Y Completed"); //Stop stepping once the y-right limit switch && y-left limit switch is pressed.
  Serial.println("");


  if (!digitalRead(xright_switch) && !digitalRead(yleft_switch) && !digitalRead(yright_switch)) //if all 3 limit switches is pressed homing is completed
  {
    homeFlag = true;
    Serial.println("Homing Completed, Current Location [0,0]");
    Serial.println("");

  }

}

void beginStepping()
{
  Serial.print("Gantry is Stepping . . . . . . . . . . . ");

  while (digitalRead(ybottom_switch)) //while bottom limit is HIGH travel +y
  {
    myStepperY.step(stepsPerRevolution);
    location[1]++; //increase array [:,0]++
    delay(dt);

    Serial.print(location[0]);
    Serial.print(",");
    Serial.print(location[1]);
  }
  myStepperX.step(-stepsPerRevolution); //travel +x
  location[0]++; //increase array [0,:]++
  delay(dt);

  Serial.print(location[0]);
  Serial.print(",");
  Serial.print(location[1]);

  while (digitalRead(yleft_switch) && digitalRead(yright_switch)) //while left and right limit is HIGH travel -y
  {
    myStepperY.step(-stepsPerRevolution);
    location[1]--; //increase array [:,0]--
    delay(dt);

    Serial.print(location[0]);
    Serial.print(",");
    Serial.print(location[1]);
  }
  myStepperX.step(-stepsPerRevolution);  //travel +x
  location[0]++; //increase array [0,:]++
  delay(dt);

  Serial.print(location[0]);
  Serial.print(",");
  Serial.print(location[1]);

  if (!digitalRead(xleft_switch) && !digitalRead(ybottom_switch))
  {
    endFlag = true;
    Serial.println("Gantry Stepping Completed......");
    Serial.print(location[0]);
    Serial.print(",");
    Serial.print(location[1]);
    Serial.println("Returning Home......");

  }
}

As for your code, your homeing function waits for all three limit switches to be LOW but your very next statement tests one of those switches for being HIGH, which will never happen since you have not moved.

Also, you are doing a lot of steps (200) between tests for your limit switch. It would be better and safer to single step, test and repeat until you hit your limit switches.

These lines are probably not what you intended...

 while (digitalRead(yright_switch));
while (digitalRead(yleft_switch));

Both whiles are followed by a code block { } but the semicolon at then end of a while terminates the while.
So the while executes continuously until the digitalRead returns HIGH.
Then the code block executes once only.

If you intend for the code block to execute while the condition is true, remove the semicolons.
If you want only the while executing then what’s the point of the following lines being in a code block?

You'll also likely encounter performance issues unless you use speed ramping with your steppers,
the AccelStepper library can do this for you its worth looking at.

Without speed ramping the maximum usable speed will be severely restricted (steppers take time to spin up,
and if you don't give them this time they will have to miss-step).

pcbbc:
These lines are probably not what you intended...

 while (digitalRead(yright_switch));

while (digitalRead(yleft_switch));




Both whiles are followed by a code block { } but the semicolon at then end of a while terminates the while.
So the while executes continuously until the digitalRead returns HIGH.
Then the code block executes once only.

If you intend for the code block to execute while the condition is true, remove the semicolons.
If you want only the while executing then what’s the point of the following lines being in a code block?

Thank you all for your replies. pcbbc you are correct the semicolons are not what i intended and i have now removed them.

blh64:
Also, you are doing a lot of steps (200) between tests for your limit switch. It would be better and safer to single step, test and repeat until you hit your limit switches.

blh64 how do I change the the step rate to single step just for the homing function? I have had a lot of trouble with getting these stepper motors to operate smoothly. The manufacture recommended stepsPerRevolution was 200 but the stepper did not sound healthy during operation. I found 400 to be the smoothest. I then increased the rpm to untill 100 where the operation sounded the smoothest.

MarkT:
You'll also likely encounter performance issues unless you use speed ramping with your steppers,
the AccelStepper library can do this for you its worth looking at.

Without speed ramping the maximum usable speed will be severely restricted (steppers take time to spin up,
and if you don't give them this time they will have to miss-step).

MarkT I tried using AccelStepper library but faced performance issues with determining the correct speed and acceleration for the stepper motors. I am using H-Bridge motor drivers with 17HS19-2004S1 Stepper Motors. I can link the first section of my code using the accelstepper library. The problem is that the stepper motors do not sound good when running with this code, despite me trying various different speeds and accelerations. It seems the stepper motors are not compatible with the library? Do you know what the problem could be and could you recommend another Stepper library?

#include "AccelStepper.h" 

// AccelStepper Setup
AccelStepper stepperY(4, 8, 9, 10, 11); // 4 = means a 4 wire stepper (4 pins required).
AccelStepper stepperX(4, 4, 5, 6, 7); // 4 = means a 4 wire stepper (4 pins required).

// Define the Pins used
#define xleft_switch 22 // Pin 22 connected to limit switch 
#define xright_switch 23 
#define yleft_switch 24
#define yright_switch 25
#define yrbottom_switch 26

// Stepper Travel Variables
long TravelX;  // Used to store the X value entered in the Serial Monitor
long TravelY; // Used to store the Y value entered in the Serial Monitor
int move_finished=1;  // Used to check if move is completed
long initial_homing=-1;  // Used to Home Stepper at startup


void setup() {
   Serial.begin(9600);  // Start the Serial monitor with speed of 9600 Bauds
   
   pinMode(xleft_switch, INPUT_PULLUP);
   pinMode(xright_switch, INPUT_PULLUP);
   pinMode(yleft_switch, INPUT_PULLUP);
   pinMode(yright_switch, INPUT_PULLUP);
   pinMode(yrbottom_switch, INPUT_PULLUP);
   
   
   delay(5);  // Wait for EasyDriver wake up

   //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperY.setMaxSpeed(8000); // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperY.setSpeed(8000);
  stepperY.setAcceleration(4000);  // Set Acceleration of Stepper
  
  stepperX.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(100.0);  // Set Acceleration of Stepper

// Start Homing procedure of Stepper Motor at startup

  Serial.print("Stepper X is Homing . . . . . . . . . . . ");
  
  while (digitalRead(xleft_switch)) {  // Make the Stepper move CCW until the switch is activated   
    stepperX.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed initialhoming=initialhoming-1;
    stepperX.run();  // Start moving the x stepper
    delay(5);
  }
  stepperX.setCurrentPosition(0);  // Set the current position as zero for now
  stepperX.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperX.setAcceleration(100.0);  // Set Acceleration of Stepper
  initial_homing=1;

   while (!digitalRead(xleft_switch)) { // Make the Stepper move CW until the switch is deactivated
    stepperX.moveTo(initial_homing);  
    stepperX.run();
    initial_homing++;
    delay(5); 
     }
     
  stepperX.setCurrentPosition(0);
  Serial.println("Homing X Completed");
  Serial.println("");
  stepperX.setMaxSpeed(1000.0);      // Set Max Speed of Stepper (Faster for regular movements)
  stepperX.setAcceleration(1000.0);  // Set Acceleration of Stepper
    

     Serial.print("Stepper Y is Homing . . . . . . . . . . . ");
     
  while (digitalRead(yleft_switch)) {  // Make the Stepper move CCW until the switch is activated   
    stepperY.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperY.run();  // Start moving the y stepper
    delay(5);
  }
    while (digitalRead(yright_switch)) {  // Make the Stepper move CCW until the switch is activated   
    stepperY.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperY.run();  // Start moving the y stepper
    delay(5);
  }
  stepperY.setCurrentPosition(0);  // Set the current position as zero for now
  stepperY.setMaxSpeed(666.66);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperY.setAcceleration(100.0);  // Set Acceleration of Stepper
  initial_homing=1;

   while (!digitalRead(yleft_switch)) { // Make the Stepper move CW until the switch is deactivated
    stepperY.moveTo(initial_homing);  
    stepperY.run();
    initial_homing++;
    delay(5);
   }
   
   while (!digitalRead(yright_switch)) { // Make the Stepper move CW until the switch is deactivated
    stepperY.moveTo(initial_homing);  
    stepperY.run();
    initial_homing++;
    delay(5);
   }

  stepperY.setCurrentPosition(0);
  Serial.println("Homing Y Completed");
  Serial.println("");
  stepperY.setMaxSpeed(1000.0);      // Set Max Speed of Stepper (Faster for regular movements)
  stepperY.setAcceleration(1000.0);  // Set Acceleration of Stepper\

  // Print out Instructions on the Serial Monitor at Start
  Serial.println("Enter Y Travel distance (Positive for CW / Negative for CCW and Zero for back to Y-Home): ");

edwat:
blh64 how do I change the the step rate to single step just for the homing function? I have had a lot of trouble with getting these stepper motors to operate smoothly. The manufacture recommended stepsPerRevolution was 200 but the stepper did not sound healthy during operation. I found 400 to be the smoothest. I then increased the rpm to untill 100 where the operation sounded the smoothest.

You don't change the step rate, you just take a a single step rather than 200 steps. Something like this:

bool atHome = false;
while( !atHome ) {
  atHome = checkLimitSwitches();
  if ( !atHome) {
    myStepperX.step(1);
    delay(15);
  }
}

You would have to create the checkLimitSwitches() function which would return true when the limit switches have been tripped.

blh64:
You don't change the step rate, you just take a a single step rather than 200 steps. Something like this:

bool atHome = false;

while( !atHome ) {
  atHome = checkLimitSwitches();
  if ( !atHome) {
    myStepperX.step(1);
    delay(15);
  }
}



You would have to create the checkLimitSwitches() function which would return true when the limit switches have been tripped.

AT this point, the end-stop is still depressed and you do not know how many steps are needed to turn the end-stop off.

So, reverse the motor direction and do single steps until the end-stop is NOT depressed. Then the rest of your code will not get confused because the end-stop shows movement is already at the end.

Good luck!

Paul