Simple stop button for (poss hold) stepper motor

Hi I am look for some help to add a stop button to my code. I have managed to get all the aspects I need from adapting and joining various code but all I need is the ability to stop/ start the stepper motor with a single button on a latch/toggle ie on / off each time it is triggered.

I have assigned a button (stopButton)and have tried putting in the potentiometer code with out of range speed settings and it holds the motor (energized) in a fixed position but only when I hole the button as soon as I release it it carry's on. any help would be gratefully received.

Ps i am very new to coding, Thanks

Here is my code:-


const int stepPin = 3;
 int dirPin = 4; 
 int dirButton = 2;
int stopButton = 5;
int state = HIGH;
int reading;
int previous = LOW;
int stepDelay=1000;
int stop = HIGH;
long time = 0;
long debounce = 200;


int customDelay,customDelayMapped; // Defines variables
 
void setup() {
  // Sets the two pins as Outputs
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);
  pinMode(stopButton, INPUT_PULLUP);
 pinMode(dirButton, INPUT_PULLUP);

   digitalWrite(dirPin,HIGH); //change the rotation direction HIGH for clockwise and LOW for anticlockwise
}
void loop() {
   reading = digitalRead(dirButton);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    time = millis();    
  }
  
    stop = digitalRead(stopButton);
if (stop == LOW) {

  


 int customDelay = analogRead(A0); // Reads the potentiometer
  int newCustom = map(customDelay, 0, 1023, 400,15000); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (300 to 4000)
  return newCustom;  

}
  
  

  digitalWrite(dirPin, state);

  previous = reading;

digitalWrite(stepPin, HIGH);
delayMicroseconds(stepDelay);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepDelay);
  
  customDelayMapped = speedUp(); // Gets custom delay values from the custom speedUp function
  // Makes pules with custom delay, depending on the Potentiometer, from which the speed of the motor depends
  digitalWrite(stepPin, HIGH);
  delayMicroseconds(customDelayMapped);
  digitalWrite(stepPin, LOW);
  delayMicroseconds(customDelayMapped);
}
// Function for reading the Potentiometer
int speedUp() {
  int customDelay = analogRead(A0); // Reads the potentiometer
  int newCustom = map(customDelay, 0, 1023, 400,15000); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (300 to 4000)
  return newCustom;  
}

You need to detect when the button becomes pressed rather than when it is pressed
See the StateChangeDetection example in the IDE

Could you right-click and select "Format Document", then check all the indents, spaces, comma's, everything. Make the text of the code look good. You do that for yourself, to easier spot bugs.

You can give all the variables for the pin numbers a 'const'. You can also add "Pin" to their names.

const int stepPin       = 3;
const int dirPin        = 4;
const int dirButtonPin  = 2;
const int stopButtonPin = 5;

If you do something with millis(), please use "unsigned long" instead of "long".

Can you give the variables and functions meaningful names ? The "previous" does not tell what it is for and the SpeedUp() is actually a speed control.

Why do you make two steps in the loop() ?

There is a "return newCustom;" in the loop(), that's not right.

If you can describe in a logical way what the sketch should do, then half the sketch is already written.

You started three topics, are they the same ?

With out of range speed settings. To say it diplomatic. Setting the speed to out of range values which make the stepper-motor stand still is a very unusual way to stop a stepper-motor.

My recommendation is that you restructure your code in a way that
each part of the code does one senseful thing and is inside one function.

  • creating step-pulses
  • checking the button
  • reading in the potentiometer and setting the stepmotors speed.

If your code is organised and structured in this way it will become easy to add a function

stepperShallRun = checkToggleSwitch();

which will on
first press returns true
second press returns false
third press returns true
fourth press returns false
.....

and you code is checking

if (stepperShallRun == true) {
  createStepPulses();
}
else {
  // do nothing
}

Here is a WOKWI-simulation that demonstrates the principle

best regards Stefan

Hi all I am completely new to Arduino code and don't really have a clue. All I know is that when I copyed and pasted the section of code :-

 int customDelay = analogRead(A0); // Reads the potentiometer
  int newCustom = map(customDelay, 0, 1023, 400,15000); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (300 to 4000)
  return newCustom;  

after the line:-

stop = digitalRead(stopButton);
if (stop == LOW)

and then bress the button it stops and locks the motor (which is what I want) but when i release the button the motor runs again. I just want it to stay locked when I release the button and then on pressing again to continue running (toggle the motor.

I guess I am hoping someone could give me a bit of code to paste into my code that would be able to make it work. I am slowly learning how to code but at the moment I am really struggling to understand how to do even simple tasks!

This forum is working this way:
You can ask questions for specific details. If you don't understand the suggestion just ask about exact that detail that you do not understand.

The code that I posted in the wokwi-simulation
as direct code here

/* explanation of the most important details:

  realising a functionality where using a momentary push-button
  acts as a toogle-switch
  push       => activated  push again => DE-activated
  push again => activated  push again => DE-activated
  etc. etc. ...
  This needs quite some code. This code is well organised in MULTIPLE functions
  where each function is a senseful SUB-program

  This is the reason why function loop looks super-short:

  void loop () {
    activationMode = GetToggleSwitchState(); // must be executed all the time
    printActionState(activationMode);
    
    if (activationMode == true) {
      blinkOnBoardLED();
    }
    else {
      digitalWrite(LED_BUILTIN, LOW); // switch off LED
    }
  }

  Huh that's all? No. Of course there is more (below function loop)

  If you just want to APPLY the functionality to your own code
  replace the code inside function    void my_Action()
  with your own code that shall only be  executed if you activated execution
  with the momentary push-button

  I recommend to RENAME the function my_Action() to a SELF-explaining name
  This will cause a compiler-error which shows you where you have to rename
  the function-call of this function too (this is inside function execute_if_Active
  If you want to understand how it works read and analyse the rest of the functions.

*/


#define ProjectName "Toggle Button demonstration"

// define IO-states for inputs with pull-up-resistors
// pull-up-resistors invert the logig
#define unPressed HIGH
#define pressed   LOW

const byte ToggleButtonPin = A0;

bool activationMode = false;
unsigned long myCounter = 0;
unsigned long MyBlinkTimer = 0;


void setup() {
  Serial.begin(115200); // adjust baudrate in the serial monitor to match the number
  Serial.println( F("Setup-Start") );
  printFileNameDateTime();

  pinMode (LED_BUILTIN, OUTPUT);  // used for indicating logging active or not
  digitalWrite(LED_BUILTIN, LOW);
  // wire button between IO-pin and GND
  // Pull-up-resistor inverts the logic
  // unpressed: IO-pin detects HIGH
  // pressed:   IO-Pin detects LOW
  pinMode(ToggleButtonPin, INPUT_PULLUP);
  MyBlinkTimer = millis();
}


void loop () {
  activationMode = GetToggleSwitchState(); // must be executed all the time
  printActionState(activationMode);
  
  if (activationMode == true) {
    blinkOnBoardLED();
  }
  else {
    digitalWrite(LED_BUILTIN, LOW); // switch off LED
  }
}


bool GetToggleSwitchState() {
  // "static" makes variables persistant over function calls
  static bool toggleState     = false;
  static bool lastToggleState = false;

  static byte buttonStateOld = unPressed;
  static unsigned long buttonScanStarted  =  0;
  unsigned long buttonDebounceTime = 50;
  static unsigned long buttonDebounceTimer;

  byte buttonStateNew;

  if ( TimePeriodIsOver(buttonDebounceTimer, buttonDebounceTime) ) {
    // if more time than buttonDebounceTime has passed by
    // this means let pass by some time until
    // bouncing of the button is over
    buttonStateNew = digitalRead(ToggleButtonPin);

    if (buttonStateNew != buttonStateOld) {
      // if button-state has changed
      buttonStateOld = buttonStateNew;
      if (buttonStateNew == unPressed) {
        // if button is released
        toggleState = !toggleState; // toggle state-variable
      } // the attention-mark is the NOT operator
    }   // which simply inverts the boolean state
  }     // !true  = false   NOT true  is false
  //       !false = true    NOT false is true
  return toggleState;
}

// this is the function that is called
// inside function execute_if_Active()
void blinkOnBoardLED() {

  if ( TimePeriodIsOver(MyBlinkTimer, 500) ) {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN) ); // read state of LED-output and set to invertetd state
  }
}


// helper-function 
void printFileNameDateTime() {
  Serial.print( F("File   : ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("Date   : ") );
  Serial.println( F(__DATE__) );
  Serial.print( F("Project: ") );
  Serial.println( F(ProjectName) );
}

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}


// a function that checks if a variabe has CHANGED its state
// only in case of a CHANGE of the variable a message is printed 
// ONE single time
void printActionState(boolean p_IsActivated) {
  static boolean lastIsActivated;
  
  if ( p_IsActivated != lastIsActivated) {
    // only if state of parameter p_logIsActivated has changed
    if (p_IsActivated) {
      Serial.println();
      Serial.println("start executing LED blinks");
      Serial.println();
      //digitalWrite(LED_BUILTIN, HIGH);
    }
    else { // not activated
      Serial.println();
      Serial.println("stopp executing LED is switched off");
      Serial.println();
      //digitalWrite(LED_BUILTIN, LOW);
    }
    lastIsActivated = p_IsActivated; // update variable lastSDlogActive
  }  
}

You should read through this code line by line.
You don't have to understand each line at the first read.

Just get an overview. Then ask specific questions. Best way as suggestions what a certain part of the code does.

Example: You want to have a toggle-switch functionality from a momemtary push-button.
So look through the code above and ask
"am I right in assuming that the code starting with ......" is that part of the code that does the toggle-switching?

I'm very sure that you will find this part of the code.
And from there you can ask more questions best way always with making a suggestion or with an attempt to modify your code.

This attempt can have as many errors as ever possible. The important part is to start thinking yourself.

If the modified code does not compile or does not work as expected post a new question.

You are asking for a functionality toggleswitch out of a momentary pushbutton which is somehow advanced. This means you have some new things to learn.

best regards Stefan

I have literally spent the last 2 weeks trying to find solutions and answers as to how to sort out what I thought was a relatively simple task of controlling a stepper motor to move from side to side at a variable speed and stop and start!

This has been one of the most challenging and frustrating things I have ever done!

I have build a robot and appeared on Robot wars.
I have made various programs with visual basics back in the day for the PC.
I have a city and guilds in electronics.
I worked for many years as a mechanic.
I understand logic and think logically.

Despite all of this I have still failed to find a way to achieve my goal!

What I have learned about Arduino code is that its like wanting to write a letter to a French person but you don't speak French!

So you either learn French or you grasp around in the dark for hours and hours and now and occasionally find the odd bit that works, or ask someone to help you who know the language! But as I have found on this forum they presume you know much of the language already! but of course, you don't!

I simply want to get by and not learn the whole language and sadly I have come to realise that it is not for me!

French teachers expect you to listen, learn, and do homework. I am quite sure billions of people learned French this way. Nothing different here. You posted similar topics on 11 September and 19 September. I gave to you a full sketch after seeing that you multi-posted the same question and expressed no desire to learn. Did you listen to (read) any of it? Here you are, asking the same question. If all you want is copy/paste code, why ask any questions. Just copy/paste from a working project and do what is for you.

By the way, here (for the third time) is how I stop a stepper:

void loop() {
  int speed = map(analogRead(A0), 0, 1024, -2000, 2000);

  if (speed <= -deadband) { // not in the deadband
    dir = 0; // counterclockwise
    motorStep(dir, speed);
  }

  if (speed >= deadband) { // not in the deadband
    dir = 1; // clockwise
    motorStep(dir, speed);
  }
  if (abs(speed) < deadband) // in the deadband - stop the motor
    motorStop(speed);
}

void motorStop(int speed) { // stop the motor when potentiometer is in the deadband
  digitalWrite(stepPin, LOW);
  delayMicroseconds(2000);
  digitalWrite(stepPin, LOW);
  delayMicroseconds(2000);
}

First of all thank you for your solution, but here the thing I don't know where in the code to paste it, I have tried putting it in the void loop and when I click verify it says
" Compilation error: 'deadband' was not declared in this scope" so I then put "int deadband; " at the top at the beginning with all the other ints etc.
click verify it says "Compilation error: 'dir' was not declared in this scope
so I do the same with that "int dir;" at the top
click verify it says "Compilation error: 'motorStep' was not declared in this scope"
so I do the same with that "int motorStep;" at the top
click verify it says "Compilation error: 'motorStep' cannot be used as a function"
and then I am thinking have I put the code in the wrong place, or I try deleting a few of the brackets "{" either way I go on to spend a long time again grasping in the dark trying to find a way forward but hitting brick walls ( this is of course due to the fact I have very limited knowledge of the subject) and even if I some how by total accident were to stumble on getting it to work with verify I have no idea how I would then link my button to trigger it (perhaps I would put all of it after " stop = digitalRead(stopButton);
if (stop == LOW) {

I just dont know

The next sentence is written in big bold uppercase letters. The meaning is not shouting.
The only meaning is emphasising. You can have a specialised tutorial specific to your application if you

CHANGE the style of asking.

This will make you

FINISH the project FASTER

Your momentary style seems to by trying this trying that for 5 hours
The more effective way is to learn 1 hour and then this part works.

Again the big bold uppercase letters are just meant as emphasizing.

I want to give some examples:

you wrote

This means you already have understood variables must be decared at the top of the program.

Now your specific question could be

What is the meaning of the error:

There is an answer that directy solves this issue
This answer could be given if you post this new version of your actual code = the complete sketch.

Then the more generalised answer is:
read part one of this tutorial

and read part 15

Working through the complete tutorial will take maybe 5 to 8 hours.
Compare the 8 hours to the number of hours that you have tried to be quick and all that happened was slowing down.

best regards Stefan

@sophiekatie123 - @StefanL38 has good instructions that should be followed, just like all good instructions. You will benefit.

Concerning the specific errors - They are caused by only using only the portion of sketch in this thread showing how I would stop a stepper motor (taken from the full sketch, which was given to you weeks ago) responding to the title "Simple stop button..." Refer back to the full sketch for reading and understanding... after you follow the instructions of Stefan. Your solution is close, and only needs a little more understanding.

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