Need Help With Digital Inputs and Outputs interfering with eachother

This is my first post on the forum as I am fairly new to programming Arduino. Right now I am trying to control a stepper motor for a project while at the same time accessing input from a push button as a way for the stepper motor to know when it has reached a certain point and reset back to its original position. My issue is that the code for the push button and the motor both work separately, but once put together the digital inputs/outputs seem to interfere with each other causing both to malfunction. If anyone has any advice I'd be happy to hear.

#define stepPin 2
#define dirPin 5
const int buttonPin = 3;
int buttonState = 0;
int DIRECTION = HIGH;

void setup() {
  pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  buttonState = digitalRead(buttonPin);
  digitalWrite(dirPin,DIRECTION); // Enables the motor to move in a particular direction
  // Makes 200 pulses for making one full cycle rotation
  for(int x = 0; x < 800; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(700);    // by changing this time delay between the steps we can change the rotation speed
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(700); 
  }

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    DIRECTION = LOW;
    Serial.print("Reseting");
    delay(1000);
  } else {
    DIRECTION = HIGH;
    Serial.print("Spinning");
  }
}

Keep in mind the button likely to ‘bounce’ every time it’s pressed or released.

Your code is very simple, and it’s likely that it sees several button events each time the button changes state.

1 Like

Push button is tricky - when pushed, it is bouncing between HIGH and LOW for a long time. You need to debounce it. The best is to do it by hardware: 2 resistors and a capacitor help to stable it, making it easy for your software. You can also debounce it with software: after confirming the input went to LOW (assuming you have constant HIGH at input when not pressed), the software needs to wait until stable HIGH again.
You may want to define first how the system need to work: would 2 super-fast button pressed be accepted? In a project I did, the definition was no - half a second wait before a 2nd push was allowed.

1 Like

if i understand correctly, the stepper motor pushes a button buttonPin at the end of the for loop, which causes it to reverse its direction and spin back to initial position?

maybe place buttonState = digitalRead(buttonPin); after the for loop?

i think better way would be to use interrupts, so changing the direction will not have to wait for your for loop to finish.
i also agree with the others to debounce your push button.

2 Likes
  • shouldn't the button pin be configured as INPUT_PULLUP and the switch wired between the pin and ground, pulling the pin LOW when it is pressed

  • buttonState is not going to be affected by the motor because it is set before the motor moves but is only checked after the motor is pulsed 800 times.

  • shouldn't the button be read after the motor is moved each step to determine if the motor has reached the button

  • not clear if the button will be pressed when the motor is turning is either direction so that it can be used to reverse the motor in either direction

  • the direction can be reversed, not set to either HIGH/LOW when the button pin goes LOW, otherwise the direction would be restored immediately after the motor not longer presses the button

  • the button needs to be debounced, to prevent the direction being "reversed" multiple times. i believe a simple 20 delay would work

look this over

const byte stepPin  = 2;
const byte dirPin   = 5;
const int buttonPin = 3;

int buttonState;
int direction = HIGH;

void loop () {
    byte but = digitalRead (buttonPin);
    if (buttonState != but)  {
        buttonState = but;
        delay (20);             // debounce 

        if (LOW == but)  {
            if (HIGH == direction)
                direction = LOW;
            else
                direction = HIGH;
            digitalWrite (dirPin, direction);
        }
    }

    digitalWrite        (stepPin, HIGH);
    delayMicroseconds   (700);
    digitalWrite        (stepPin, LOW);
    delayMicroseconds   (700);
}

void setup ()
{
    pinMode (stepPin,   OUTPUT);
    pinMode (dirPin,    OUTPUT);
    digitalWrite (dirPin, direction);

    pinMode (buttonPin, INPUT_PULLUP);
    buttonState = digitalRead (buttonPin);

    Serial.begin (9600);
}
1 Like

Your original code, as posted, does:

  • run direction HIGH 800 pulses
  • check for button; if no button, do again;
  • else, if button, change direction and run 800 pulses, then check for button.

IS that what you want? It looks as though you're not looking for the code to 'learn' anything(like how far to go to get back to it's start position), just cycle from end to end, where the same button state defines both ends.
And yes, as others are pointing out, button needs to be foolproof to avoid trouble at the end points.

1 Like

Thanks so much! After studying the code I understand the usefulness of debouncing and I really appreciate your help!

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