Starting and stopping a stepper using a button

My project is complex for me and I need some help. I am using an Arduino Uno Wifi Rev 2 fitted with a CNC shield with TMC2208 stepper drivers fitted to Y and Z axis. I have a button Normally Open fitted to the Z- end stop. I would like to have the stepper attached to Z start when I press the button and stop immediately when I release the button. I have tried AI and am completely frustrated. Can anyone please give an old man some help. Here is the code that doesn't work.

// Define pin numbers
#define EN_PIN 8
#define X_DIR_PIN 5 
#define X_STP_PIN 2
#define Y_DIR_PIN 6
#define Y_STP_PIN 3 
#define Z_DIR_PIN 7
#define Z_STP_PIN 4 
#define BTN_PIN 11

// TMC2208
int delayTime = 160; // Delay between each pause (us)
int zStps = 20000; // Steps to move Z
bool isMoving = false; // Flag to keep track if the stepper is moving

void step(boolean dir, byte dirPin, byte stepperPin, int steps) {
  digitalWrite(dirPin, dir);
  delay(5);

  for (int i = 0; i < steps; i++) {
    digitalWrite(stepperPin, HIGH);
    delayMicroseconds(delayTime); 
    digitalWrite(stepperPin, LOW);
    delayMicroseconds(delayTime); 
  }
}

void setup() {
  pinMode(X_DIR_PIN, OUTPUT); 
  pinMode(X_STP_PIN, OUTPUT);
  pinMode(Y_DIR_PIN, OUTPUT); 
  pinMode(Y_STP_PIN, OUTPUT);
  pinMode(Z_DIR_PIN, OUTPUT); 
  pinMode(Z_STP_PIN, OUTPUT);
  pinMode(BTN_PIN, INPUT_PULLUP); // Set the button pin as input with pull-up resistor
  pinMode(EN_PIN, OUTPUT);
  digitalWrite(EN_PIN, LOW);
}

void loop() {
  // Read the button state
  bool buttonState = !digitalRead(BTN_PIN); // Invert the button state, as we're using a Normally Open button

  if (buttonState && !isMoving) {
    // Button has been pressed, move the Z motor to the desired position
    step(false, Z_DIR_PIN, Z_STP_PIN, zStps); // Set the direction to false (CCW) to move the motor in the opposite direction
    isMoving = true;
  }

  if (!buttonState && isMoving) {
    // Button has been released, stop the Z motor
    isMoving = false;
    step(false, Z_DIR_PIN, Z_STP_PIN, 0); // Stop the motor by stepping 0 steps
  }

  // If the stepper is still moving, continue to step
  if (isMoving) {
    step(false, Z_DIR_PIN, Z_STP_PIN, 1); // Set the direction to false (CCW) to move the motor in the opposite direction
  }
}

Sure there are many to help you

But Please first tell us the exact issue that what is not working and a circuit diagram will be highly helpful

This is a code provided by a robot, isn´t it?

The INPUT_PULLUP is making BTN_PIN read HIGH and therefore buttonState is LOW, so the first conditional never assigns isMoving as true so Z motor never moves. (assuming your button pin is tied LOW through a resistor to ground)

Change

BTN_PIN, INPUT_PULLUP

to

BTN_PIN, INPUT

The motor will take off, so be sure to push the button, and release it only when you want Z to move.

A rough simulation.

When I push the button the stepper moves correctly in the right direction.
When I release the button the stepper is supposed to stop but it doesn't, it keeps moving for20000 steps and then stops. It doesn't matter if I hold the button down for 1000 milliseconds or repeatably on and off.
Thank you for getting back so quickly.

Yes, I mentioned AI
AI and I are no longer speaking

The motor taking off is a problem. I need the motor to only respond to the button in a set up sequence so that an operator can move the motor by holding down the button and once the set up is in position the operator can release the button and the motor stops instantly.
Thank you for being so prompt.

Thank you for the simulation however when I turn on the arduino the motor immediately [as you mentioned] runs for 20000 steps and stops but when I press the button the motor starts but when I release the button the motor continues to run for 20000 steps

why not just run the motor one step at a time while the button it pressed. it should stop immediately when the button is released

Check button wiring that it is not floating. The button is pulled high internally when not pressed, but should be pulled to ground by a resistor when pressed.

This is a blocking function, meaning the loop() function will not resume until the motor has finished.
You read the value from the button at the start of the loop() function. That's why you are getting that behaviour.

There's better ways to do this but a quick fix is to check for the value of the button inside the for loop
and break the loop if its detected:

  for (int i = 0; i < steps; i++) {
    digitalWrite(stepperPin, HIGH);
    delayMicroseconds(delayTime); 
    digitalWrite(stepperPin, LOW);
    delayMicroseconds(delayTime); 

    if(digitalRead(BTN_PIN) == HIGH){
       break;
}
  }

Hi, @paymentupfront

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

We need to see how you have connected your hardware.

Thanks... Tom.. :smiley: :+1: :coffee: :australia:

THAT is TOOO obvious ............... but it worked. Thank you so very much Genius.