Stepper motors and push buttons

#include <AccelStepper.h>
#include <Bounce2.h>

#define NUM_BUTTONS 2

const int dirPin1 = 4;
const int stepPin1 = 5;
const int dirPin2 = 6; // Pins for the second stepper motor
const int stepPin2 = 7;
const int motorInterfaceType = 1;

bool start1 = false;
bool start2 = false;
bool movingFirstStepper = false;
bool movingSecondStepper = false;

const int buttonPin[NUM_BUTTONS] = {2, 3};

AccelStepper myStepper1 = AccelStepper(motorInterfaceType, stepPin1, dirPin1);
AccelStepper myStepper2 = AccelStepper(motorInterfaceType, stepPin2, dirPin2);

Bounce2::Button button[NUM_BUTTONS] = {Bounce2::Button()};

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

  for (byte i = 0; i < NUM_BUTTONS; i++)
  {
    button[i].attach(buttonPin[i], INPUT_PULLUP);
    button[i].setPressedState(LOW);
    button[i].interval(5);
  }

  myStepper1.setMaxSpeed(1000); // Set a higher speed for the first stepper motor
  myStepper1.setAcceleration(300); // Set acceleration for the first stepper motor
  myStepper2.setMaxSpeed(1000); // Set a higher speed for the second stepper motor
  myStepper2.setAcceleration(300); // Set acceleration for the second stepper motor
}

void loop()
{
  for (byte i = 0; i < NUM_BUTTONS; i++)
  {
    button[i].update();

    if (button[0].fell())
    {
      Serial.println("Start button pressed");
      start1 = true;
    }

    if (button[1].fell())
    {
      Serial.println("Stop button pressed");
      start1 = false;
      myStepper1.stop();
      myStepper2.stop();
      myStepper1.setCurrentPosition(0);
      myStepper2.setCurrentPosition(0);
    }
  }

  if (start1)
  {
    if (!movingFirstStepper)
    {
      myStepper1.move(200);
      movingFirstStepper = true;
    }

    if (myStepper1.distanceToGo() == 0 && !movingSecondStepper)
    {
      myStepper2.move(100);
      movingSecondStepper = true;
    }

    myStepper1.run();
    myStepper2.run();

    if (movingFirstStepper && myStepper1.distanceToGo() == 0 && movingSecondStepper && myStepper2.distanceToGo() == 0)
    {
     myStepper2.moveTo(0);
      movingFirstStepper = false;
      movingSecondStepper = false;
    }
  }
}

I already have created more or less the code I desire to run. My only problem as of right now is that I desire stepper2 to move back to its 0 position from the 100 steps before stepper1 engages again moving 200 steps. If anyone could solve my problem and write the code or explain what I could change I would appreciate it as I have been stuck for hours...

You are using an array for your 2 button objects. Why are you not using an array for your 2 stepper objects?

Why are these not also arrays?

Would that make any difference in the overall result that I want? If I am being honest I just started coding and lost my patience the more I added to the code

Maybe.

Not using arrays means you have needed to write 2x as much code, increasing the chances of making an error by 2x.

What you have coded here is a if-condition that uses the logical and operator.

Only in case
each partial condition as there are
movingFirstStepper == true
and
myStepper1.distanceToGo() == 0 // stepper1 has finished his 200 steps
and
movingSecondStepper == true
and
myStepper2.distanceToGo() == 0 // stepper2 has finished his 100 steps

which means the condition all in all becomes only true
if your stepper1 has finished his 200 steps

You will have to write code with two different conditions
one for stepper1
and one for stepper 2

seems like you need a sequencer. you're already doing something similar within the start1 condition but could make it more explicit.

instead of using an if statement, add a state variable indicating what it being done, including an IDLE and START states
and use a switch statement to invoke the code for each state

the IDLE state does nothing. Pressing a button changes state to START which invokes myStepper1.move(200); and set state to the next state, MOVE_1, for example.

the MOVE_1 state waits for motor 1 to reach it's destination, starts the 2nd motor moving and advances to the next state, MOVE_2

the MOVE_2 state is similar to MOVE_1, waiting for the 2nd motor to reach it's desitination. When it does, sounds like you want the 2nd motor to move back to its original position, myStepper2.move(-100);. invoke those commands and advance to the next state, RETURN_2.

the RETURN_2 state is similar to the others, waiting for the 2nd motor to reach it's destination. When it does, it sounds like you want to start the 1st motor moving again and can advance to the MOVE_1 state

pressing a button could invoke some commands to stop the motors and enter a state that waits for both motors to reach their destinations and move the IDLE state

Could you show me how you would add the extra condition?

I have not use the state variable before, could you please write an example line or where you believe I should correct the code?

look this over
had to test with different button code

i realized that i didn't handle the 2nd button. Hopefully this is clear enough for you to handle it

// stepper motor sequencer

# include <AccelStepper.h>
# include <Bounce2.h>

const int dirPin1  = 4;
const int stepPin1 = 5;
const int dirPin2  = 6;
const int stepPin2 = 7;

bool start1 = false;
bool start2 = false;
bool movingFirstStepper = false;
bool movingSecondStepper = false;

const int motorInterfaceType = 1;
AccelStepper myStepper1 = AccelStepper (motorInterfaceType, stepPin1, dirPin1);
AccelStepper myStepper2 = AccelStepper (motorInterfaceType, stepPin2, dirPin2);

const byte PinButs [] = {2, 3};
const int NUM_BUTTONS = sizeof(PinButs);

Bounce2::Button button[NUM_BUTTONS] = {Bounce2::Button ()};
Bounce button [NUM_BUTTONS] = {Bounce2::Button ()};

enum { S_IDLE, S_START, S_MOVE1, S_MOVE2, S_RETURN2 };
int state = S_IDLE;

// -----------------------------------------------------------------------------
void loop ()
{
    for (byte i = 0; i < NUM_BUTTONS; i++) {
        button[i].update();

        if (button[0].fell ()) {
            Serial.println ("Start button pressed");
            state = S_START;
        }

        if (button[1].fell ()) {
            Serial.println ("Stop button pressed");
            start1 = false;
            myStepper1.stop ();
            myStepper2.stop ();
            myStepper1.setCurrentPosition (0);
            myStepper2.setCurrentPosition (0);
        }
    }

    switch (state) {
    case S_IDLE:                // do nothing
        break;

    case S_START:
        myStepper1.move (200);
        state = S_MOVE1;
        Serial.println ("  S_MOVE1");
        break;

    case S_MOVE1:               // wait for motor 1 to reach destination
        myStepper1.run ();
        if (myStepper1.distanceToGo () == 0)  {
            myStepper1.move (200);
            state = S_MOVE2;
            Serial.println ("  S_MOVE2");
        }
        break;

    case S_MOVE2:               // wait for motor 2 to reach destination
        myStepper2.run ();
        if (myStepper2.distanceToGo () == 0)  {
            myStepper1.move (-200);
            state = S_RETURN2;
            Serial.println ("  S_RETURN2");
        }
        break;

    case S_RETURN2:             // wait for motor 2 to return
        myStepper2.run ();
        if (myStepper2.distanceToGo () == 0)  {
            state = S_IDLE;                 // ??
            Serial.println ("  S_IDLE");
        }
        break;
    }
}

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

    for (byte i = 0; i < NUM_BUTTONS; i++) {
        button[i].attach          (PinButs[i], INPUT_PULLUP);
        button[i].setPressedState (LOW);
        button[i].interval        (5);
    }

    myStepper1.setMaxSpeed     (1000);
    myStepper1.setAcceleration (300); 

    myStepper2.setMaxSpeed     (1000);
    myStepper2.setAcceleration (300);
}

Not sure if this description describes all details,

@calisifer
You should write a posting where you describe the movements in normal words without any code.

moving 200 steps sounds like one complete rotation = 360°
moving 100 steps sounds like half a rotation = 180°

Is this correct?

So my understanding of what the two steppermotors shall do is
stepper1 rotates 200 steps
at the same time as stepper1 starts to rotate
stepper2 starts to rotate 100 steps

when stepper1 has reached his target (= 200 steps)
stepper2 shall rotate back 100 steps

when stepper2 has finished rotating back 100 steps
stepper2 shall do his next 200 steps.

It is unclear if these are the movements that you want to have.
So please confirm or correct this description.

When you have posted this description the correct code can be written.

Hey Stefan,
Thanks for being willing to help. The description would be that I desire the first button to do a full rotation and once it reaches that full rotation only then will the second stepper do a 180° rotation which should go back to its original position and then the first stepper can rotate 360° again.

image

So the two stepper run never at the same time

stepper 1 full rotation
stepper 2 half rotation forward
stepper 2 half rotation back

repeat

You can code this as pure linear sequence

You are right, that is the full sequence that I am working on. How could I implement linear sequence to achieve it?

Thank you so much for the diagram, that is exactly what I intend to do with the arduino.

by linear sequence do you mean something like the following. the sequence is started and runs to completion each time the button is pressed. Since the sequence runs to completion, it blocks, buttons aren't checked and the sequence can't be interrupted

void loop ()
{
    for (byte i = 0; i < NUM_BUTTONS; i++) {
        button[i].update ();

        if (button[0].fell ()) {
            Serial.println ("Start button pressed");

            myStepper1.move (200);
            while (myStepper1.distanceToGo () != 0)
                myStepper1.run ();

            myStepper2.move (100);
            while (myStepper2.distanceToGo () != 0)
                myStepper2.run ();

            myStepper2.move (0);
            while (myStepper2.distanceToGo () != 0)
                myStepper2.run ();

        if (button[1].fell ()) {
            Serial.println ("Stop button pressed");
            myStepper1.stop ();
            myStepper2.stop ();
            myStepper1.setCurrentPosition (0);
            myStepper2.setCurrentPosition (0);
        }
    }
}

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