Steppers Not Moving At Same Speed

Hello Experts,

I have a code for moving the stepper motors of a 3d printer. In one part of the code, I can chose to move one stepper motor by pressing a button. In other part of the code (homing), the same stepper needs to be moved, and I used the same function. The problem is, the speeds are not the same: the "homing" speed is way, way slower.

I am using an Arduino Mega with LCD Keypad Shield. Here is the part of the code that the stepper goes "fast":

void menuItem1() { // Function executes when you select the 2nd item from main menu
  int activeButton = 0;

  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Move X Axis");

  while (activeButton == 0) {
    int button;
    readKey = analogRead(0);
    if (readKey < 790) {
      delayMicroseconds(1000);
      readKey = analogRead(0);
    }
    button = evaluateButton(readKey);
    switch (button) {
      case 0:  // When button returns as 0
        break;
      case 1:  // When button returns as 1
        lcd.clear();
        lcd.print("Press Up or Down");
        lcd.setCursor(0, 1);
        break;
      case 2:  // When button returns as 2
        valXUp = digitalRead(LimitSwitchXUp); // read sensor
        if (valXUp == HIGH) {
          MoveAxisUp (Xdir, Xstep);
        }
        break;
      case 3:  // When button returns as 3
        valXDown = digitalRead(LimitSwitchXDown); // read sensor
        if (valXDown == HIGH) {
          MoveAxisDown (Xdir, Xstep);
          break;
        }
        break;
      case 4:  // This case will execute if the "back" button is pressed
        button = 0;
        activeButton = 1;
        break;
    }
  }
}

In this case, the X axis will move with this MoveAxisDown function. Here's the function for you guys to see (for up and down):

void MoveAxisUp(int Direction, int Step) {
  digitalWrite(Direction, HIGH);          // Xdir = X Direction
  digitalWrite(Step, HIGH);        // Setting Steps
  delayMicroseconds(200);          // Delay between Steps
  digitalWrite(Step, LOW);
  delayMicroseconds(200);          // The nut will go up on its own axis
}

void MoveAxisDown(int Direction, int Step) {
  digitalWrite(Direction, LOW);          // Xdir = X Direction
  digitalWrite(Step, HIGH);        // Setting Steps
  delayMicroseconds(200);          // Delay between Steps
  digitalWrite(Step, LOW);
  delayMicroseconds(200);          // The nut will go DOWN on its own axis
}

Now, here's the part of the code where the stepper go very slow:

void menuItem5() { // Function executes when you select the 5th item from main menu
  int activeButton = 0;

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Press Up To");
  lcd.setCursor(0, 1);
  lcd.print("Start Homing");

  while (activeButton == 0) {
    int button;
    float savedLT;
    readKey = analogRead(0);
    if (readKey < 790) {
      delay(100);
      readKey = analogRead(0);
    }
    button = evaluateButton(readKey);
    switch (button) {
      case 2:
        valXUp = digitalRead(LimitSwitchXUp); // Reading sensor values
        valXDown = digitalRead(LimitSwitchXDown);

        valZ1Up = digitalRead(LimitSwitchZ1Up);
        valZ1Down = digitalRead(LimitSwitchZ1Down);

        //Serial.println("ValUP: ");
        valZ2Up = digitalRead(LimitSwitchZ2Up);
        //Serial.println(valZ2Up);
        valZ2Down = digitalRead(LimitSwitchZ2Down);
        //Serial.println(valZ2Down);

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Moving Z2");
        delay(1000);

        flagZ2 = 0;
        while (flagZ2 == 0) {
          valZ2Down = digitalRead(LimitSwitchZ2Down);
          Serial.println(valZ2Down);
          Serial.print("Z2 - Down");
          if (valZ2Down == LOW) {
            valZ2Down = digitalRead(LimitSwitchZ2Down);
            if (valZ2Down == LOW) {
              valZ2Down = digitalRead(LimitSwitchZ2Down);
              if (valZ2Down == LOW) {
                flagZ2 = 1;
              }
            }
          }
          MoveAxisUp (Z2dir, Z2step);
        }

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Moving Z1");
        delay(1000);

        flagZ1 = 0;
        while (flagZ1 == 0) {
          valZ1Down = digitalRead(LimitSwitchZ1Down);
          Serial.println(valZ1Down);
          Serial.print("Z1 - Down");
          if (valZ1Down == LOW) {
            valZ1Down = digitalRead(LimitSwitchZ1Down);
            if (valZ1Down == LOW) {
              valZ1Down = digitalRead(LimitSwitchZ1Down);
              if (valZ1Down == LOW) {
                valZ1Down = digitalRead(LimitSwitchZ1Down);
                flagZ1 = 1;
              }
            }
          }
          MoveAxisUp (Z1dir, Z1step);
        }

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Moving X");
        delay(1000);

        flagX = 0;
        while (flagX == 0) {
          valXUp = digitalRead(LimitSwitchXUp);
          Serial.println(valXUp);
          Serial.print("X - Up");
          if (valXUp == LOW) {
            valXUp = digitalRead(LimitSwitchXUp);
            if (valXUp == LOW) {
              valXUp = digitalRead(LimitSwitchXUp);
              if (valXUp == LOW) {
                flagX = 1;
              }
            }
          }
          MoveAxisUp (Xdir, Xstep);
        }

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Moving Z2");
        delay(1000);

        flagZ22 = 0;
        while (flagZ22 == 0) {
          valZ2Up = digitalRead(LimitSwitchZ2Up);
          Serial.print("Z2 - Up");
          Serial.println(valZ2Up);
          if (valZ2Up == LOW) {
            valZ2Up  = digitalRead(LimitSwitchZ2Up);
            Serial.print("Z2 - Up");
            Serial.println("Ciclo 1");
            if (valZ2Up == LOW) {
              valZ2Up = digitalRead(LimitSwitchZ2Up);
              Serial.println("Ciclo 2");
              delayMicroseconds(1000);
              if (valZ2Up == LOW) {
                Serial.println("Ciclo 3");
                valZ2Up = digitalRead(LimitSwitchZ2Up);
                if (valZ2Up == LOW ) {
                Serial.println("Ciclo 4");
                flagZ22 = 1;                  
                }
              }
            }
          }
          MoveAxisDown (Z2dir, Z2step);
        }

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Homing Completed");
        break;

      case 4:  // This case will execute if the "back" button is pressed
        button = 0;
        activeButton = 1;
        break;
    }
  }
}

In this part, I'm homing the system. the "val something" variable is a limit switch that I use to prevent the axis from coliding. I need to check if it's low 3 times because of the noise.

Here is the full code if you need it: EDIT: I can't add the full code because the forum only allows 9000 characters.

Any comments?

Thank you Experts,

Josdc

Hello again Experts,

The full code is in the attachments.

Thanks,

Josdc

Original-Menu-Code.ino (25.3 KB)

This is a very complicated way to home your axis - and I am struggling to be polite :slight_smile:

void menuItem5() { // Function executes when you select the 5th item from main menu
  int activeButton = 0;

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Press Up To");
  lcd.setCursor(0, 1);
  lcd.print("Start Homing");

  while (activeButton == 0) {
    int button;
    float savedLT;
    readKey = analogRead(0);
    if (readKey < 790) {
      delay(100);
      readKey = analogRead(0);
    }
    button = evaluateButton(readKey);
    switch (button) {
      case 2:
        valXUp = digitalRead(LimitSwitchXUp); // Reading sensor values
        valXDown = digitalRead(LimitSwitchXDown);

        valZ1Up = digitalRead(LimitSwitchZ1Up);
        valZ1Down = digitalRead(LimitSwitchZ1Down);

        //Serial.println("ValUP: ");
        valZ2Up = digitalRead(LimitSwitchZ2Up);
        //Serial.println(valZ2Up);
        valZ2Down = digitalRead(LimitSwitchZ2Down);
        //Serial.println(valZ2Down);

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Moving Z2");
        delay(1000);

        flagZ2 = 0;
        while (flagZ2 == 0) {
          valZ2Down = digitalRead(LimitSwitchZ2Down);
          Serial.println(valZ2Down);
          Serial.print("Z2 - Down");
          if (valZ2Down == LOW) {
            valZ2Down = digitalRead(LimitSwitchZ2Down);
            if (valZ2Down == LOW) {
              valZ2Down = digitalRead(LimitSwitchZ2Down);
              if (valZ2Down == LOW) {
                flagZ2 = 1;
              }
            }
          }
          MoveAxisUp (Z2dir, Z2step);
        }

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Moving Z1");
        delay(1000);

        flagZ1 = 0;
        while (flagZ1 == 0) {
          valZ1Down = digitalRead(LimitSwitchZ1Down);
          Serial.println(valZ1Down);
          Serial.print("Z1 - Down");
          if (valZ1Down == LOW) {
            valZ1Down = digitalRead(LimitSwitchZ1Down);
            if (valZ1Down == LOW) {
              valZ1Down = digitalRead(LimitSwitchZ1Down);
              if (valZ1Down == LOW) {
                valZ1Down = digitalRead(LimitSwitchZ1Down);
                flagZ1 = 1;
              }
            }
          }
          MoveAxisUp (Z1dir, Z1step);
        }

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Moving X");
        delay(1000);

        flagX = 0;
        while (flagX == 0) {
          valXUp = digitalRead(LimitSwitchXUp);
          Serial.println(valXUp);
          Serial.print("X - Up");
          if (valXUp == LOW) {
            valXUp = digitalRead(LimitSwitchXUp);
            if (valXUp == LOW) {
              valXUp = digitalRead(LimitSwitchXUp);
              if (valXUp == LOW) {
                flagX = 1;
              }
            }
          }
          MoveAxisUp (Xdir, Xstep);
          delayMicroseconds(100);
        }

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Moving Z2");
        delay(1000);

        flagZ22 = 0;
        while (flagZ22 == 0) {
          valZ2Up = digitalRead(LimitSwitchZ2Up);
          Serial.print("Z2 - Up");
          Serial.println(valZ2Up);
          if (valZ2Up == LOW) {
            valZ2Up  = digitalRead(LimitSwitchZ2Up);
            Serial.print("Z2 - Up");
            Serial.println("Ciclo 1");
            if (valZ2Up == LOW) {
              valZ2Up = digitalRead(LimitSwitchZ2Up);
              Serial.println("Ciclo 2");
              delayMicroseconds(1000);
              if (valZ2Up == LOW) {
                Serial.println("Ciclo 3");
                valZ2Up = digitalRead(LimitSwitchZ2Up);
                if (valZ2Up == LOW ) {
                Serial.println("Ciclo 4");
                flagZ22 = 1;                  
                }
              }
            }
          }
          MoveAxisDown (Z2dir, Z2step);
        }

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Homing Completed");
        break;

You have a huge amount of stuff in there that is going to interfere with your step timing. Just write a simple homing function.

And this is far from ideal because it uses delay()

void MoveAxisUp(int Direction, int Step) {
  digitalWrite(Direction, HIGH);          // Xdir = X Direction
  digitalWrite(Step, HIGH);        // Setting Steps
  delayMicroseconds(200);          // Delay between Steps
  digitalWrite(Step, LOW);
  delayMicroseconds(200);          // The nut will go up on its own axis
}

void MoveAxisDown(int Direction, int Step) {
  digitalWrite(Direction, LOW);          // Xdir = X Direction
  digitalWrite(Step, HIGH);        // Setting Steps
  delayMicroseconds(200);          // Delay between Steps
  digitalWrite(Step, LOW);
  delayMicroseconds(200);          // The nut will go DOWN on its own axis
}

Have a look at the second example in this Simple Stepper Code to see how to use millis() and micros() for non-blocking timing.

...R

Thank you so much for your feedback Robin! I will follow your instruction.

Thanks,

João

a common homing switch is a non-impact switch. it would be able to measure a passing surface.

you run your axis towards the switch, then run slowly till the switch changes state.
then reverse a bit more than needed to have the switch resume to normal.
then slowly move until the switch changes, lock in that point. then reverse
then move to it again, compare the last point to this point.

consider that you have a runaway axis, the impact on the end would be a physical stop. it should not effect the operation of the switch or damage the switch. consider hitting the end stop with a hammer. a beam interrupt would not be damaged. a press button would be moved, shifted or destroyed.

dave-in-nj:
a common homing switch is a non-impact switch. it would be able to measure a passing surface.

you run your axis towards the switch, then run slowly till the switch changes state.
then reverse a bit more than needed to have the switch resume to normal.
then slowly move until the switch changes, lock in that point. then reverse
then move to it again, compare the last point to this point.

consider that you have a runaway axis, the impact on the end would be a physical stop. it should not effect the operation of the switch or damage the switch. consider hitting the end stop with a hammer. a beam interrupt would not be damaged. a press button would be moved, shifted or destroyed.

Hello Dave,

I'm using very, very small stepper motors. The colision is not a problem.

Josdc:

          if (valZ1Down == LOW) {

valZ1Down = digitalRead(LimitSwitchZ1Down);
            if (valZ1Down == LOW) {
              valZ1Down = digitalRead(LimitSwitchZ1Down);
              if (valZ1Down == LOW) {
                valZ1Down = digitalRead(LimitSwitchZ1Down);
                flagZ1 = 1;
              }
            }
          }

You really expecting there may be different values in subsequent reads?