Toggle motor direction with momentary switch? 28BYJ-48 Stepper

Hello, total beginner here... I'm trying to control a stepper motor (5V version of 28BYJ-48). This code runs the motor and it works fine, but what I'm looking to do is to add a momentary push button that can toggle between rotating CCW and CW, because now it only turns CCW. I'm assuming it's quite simple but as a total beginner I have really no clue where to get started.

Here is my code so far, simply just rotates the motor CCW at 2ms between each half-step

int in1 =  8; //ardunio pin  8 is now assigned to in1 on the ULN2003 driver
int in2 =  9; //arduino pin  9 is now assigned to in2 on the ULN2003 driver
int in3 = 10; //arduino pin 10 is now assigned to in3 on the ULN2003 driver
int in4 = 11; //arduino pin 11 is now assigned to in4 on the ULN2003 driver

#define x 2000 //"x" now means whatever number inserted here. 
// In this case, the microsecond delay between each step. 
// (2000 microseconds equals 2ms)


void setup() {
  pinMode(in1, OUTPUT);  //pin "in1" is now an output pin
  pinMode(in2, OUTPUT);  //pin "in2" is now an output pin
  pinMode(in3, OUTPUT);  //pin "in3" is now an output pin
  pinMode(in4, OUTPUT);  //pin "in4" is now an output pin
}


void loop() {
  
  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);
  
  delayMicroseconds(x);
  
  digitalWrite (in1, HIGH);
  digitalWrite (in2, HIGH);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, HIGH);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, HIGH);
  digitalWrite (in3, HIGH);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  digitalWrite (in3, HIGH);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  digitalWrite (in3, HIGH);
  digitalWrite (in4, HIGH);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, HIGH);

  delayMicroseconds(x);

  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, HIGH);

  delayMicroseconds(x);
  
}

What have you tried ?

Welcome to the Arduino forum. Thanks for posting your code correctly the first time. Very rare experience!

To begin, you need to make two different functions. One for CCW and one for CW.
Begin by changing the line "void loop() {" to "void CCW() }".

Then make a new function
"void loop() {
CCW();
} "

Without the ", of course. Now you have the same program operation, but are calling a function to make the stepper go CCW.

That all leave you the opportunity to code the mirror image of the CCW function and call it CW.

Look at all the sample programs that come with the IDE. One or more will let you see how a push button switch can be tested for. That logic and a bit more will let your stepper program switch between CCW and CW direction when the switch gets pressed.
Good luck
Paul

Thank you for a quick response! So, firstly I actually just tried to make a simple code to turn on and off the stepper with a momentary push button. I couldn't find any specific code for that so I kind of experimented somewhat with a led toggle switch code I found. But the problem is what I ended up getting was a button that gave me one step per button push instead, then I ended up here.
What I'd love to find out is what can I add to this "base code" to enable a push button that allows me to run the motor, then push the button, and the motor will run, just the opposite way.

How is this? Am I on the right track?

int in1 =  8; //ardunio pin  8 is now assigned to in1 on the ULN2003 driver
int in2 =  9; //arduino pin  9 is now assigned to in2 on the ULN2003 driver
int in3 = 10; //arduino pin 10 is now assigned to in3 on the ULN2003 driver
int in4 = 11; //arduino pin 11 is now assigned to in4 on the ULN2003 driver

int button = 2; //arduino pin 2 is set to be the push button signal pin

#define x 2000 //"x" now means whatever number inserted here. 
// In this case, the microsecond delay between each step. (2000 microseconds equals 2ms)


void setup() {
  pinMode(in1, OUTPUT); //pin "in1" is now an output pin
  pinMode(in2, OUTPUT); //pin "in2" is now an output pin
  pinMode(in3, OUTPUT); //pin "in3" is now an output pin
  pinMode(in4, OUTPUT); //pin "in4" is now an output pin

}

//CCW Rotation

void loop() {
  CCW();
  CW();
}

 void CCW(){
  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);
  
  delayMicroseconds(x);
  
  digitalWrite (in1, HIGH);
  digitalWrite (in2, HIGH);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, HIGH);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, HIGH);
  digitalWrite (in3, HIGH);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  digitalWrite (in3, HIGH);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  digitalWrite (in3, HIGH);
  digitalWrite (in4, HIGH);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, HIGH);

  delayMicroseconds(x);

  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, HIGH);

  delayMicroseconds(x);
}

// CW Rotation

void CW(){
  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, HIGH);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, HIGH);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  digitalWrite (in3, HIGH);
  digitalWrite (in4, HIGH);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  digitalWrite (in3, HIGH);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, HIGH);
  digitalWrite (in3, HIGH);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, LOW);
  digitalWrite (in2, HIGH);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, HIGH);
  digitalWrite (in2, HIGH);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);

  delayMicroseconds(x);

  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);
  
  delayMicroseconds(x);   
}

The obvious question is: does it work? First going one way and then the other.

I have yet to add the actual push button part, just wondered mostly about if this would be the correct way to begin the loop code.

void loop() {
  CCW();
  CW();
}

and then go like this:

 void CCW(){
 digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, LOW);

etc... and then

void CW(){
  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
  digitalWrite (in3, LOW);
  digitalWrite (in4, HIGH);

etc... if that made any sense? Like tell the loop to run the "void CCW" and the "void CW"?

Absolutely correct! But does it work? Have you looked at a logic table for the stepper motor so you can see the sequence of high and low pins for each step, each direction. I remember such a table when I did my Arduino kit several years ago.

Oh yeah I know that the step sequence works perfectly fine and is tuned to do half-steps for the motor. But the issue I'm kind of stuck at is how to get the actual push button to activate each of the two options. And I'd want it so that the push button can activate CCW by pressing once, then activate CW by pressing a second time, then back to CCW / CW / CCW / CW etc when pressing that one button. Then eventually I also want to add a secondary potentiometer that adds the "x" value (which is delay time per step so I can adjust the speed with the potentiometer, and the rotation with the button), but I'm first trying to figure out how to set up the button to actually activate each individual option as a "loop" so that when lets say CW is active, it runs at a loop until CCW is activated

You could use the state change detection method (and my active low state change detection) to toggle a flag. Then use the state of the flag to call either the CW or CCW function.

Here is an example to demonstrate toggling a flag with a momentary push button switch. The switch is wired to ground and an input set to pinMode INPUT_PULLUP (active LOW input).

// by C Goulding aka groundFungus

#define CCW false
#define CW true 

const byte  buttonPin = 12;    // the pin to which the pushbutton is attached
const byte ledPin = 13;       // the pin to which the LED is attached

bool buttonState = 0;         // current state of the button
bool lastButtonState = 0;     // previous state of the button

bool directionFlag = CW;

void setup()
{
   // initialize the button pin as a input with internal pullup enabled
   pinMode(buttonPin, INPUT_PULLUP);
   // initialize the LED as an output:
   pinMode(ledPin, OUTPUT);
   // initialize serial communication:
   Serial.begin(9600);
}

void loop()
{
   static unsigned long timer = 0;
   unsigned long interval = 50;  // check switch 20 times per second
   if (millis() - timer >= interval)
   {
      timer = millis();
      // read the pushbutton input pin:
      buttonState = digitalRead(buttonPin);
      // compare the new buttonState to its previous state
      if (buttonState != lastButtonState)
      {
         if (buttonState == LOW)
         {
            // if the current state is LOW then the button
            // went from off to on:
            digitalWrite(ledPin, !digitalRead(ledPin)); // toggle the output
            directionFlag = !directionFlag;
            Serial.print("direction flag = ");
            Serial.println(directionFlag ? "CW" : "CCW");
         }
      }
      // save the current state as the last state,
      //for next time through the loop
      lastButtonState = buttonState;
   }
}

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