How to add start stop on my code

hello, I'm having trouble here, I only have 1 pin remaining (13) and I need to have a start stop button. Im thinking that the button that will be added can both start the code to run my switch case and when pushed again, it will pause the machine, and when pushed again, it will just resume its last case state, how it can be done?

#include <Stepper.h>

int stepsPerRevolution = 2048;
int motSpeed = 50;
int dt = 500;
int state_fam = 0;

const byte button1Pin = 10;
const byte button2Pin = 11;
const byte button3Pin = 12;
const byte button4Pin = 13;

int motDir = 1;

Stepper myStepper1(stepsPerRevolution, 2, 4, 3, 5);
Stepper myStepper2(stepsPerRevolution, 6, 8, 7, 9);

void setup() {
  Serial.begin(115200);
  myStepper1.setSpeed(motSpeed);
  myStepper2.setSpeed(motSpeed);
  pinMode(button1Pin, INPUT_PULLUP);
  pinMode(button2Pin, INPUT_PULLUP);
  pinMode(button3Pin, INPUT_PULLUP);
  myStepper1.setSpeed(motSpeed);
  myStepper2.setSpeed(motSpeed);


  while (digitalRead(button2Pin) == HIGH) {
    myStepper2.step(motDir * -1);
    delay(50);
  }

}

byte runStepper1 = false;
byte runStepper2 = false;


void loop() {
  Serial.print("state: ");
  Serial.println(state_fam);

  switch (state_fam) {
    case 0:
      runStepper1 = true;
      myStepper1.step(motDir * 1);

      if (digitalRead(button1Pin) == LOW) {
        runStepper1 = false;
        state_fam = 1;
      }

      break;

    case 1:
      runStepper2 = true;
      myStepper2.step(motDir * 1);

      if (digitalRead(button2Pin) == LOW) {
        runStepper2 = false;
        state_fam = 2;
      }

      break;

    case 2:
      runStepper2 = true;
      myStepper2.step(motDir * -1);

      if (digitalRead(button3Pin) == LOW) {
        runStepper2 = false;
        state_fam = 0;
      }
      break;
  }
  delay(50);
}

The analog pins work as digital inputs and outputs.

const byte buttonStartStop = A1;
... 

pinMode(buttonStartStop,INPUT_PULLUP);
...

if(digitalRead(buttonStartStop) ==LOW){...

and use the stateChangeDetection example code to set and reset a flag that you could use to inhibit other code.

2 Likes

look this over (untested)

#include <Stepper.h>

int stepsPerRevolution = 2048;
int motSpeed = 50;
int dt = 500;
int state_fam = 0;
int state_fam_old;


const byte button1Pin = 10;
const byte button2Pin = 11;
const byte button3Pin = 12;
const byte button4Pin = 13;
      byte but4State;

int motDir = 1;

Stepper myStepper1(stepsPerRevolution, 2, 4, 3, 5);
Stepper myStepper2(stepsPerRevolution, 6, 8, 7, 9);

void setup() {
    Serial.begin(115200);
    myStepper1.setSpeed(motSpeed);
    myStepper2.setSpeed(motSpeed);
    pinMode(button1Pin, INPUT_PULLUP);
    pinMode(button2Pin, INPUT_PULLUP);
    pinMode(button3Pin, INPUT_PULLUP);

    pinMode(button4Pin, INPUT_PULLUP);
    but4State = digitalRead(button4Pin);

    myStepper1.setSpeed(motSpeed);
    myStepper2.setSpeed(motSpeed);

    while (digitalRead(button2Pin) == HIGH) {
        myStepper2.step(motDir * -1);
        delay(50);
    }
}

byte runStepper1 = false;
byte runStepper2 = false;

const int Stop = 5;

void loop() {
    Serial.print("state: ");
    Serial.println(state_fam);

    switch (state_fam) {
    case 0:
        runStepper1 = true;
        myStepper1.step(motDir * 1);

        if (digitalRead(button1Pin) == LOW) {
            runStepper1 = false;
            state_fam = 1;
        }

        break;

    case 1:
        runStepper2 = true;
        myStepper2.step(motDir * 1);

        if (digitalRead(button2Pin) == LOW) {
            runStepper2 = false;
            state_fam = 2;
        }
        break;

    case 2:
        runStepper2 = true;
        myStepper2.step(motDir * -1);

        if (digitalRead(button3Pin) == LOW) {
            runStepper2 = false;
            state_fam = 0;
        }
        break;

    case Stop:
        break;
    }

    byte but = digitalRead (button4Pin);
    if (but4State != but)  {
        but4State = but;
        delay (20);

        if (LOW == but)  {
            if (Stop == state_fam)
                state_fam = state_fam_old;
            else  {
                state_fam_old = state_fam;
                state_fam = Stop;
            }
        }
    }

    delay(50);
}
2 Likes

thanks man, will look into it

its working, thank you

@gcjr:

what is so hard about explaining your modificated sketch?
Do your fingers hurt if you type 50 to 200 additional letters?

@shigs555

you did not explicitly write what microcontroller you are using.
From the IO-pins used it is very likely that you use an arduino uno.
As user @DaveX already mentioned you could use the pins A0, A1, A2, A3, A4, A5 as digital pins too.

So this would enable to have a separate start and a stop button and then there would be still 4 IO-pins left free for whatever you like.

You posted your sketch and a wokwi simulation.
Sure I can read the code I can watch the simulation.
Non-theless I highly prefer to know the backround of a code.
What is the purpose of your device?

Pretty often knowing the real thing enables to make new suggestions for solutions.
Sometimes much more elegant then the chosen one.

Anyway to explain what GCJR-code does

He defined the IO-pin 13 as INPUT_PULLUP

Then below your switch-case-break-statement he added the start-stop functionality.

Such a functionality works this way

You define a second variable "state_fam_old" to memorise the state your code was in in the moment of stopping.
This state can be
case 0:
case 1:
case 2:
case stop: (which is case "5"

This means if you press the button after stopping the code continues with the same state as before stopping.

Here is the re-modificated sketch as a WOKWI-Simulation

sketch

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

#include <Stepper.h>

int stepsPerRevolution = 2048;
int motSpeed = 50;
int dt = 500;
int state_fam = 0;
int state_fam_old;


const byte button1Pin = 10;
const byte button2Pin = 11;
const byte button3Pin = 12;
const byte StartStopPin = 13;

const byte pressed = LOW; // define a self-explaining constant
byte lastBut4State;

int motDir = 1;

Stepper myStepper1(stepsPerRevolution, 2, 4, 3, 5);
Stepper myStepper2(stepsPerRevolution, 6, 8, 7, 9);

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  myStepper1.setSpeed(motSpeed);
  myStepper2.setSpeed(motSpeed);
  pinMode(button1Pin, INPUT_PULLUP);
  pinMode(button2Pin, INPUT_PULLUP);
  pinMode(button3Pin, INPUT_PULLUP);

  pinMode(StartStopPin, INPUT_PULLUP);
  lastBut4State = digitalRead(StartStopPin);

  myStepper1.setSpeed(motSpeed);
  myStepper2.setSpeed(motSpeed);
  
  Serial.println("print button 2 to start");
  while (digitalRead(button2Pin) == HIGH) {
    delay(50);
  }
  Serial.println("button2Pin pressed => start loop()");
}

byte runStepper1 = false;
byte runStepper2 = false;

const int Stopped = 5;

void loop() {
  //Serial.print("state: ");
  //Serial.println(state_fam);
  dbgc("ToL",state_fam);

  switch (state_fam) {
    case 0:
      runStepper1 = true;
      myStepper1.step(motDir * 1);

      if (digitalRead(button1Pin) == pressed) {
        Serial.println("button1Pin pressed => stop stepper1");
        Serial.println("rotating stepper2 CW");
        runStepper1 = false;
        state_fam = 1;
      }
      break;

    case 1:
      runStepper2 = true;
      myStepper2.step(motDir * 1);

      if (digitalRead(button2Pin) == pressed) {
        Serial.println("button2Pin pressed change to state 2=rotate stepper2 CCW");
        runStepper2 = false;
        state_fam = 2;
      }
      break;

    case 2:
      runStepper2 = true;
      myStepper2.step(motDir * -1);

      if (digitalRead(button3Pin) == pressed) {
        Serial.println("button3Pin pressed changing to state 0");
        runStepper2 = false;
        state_fam = 0;
      }
      break;

    case Stopped:
      break;
  }

  byte actualButState = digitalRead (StartStopPin); // read in button for start/stop
  if (lastBut4State != actualButState)  {           // check if logic state has changed
    lastBut4State = actualButState;                 // update variable lastBut4State
    delay (50); // wait a short moment for debouncing 

    // check if Start-Stop-Button is pressed
    if (actualButState == pressed)  {
      // when Start-Stop-Button is pressed

      // check if code is in mode "Stopped"
      if (state_fam == Stopped)
        // when code IS in mode Stopped 
        state_fam = state_fam_old; // continue through switching to the mode before stopping
      else  { // = a stepper is running
        state_fam_old = state_fam; // memorise the actual state
        state_fam = Stopped;       //  and change to mode Stopped
      }
    }
  }

  delay(50);
}

best regards Stefan

i leave it to you to provide the explanation

sorry for the confusion sir

well the background of my device is a semi automatic presser

where initially stepper 2 will reverse to hit limitswitch 3

to stop stepper 2 and run stepper 1

now when stepper 1 hit limit switch 1

it will stop the stepper 1(which it holds now the limit switch 1) and run stepper 2 forward which also releases limit switch 3

if stepper 2 hit limit switch 2, stepper 2 will reverse

now my problem is that when stepper 2 hit limit switch 3, it immediately run my state 1 because my limit switch1 is being held.

how to fix it? im thinking i should cancel limit switch 1 when is was being pressed but I cant do it

heres the link STATE MACHINE void setup home with pause resume - Wokwi ESP32, STM32, Arduino Simulator

#include <Stepper.h>

int stepsPerRevolution = 2048;
int motSpeed = 50;
int dt = 500;
int state_fam = 0;
int state_fam_old;


const byte limit1Pin = 10;
const byte limit2Pin = 11;
const byte limit3Pin = 12;
const byte button4Pin = 13;
      byte but4State;

int motDir = 1;

Stepper myStepper1(stepsPerRevolution, 2, 4, 3, 5);
Stepper myStepper2(stepsPerRevolution, 6, 8, 7, 9);

void setup() {
    Serial.begin(115200);
    myStepper1.setSpeed(motSpeed);
    myStepper2.setSpeed(motSpeed);
    pinMode(limit1Pin, INPUT_PULLUP);
    pinMode(limit2Pin, INPUT_PULLUP);
    pinMode(limit3Pin, INPUT_PULLUP);

    pinMode(button4Pin, INPUT_PULLUP);
    but4State = digitalRead(button4Pin);

    myStepper1.setSpeed(motSpeed);
    myStepper2.setSpeed(motSpeed);

    while (digitalRead(limit3Pin) == HIGH) {
        myStepper2.step(motDir * -1);
        delay(50);
    }
}

byte runStepper1 = false;
byte runStepper2 = false;

const int Stop = 5;

void loop() {
    Serial.print("state: ");
    Serial.println(state_fam);

    switch (state_fam) {
    case 0:
        runStepper1 = true;
        myStepper1.step(motDir * 1);

        if (digitalRead(limit1Pin) == LOW) {
            runStepper1 = false;
            state_fam = 1;
        }

        break;

    case 1:
        runStepper2 = true;
        myStepper2.step(motDir * 1);

        if (digitalRead(limit2Pin) == LOW ) {
            runStepper2 = false;
            state_fam = 2;
        }
        break;

    case 2:
        runStepper2 = true;
        myStepper2.step(motDir * -1);

        if (digitalRead(limit3Pin) == LOW) {
            runStepper2 = false;
            state_fam = 0;
        }
        break;

    case Stop:
        break;
    }

    byte but = digitalRead (button4Pin);
    if (but4State != but)  {
        but4State = but;
        delay (20);

        if (LOW == but)  {
            if (Stop == state_fam)
                state_fam = state_fam_old;
            else  {
                state_fam_old = state_fam;
                state_fam = Stop;
            }
        }
    }

    delay(50);
}

can you post a picture ift his device.
Your explanation is still confusing me

Your code starts with

int state_fam = 0;

which does

    case 0:
        runStepper1 = true;
        myStepper1.step(motDir * 1);

how does this relate to
initially stepper 2 will reverse to hit limitswitch 3
???

You should rename your states from 0,1,2,stopped
to meaningful names what the state is doing

The same applies to your buttons
Your description talks of limit-switches but your code talks of buttons

heres the image, its just a prototype for now thats why it is still in autocad

well i think debouncing limit switch 1 will do it

because I want to cancel limit switch 1 if it was pressed, tho Im not that familiar with writing debouncing

OK an image.
Where is stepper1 ?
where is stepper2 ?

again confusing

please write a description in normal words.
I want to emphasize: normal words

Normal words means: no coding terms just the words

  • stepper1
  • stepper2
  • limit-switch1 is attached to which stepper and gets hit when stepper rotates clockwise counter-clockwise ?
  • limit-switch2 is attached to which stepper and gets hit when stepper rotates clockwise counter-clockwise ??
  • limit-switch3 is attached to which stepper and gets hit when stepper rotates clockwise counter-clockwise ??

limit switch1 is attached to stepper 1 and gets hit when stepper 1 rotates clockwise

when limit switch 1 gets hit stepper1 will stop

and it will run stepper 2 clockwise

Limit switch 2 is attached to stepper 2 and gets hit when stepper 2 rotates clockwise

now stepper 2 will rotates counter clockwise and when it hits limit switch 3, stepper 1 should rotate clockwise

tho to pin point my problem

limit switch 3 should run stepper1 but it doesnt run

because stepper 1 is pressing limit switch 1

i need to run the stepper 1 while limit switch 1 pressed and be stopped when limit switch has been pressed again


it should be state 0 but it immediately goes to state 1 when the limit switches is like this

OK. So there are the following modes of operation:

mode 0:

  • stepper1 rotates CW checking for limit-switch1 to be pressed
  • if limit-switch1 IS pressed
    • stop stepper1
    • change to mode 1

mode1:

  • rotate stepper2 CW checking for limit-switch2 to be pressed
  • if limit-switch IS pressed
    • change to mode 2

mode 2:

  • rotate stepper2 CCW checking for limit-switch3 to be pressed
    if limit-switch3 IS pressed
    • rotate stepper1 CW
    • shall steppper2 be stopped or continue to rotate CCW?

So what does that mean?
is stepper1 doing a full rotation?

you have another mode of operation:

rotating stepper1 CW checking for limit-switch to be unpressed
if limit-switch is unpressed

    • change to mode 0

and here you should rename your state 0,1,2 to have meaningful names

meaningful names will help YOU and all other users to understand what your machine is doing

mode 0:

  • stepper1 rotates CW checking for limit-switch1 to be pressed
  • if limit-switch1 IS pressed
    • stop stepper1
    • change to mode 1

mode1:

  • rotate stepper2 CW checking for limit-switch2 to be pressed
  • if limit-switch IS pressed
    • change to mode 2

mode 2:

  • rotate stepper2 CCW checking for limit-switch3 to be pressed
    if limit-switch3 IS pressed
    • rotate stepper1 CW
    • steppper2 be stop

this

stepper 2 shoulded be stop

okay sir, will change it

thank you very much for your guidance sir