Arduino, 2x Limit Switches, Stepper Motor not changing direction

I'm beginner to Arduino, including some electronics, and coding, sorry :blush:

My project for now is simple, 1x Stepper Motor to move Clockwise then
Counter Clockwise, triggered by 2x Limit Switches

Problem; limit switches show that they trigger via the Serial Monitor,
but the Motor does not respond by changing direction

Screenshot 2022-06-15 at 09.12.37

hope i did all of that correct :see_no_evil:

[code]
/*
   Created by ArduinoGetStarted.com

   This example code is in the public domain

   Tutorial page: https://arduinogetstarted.com/tutorials/arduino-stepper-motor-and-limit-switch
*/

#include <ezButton.h>
#include <AccelStepper.h>

#define DIRECTION_CCW -1
#define DIRECTION_CW   1

#define STATE_CHANGE_DIR 1
#define STATE_MOVE       2
#define STATE_MOVING     3

#define MAX_POSITION 0x7FFFFFFF // maximum of position we can set (long type)

ezButton limitSwitch_1(A0); // create ezButton object that attach to pin A0;
ezButton limitSwitch_2(A1); // create ezButton object that attach to pin A1;

AccelStepper stepper(AccelStepper::FULL4WIRE, 7, 6, 5, 4);

int stepperState = STATE_MOVE;
int direction    = DIRECTION_CW;
long targetPos   = 0;

void setup() {
  Serial.begin(9600);

  limitSwitch_1.setDebounceTime(50); // set debounce time to 50 milliseconds
  limitSwitch_2.setDebounceTime(50); // set debounce time to 50 milliseconds

  stepper.setMaxSpeed(500.0);   // set the maximum speed
  stepper.setAcceleration(50.0); // set acceleration
  stepper.setSpeed(100);         // set initial speed
  stepper.setCurrentPosition(0); // set position
}

void loop() {
  limitSwitch_1.loop(); // MUST call the loop() function first
  limitSwitch_2.loop(); // MUST call the loop() function first

  if (limitSwitch_1.isPressed()) {
    stepperState = STATE_CHANGE_DIR;
    Serial.println(F("The limit switch 1: TOUCHED"));
  }

  if (limitSwitch_2.isPressed()) {
    stepperState = STATE_CHANGE_DIR;
    Serial.println(F("The limit switch 2: TOUCHED"));
  }

  switch (stepperState) {
    case STATE_CHANGE_DIR:
      direction *= -1; // change direction
      Serial.print(F("The direction -> "));
      if (direction == DIRECTION_CW)
        Serial.println(F("CLOCKWISE"));
      else
        Serial.println(F("ANTI-CLOCKWISE"));

      stepperState = STATE_MOVE; // after changing direction, go to the next state to move the motor
      break;

    case STATE_MOVE:
      targetPos = direction * MAX_POSITION;
      stepper.setCurrentPosition(0); // set position
      stepper.moveTo(targetPos);
      stepperState = STATE_MOVING; // after moving, go to the next state to keep the motor moving infinity
      break;

    case STATE_MOVING: // without this state, the move will stop after reaching maximum position
      if (stepper.distanceToGo() == 0) { // if motor moved to the maximum position
        stepper.setCurrentPosition(0);   // reset position to 0
        stepper.moveTo(targetPos);       // move the motor to maximum position again
      }
      break;
  }

  stepper.run(); // MUST be called in loop() function
}
[/code]

Does 1*=-1 change direction?

in my mind yes, but when altering those numbers, nothing
changed... i changed many things, coding and wiring wise,
nothing changed

the code as you can see is from ArduinoGetStarted.com,
so i assumed it will work, the engineer that works for them
couldn't help me either

You posted a pretty picture but it is of no use to me. Posting a schematic with all the connections as you have wired it will help a lot. Include links to technical data on all of the hardware items. Links to axon are about useless.

to me everything schematic wise shows in my pretty picture,
please show what in a schematic will show what the picture
does not?

Stepper_Motor_Shield_For_Arduino_DRV8825__SKU_DRI0023

DFRobot Shield DRV8825 SKU:DRI0023

  • Support 3.3V and 5V operating voltage
  • Suitable for two-phase and four-wire stepper motor
  • Board with two DRV8825 driver chip and a heat sink has been mounted.
  • Input Voltage:8.2-45V DC (Just power the stepper motor driver), 1.6A output current per coil
  • Driving Pins: D4,D5,D6,D7,D8,D12
  • Squeeze connector, quite easy and convenient.
  • 8 channel digital I/O pins & 6 channel Analog input pins
  • DRV8825 Microstepping bipolar stepper motor driver
  • Six different microstep resolutions (full-step, 1/2-step, 1/4-step, 1/8-step, 1/16-step, 1/32-step)
  • Compatible with Arduino UNO R3, Leonardo, Mega and other controllers, with full port extensions. Support XBee, XBee Wi-Fi, Bluetooth and RF modules, ensure that the needs of your wireless communications.
  • There is a switch on the board Xbee wireless interfaces corner. PROG stop wireless module, available USB programming. RUN time can use the wireless communication module.

Hybrid Stepper Motor 0.5Nm NEMA17 0.9 deg/step 42BYGHM809

  • 0.5Nm (48N.cm) - 4 Wire
  • Step Angle (degrees) : 0.9 Deg (400 steps/Rev)
  • 2-Phase (Rated Current: 1.7A/Phase)
  • Rated Voltage: 3V
  • 5mm Diameter Drive Shaft
  • NEMA 17 form factor

for interest sake this was the pretty picture from
ArduinoGetStarted.com where the code and
instruction were (their wiring on the limit switches
seemed weird, i still tried it, it didn't work)

Print out targetPos after this line and see what you are getting:

    case STATE_MOVE:
      targetPos = direction * MAX_POSITION;

It seems like your connections are good since you are seeing the correct values reported earlier in the program.

ok i see the target position you show, what does
"Print out targetPos" mean, preferably show me
what it means? :blush: i like this, feels exciting

Maybe like this:

 case STATE_MOVE:
      targetPos = direction * MAX_POSITION;
      Serial.print("case STATE_MOVE, current target position = ");
      Serial.println(targetPos);
      stepper.setCurrentPosition(0); // set position
      stepper.moveTo(targetPos);
      //delay(50);   // just in case the serial port gets flooded
      stepperState = STATE_MOVING; // after moving, go to the next state to keep the motor moving infinity
      break;

You may need to slow execution down (with a delay(), just for development) to avoid flooding the serial port.

thanks, this sadly didn't work, nothing changed,
the delay(50) wasn't needed

Can you please let us know what you are seeing printed out?

can i just use Serial Monitor?
if not, where do i put this Serial.println(targetPos); in the code?

See post #9. I actually put the prints in the STATE_MOVE case and you will see the results printed in serial monitor. To copy for us to see, highlight some of the output and hit ctrl-c to copy and then paste the copied text into a post.

Can someone explain to me the logic behind debouncing a limit switch.
My pea-brain tells me that once the switch opens it must be at the limit.
So why debounce. Do you expect another limit behind the limit?
That needless debounce code might also interfere with stepper speed.
Leo..

I don't get the obsession with debounce, either.

If the first action is the important one, debounce is not necessary. Another function of software debounce is to verify that the closure was a valid switch action and not noise, but for a limit switch I guess you would want to stop the motor first and ask questions later.

I am a fan of hardware debounce. I usually get flamed for saying this but I don't much care. That is how I have been doing it for near half a century and I don't plan to stop. I have found that if a 0.1uF cap won't debounce a switch then it is garbage.

I am a fan of hardware be-bounce as well. Very easy to do and reduces one source of gremlins. :+1:

Though may not matter much for a limit switch, except if using it to zero out your axes, may get minute errors. Which again may or may not matter depending on how much your program is relying on machine zero.

@cncnotes, doing the 2 step home* like grbl, Marlin and others do would seem to minimize those errors.

*fast to the limit switch, back up and slow back to limit switch then stand off.

1 Like

But this is a limit switch, and you should use an opening contact, for safety.
An opening contact is more reliable than a closing one.
Leo..

I don't like running hot wires all over the machine. Seems, to me, running ground to the switches is somewhat safer. Every 3D printer that I have worked on uses grounded switches so there must be something to it.

Yes, IMHO the switch should be between pin and ground,
with internal pull up, and a 10n cap across the switch to kill RF.
Normally closed, and opening when the limit is reached.
Leo..