Stepper motor control logic (Arduino UNO + Adafruit motor shield)

I am currently working on a project that consists of a ventilation vane that is actuated by a stepper motor.

Basically, the ventilation vane movement is controlled by a ON/OFF latched pushbutton switch.

When logic value at Digital Pin 2 is :

5V (HIGH) --> the arduino commands the stepper motor to take 50 steps forward.
0V (LOW) --> the arduino commands the stepper motor to take 50 steps backwards.

Here is the code :

#include <AFMotor.h>

// Connect one stepper motor with 200 steps per revolution (1.8 degree)

AF_Stepper motor(200, 2);        // to motor port #2 (M3 and M4)


#define ON HIGH
#define OFF LOW
int digitalPin = 2;
int val = 0;  


void setup() {
  
  Serial.begin(9600);           // set up Serial library at 9600 bps
  motor.setSpeed(60);           // 30 rpm   
}

void loop() {
  
  pinMode(2, INPUT);  
  val = digitalRead(2);         //Read Logical value
    if (val == HIGH) {
  Serial.println("MICROSTEP steps");
  motor.step(50, FORWARD, MICROSTEP);  //CLOSE GRILLE VANE

delay(2000); 
  
  pinMode(2, INPUT);
  val = digitalRead(2);        //Read Logical value
    if (val == LOW) {
  Serial.println("MICROSTEP steps");
  motor.step(50, BACKWARD, MICROSTEP);  //OPEN GRILLE VANE

delay(2000);
  
    }
  } 
}

Thus far, it is working as intended except when @ the ON position beyond the delay(2000). When Digital PIN 2 reads the 5V for the first time, the command is executed as intended but after the delay, the stepper motor is receiving a command for another 50 steps, which I do not want.

Basically, when switch is latched @ON (5V) the stepper should only do 50 steps and maintain its position until a LOW value is detected again. For some reason, the OFF position works as intended, meaning the stepper motor takes 50 backwards only once, regardless of subsequent LOWs being detected.

Any insight would be greatly appreciated !

Thank you,

Mauricio

  pinMode(2, INPUT);

Why do you think you need to set the mode on every pass through loop()? Usually, this is done ONCE in setup().

  val = digitalRead(2);         //Read Logical value
    if (val == HIGH) {

Look at the state change detection example. You want to do something when the switch BECOMES pressed, not when the switch IS pressed.

Thanks for the input.

I removed the pinMode declaration from the loop() section and it is now present in the setup() only.

Regarding the state change detection for the switch, I have browsed the language reference and I am having difficulty in assessing the correct control structure to be used here. I do not comprehend why the symptom is not present for the LOW state but is for the HIGH state; given that the loop structure is almost identical.

Basically, when switch is latched @ON (5V) the stepper should only do 50 steps and maintain its position until a LOW value is detected again.

What you want, and what you wrote in the code, are two different things. What you wrote in the code is "if the switch is still pressed after 50 steps, do another 5 steps, and another and another, until the switch is released.

The state change detection example show you how to make something happen when the switch becomes pressed, and NOT happen again until the switch is released and pressed again.

This all assumes, of course, that you have the switch wired with an external resistor.

If not, then you have a floating pin, and you can't be sure what will happen.

You could, of course use the internal pullup resistor, by setting the pin mode to INPUT_PULLUP. Then, LOW means pressed.

PaulS:
What you want, and what you wrote in the code, are two different things. What you wrote in the code is "if the switch is still pressed after 50 steps, do another 5 steps, and another and another, until the switch is released.

The state change detection example show you how to make something happen when the switch becomes pressed, and NOT happen again until the switch is released and pressed again.

I think I understand now. I will report back when it works !

Thanks again.

Woohoo ! It works. 8)

#include <AFMotor.h>

// Connect one stepper motor with 200 steps per revolution (1.8 degree)

AF_Stepper motor(200, 2);        // to motor port #2 (M3 and M4)
const int  buttonPin = 2;        // the pin that the pushbutton is attached to

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

void setup() {

  pinMode(buttonPin, INPUT);    // initialize the button pin as a input
  Serial.begin(9600);           // set up Serial library at 9600 bps
  motor.setSpeed(90);           // 30 rpm   

}

void loop() {

  buttonState = digitalRead(buttonPin);      // read the pushbutton input pin

  if (buttonState != lastButtonState) {      // compare the buttonState to its previous state
    if (buttonState == HIGH) {
      Serial.println("MICROSTEP steps");
      motor.step(50, FORWARD, MICROSTEP);    //CLOSE GRILLE VANE
      delay(500); 
    }
    else {
      Serial.println("MICROSTEP steps");
      motor.step(50, BACKWARD, MICROSTEP);   //OPEN GRILLE VANE
      delay(500); 
    }

    lastButtonState = buttonState; // save the current state as the last state for next time through the loop

  }
}

I am glad you have it working, but may I be permitted to throw a wet blanket on your nice camp fire?

You don't have any mechanism to enable you to set the zero position for your motor. The usual way to do that is to have some code in setup that runs the motor until it trips a limit switch. Without that there is a risk, if the flap jams or the Arduino crashes when the motor is in an unknown position, that it will try to move the motor beyond the range you want.

If all you need to do is open and close a flap I suspect a servo would be more convenient as it has an in-built position detection system.

...R
Stepper Motor Basics

Thank you for the input Robin2. I will definitely consider your advice.