Need Help With A Specific Code For Stepper Motor Control

Hi everyone,

I'm working on a project where I'm controlling a stepper motor through an Arduino Mega and the adafruit LCD Shield. This is my first "big" project using an Arduino and of course, my programming knowledge is limited.

The idea is to put the amount of steps/angles (1.8 degree/step) I want in the stepper motor by clicking the buttons on the LCD Shield and have it display the angle that I have choosen. Once the SELECT button is pressed, the motor rotates to the selected angle. Then I'm given the option to put a new entry by pressing the SELECT button again. That'll reset the stepper motor position by rotating the exact same angle but in the opposite direction. From there, I can start over in the void loop to put in a new angle.

I used mostly other codes I've found and made heavy modifications to it. The code works pretty well but the part of the code that returns the motor to the starting position doesn't work. That means the motor can not return to its starting position before a new entry is put in. I'm pretty confident it is this section of the code near the end that is causing this problem. What am I doing wrong?? :o

if (buttons) {
          if (buttons & BUTTON_SELECT) {
                Serial.print("new entry worked");
                // Reverse Motor Position to Beginning
                digitalWrite(dirPin,LOW); 
                // Makes selected number of pulses
                for(int x = 0; x < numberOfPhase; x++) {
                digitalWrite(stepPin,HIGH); 
                delayMicroseconds(1000); 
                digitalWrite(stepPin,LOW); 
                delayMicroseconds(1000);
                int reset = 5; 
                break; 
                }
          }
        }//buttons end

Here is the entire code:

// include the library code:
#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>
#include <LiquidCrystal.h>

// The shield uses the I2C SCL and SDA pins. On classic Arduinos
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
// However, you can connect other I2C sensors to the I2C bus and share
// the I2C bus.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

// defines pins numbers
const int stepPin = 11; 
const int dirPin = 13; 

void setup() {
  Serial.begin(9600);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);               
  lcd.setCursor(0,0);
  lcd.print("Select Angle");
  delay(2500);

  // Sets the two pins as Outputs
  pinMode(stepPin,OUTPUT); 
  pinMode(dirPin,OUTPUT);
}

void loop() {
  
  // set my step variable
  int numberOfPhase = 0;
  int phase = 1;
  int angleDisplay = numberOfPhase*1.8; //one step equal 1.8 degree
  int reset = 0;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Angle: 0");
  uint8_t buttons = lcd.readButtons();

  while (reset <= 0){
  uint8_t buttons = lcd.readButtons();

    //buttons control
    if (buttons) {
      //display angle input
      lcd.setCursor(7,0);
      
      if (buttons & BUTTON_UP) {
        numberOfPhase = numberOfPhase + phase;
        if (angleDisplay >= 360){
          numberOfPhase = 200;
          angleDisplay = numberOfPhase*1.8;
          lcd.print(angleDisplay,1);
        }
        else {
        angleDisplay = numberOfPhase*1.8;
        lcd.print(angleDisplay,1);
        }
      }//up button end
      
      if (buttons & BUTTON_DOWN) {
        numberOfPhase = numberOfPhase - phase;
        if (angleDisplay <= 0){
          numberOfPhase = 0;
          angleDisplay = numberOfPhase*1.8;
          lcd.print(angleDisplay,1);
            }
        else {
        angleDisplay = numberOfPhase*1.8;
        lcd.print(angleDisplay,1);
        }
      }//down button end
      
      if (buttons & BUTTON_RIGHT) {
        numberOfPhase = numberOfPhase + 5*phase;
          if (angleDisplay >= 360){
          numberOfPhase = 200;
          angleDisplay = numberOfPhase*1.8;
          lcd.print(angleDisplay,1);
          }
          else {
          angleDisplay = numberOfPhase*1.8;
          lcd.print(angleDisplay,1);
          }
          Serial.println(numberOfPhase);
       }//right button end
        
      if (buttons & BUTTON_LEFT) {
       numberOfPhase = numberOfPhase - 5*phase;
        if (angleDisplay <= 0){
          numberOfPhase = 0;
          angleDisplay = numberOfPhase*1.8;
          lcd.print(angleDisplay,1);
          Serial.print(numberOfPhase);
          Serial.print('\n');
          }
        else {
        angleDisplay = numberOfPhase*1.8;
        lcd.print(angleDisplay,1);
        Serial.print(numberOfPhase);
        Serial.print('\n');
        }
      }//left button end
  
        if (buttons & BUTTON_SELECT) {
          int motorStep = numberOfPhase; 
          //int reset = reset++; 
          lcd.clear();
          lcd.print("Angle Selected:");
          lcd.setCursor(0,1);
          lcd.print(angleDisplay);
          delay(1000);
          Serial.print("numberOfPhase: ");
          Serial.println(motorStep);
          
            // Enables the motor to move in a particular direction
            digitalWrite(dirPin,HIGH); 
          
            // Makes selected number of pulses
            for(int x = 0; x < motorStep; x++) {
            digitalWrite(stepPin,HIGH); 
            delayMicroseconds(1000); 
            digitalWrite(stepPin,LOW); 
            delayMicroseconds(1000); 
            }
            //ending the while loop
            int reset = 1;
            Serial.print(reset);
            break;
        }//select button end
     }//button end
  }//while loop end
        
        delay(1000);
        lcd.clear();
        lcd.print("Press SELECT for");
        lcd.setCursor(0,1);
        lcd.print("for new entry");
        delay(5000);

        
        if (buttons) {
          if (buttons & BUTTON_SELECT) {
                Serial.print("new entry worked");
                // Reverse Motor Position to Beginning
                digitalWrite(dirPin,LOW); 
                // Makes selected number of pulses
                for(int x = 0; x < numberOfPhase; x++) {
                digitalWrite(stepPin,HIGH); 
                delayMicroseconds(1000); 
                digitalWrite(stepPin,LOW); 
                delayMicroseconds(1000);
                int reset = 5; 
                break; 
                }
          }
        }//buttons end
     
      Serial.print("new entry did NOT work");
}//void loop end
                for(int x = 0; x < numberOfPhase; x++) {
                digitalWrite(stepPin,HIGH); 
                delayMicroseconds(1000); 
                digitalWrite(stepPin,LOW); 
                delayMicroseconds(1000);
                int reset = 5; 
                break; 
                }

First off, your indenting is absolutely horrible.

Second, the reset variable declaration and initialization is pointless because it is local to, and never used in, the for loop.

Third, the for loop is pointless because the break statement assures that it will iterate not more than once.

Fourth, why are you not using the Stepper library? Stepping in the opposite direction is a matter of calling step() with a negative number (the number of steps taken in one direction times -1).

You may find some useful stuff in these links

Stepper Motor Basics

Simple Stepper Code

...R

Thanks Robin.
I've read the two links and it was very informative!

As for Paul,
sorry for my bad indenting; I'm a complete noob when it comes to programming. I've addressed the second and third thing you had. Now the reason why I didn't use the Stepper Library is because I learn the wire connections and coding from How to Mechatronics and I'm more comfortable using their code.

I got the code to work except for the part where I need to press the SELECT button to reset the motor to the starting position. The code seems to be halted when it gets to my second while loop or the if (buttons) function inside the second while loop.

Here is the updated code below. Everything works except for the second while loop. Would be very grateful if you can take minute to look at it. Thanks.

// include the library code:
#include <Wire.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>
#include <LiquidCrystal.h>

// The shield uses the I2C SCL and SDA pins. On classic Arduinos
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
// However, you can connect other I2C sensors to the I2C bus and share
// the I2C bus.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

// defines pins numbers
const int stepPin = 11;
const int dirPin = 13;

void setup() {
  Serial.begin(9600);
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Select Angle");
  delay(2500);

  // Sets the two pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
}

void loop() {
  // set my step variable
  int numberOfStep = 100;
  int phase = 1;
  int reset = 0;
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Angle: ");

  //first while loop
  while (reset <= 0) {
    //declare buttons in while loop
    uint8_t buttons = lcd.readButtons();
    //declare angle variable
    float angle = numberOfStep * 1.8; //one step equal 1.8 degree
    lcd.setCursor(7, 0);
    lcd.print(angle);

    //buttons control
    if (buttons) {
      //display angle input
      lcd.setCursor(7, 0);
      lcd.print(angle);

      if (buttons & BUTTON_UP) {
        numberOfStep = numberOfStep + phase;
        Serial.print("phase: ");
        Serial.println(numberOfStep);
        Serial.print("angle: ");
        Serial.println(angle);
        delay(500);
        if (numberOfStep >= 200) {
          numberOfStep = 200;
          lcd.print(angle, 1);
        }
      }//up button end

      if (buttons & BUTTON_DOWN) {
        numberOfStep = numberOfStep - phase;
        Serial.print("phase: ");
        Serial.println(numberOfStep);
        Serial.print("angle: ");
        Serial.println(angle);
        delay(500);
        if (numberOfStep <= 0) {
          numberOfStep = 0;
          lcd.print(angle, 1);
        }
      }//down button end

      if (buttons & BUTTON_RIGHT) {
        numberOfStep = numberOfStep + 5 * phase;
        Serial.print("phase: ");
        Serial.println(numberOfStep);
        Serial.print("angle: ");
        Serial.println(angle);
        delay(500);
        if (numberOfStep >= 200) {
          numberOfStep = 200;
          lcd.print(angle, 1);
        }
      }//right button end

      if (buttons & BUTTON_LEFT) {
        numberOfStep = numberOfStep - 5 * phase;
        Serial.print("phase: ");
        Serial.println(numberOfStep);
        Serial.print("angle: ");
        Serial.println(angle);
        delay(500);
        if (numberOfStep <= 0) {
          numberOfStep = 0;
          //angleDisplay = numberOfPhase*1.8;
          lcd.print(angle, 1);
        }
      }//left button end

      if (buttons & BUTTON_SELECT) {
        lcd.clear();
        lcd.print("Angle Selected:");
        lcd.setCursor(0, 1);
        lcd.print(angle);
        delay(1000);
        Serial.print("numberOfStep: ");
        Serial.println(numberOfStep);

        // Enables the motor to move in a particular direction
        digitalWrite(dirPin, HIGH);

        // Makes selected number of pulses
        for (int x = 0; x < numberOfStep; x++) {
          digitalWrite(stepPin, HIGH);
          delayMicroseconds(1000);
          digitalWrite(stepPin, LOW);
          delayMicroseconds(1000);
        }
        //ending the while loop
        reset = ++reset;
        Serial.print("reset: ");
        Serial.println(reset);
      }//select button end
    }//button end
  }//while loop end

  //to confirm the first while loop ended
  Serial.println("first while loop ended");

  //declare buttons
  uint8_t buttons = lcd.readButtons();
  //ask users if they want a new entry
  delay(1000);
  lcd.clear();
  lcd.print("Press SELECT for");
  lcd.setCursor(0, 1);
  lcd.print("for new entry");
  //second while loop
  while (reset < 2) {
    if (buttons) {
      if (buttons & BUTTON_SELECT) {
        Serial.print("new entry worked");
        // Reverse Motor direction
        digitalWrite(dirPin, LOW);
        // Resets the motor position to its start
        for (int x = 0; x < numberOfStep; x++) {
          digitalWrite(stepPin, HIGH);
          delayMicroseconds(1000);
          digitalWrite(stepPin, LOW);
          delayMicroseconds(1000);
          reset = ++reset;
          Serial.print("reset #2: ");
          Serial.println(reset);
        }
      }
    }//buttons end
  }

}//void loop end

Between the two while loops you read the buttons before you ask the user to press one. You'll probable want to give them some time to press it. The code won't wait. It will read the buttons see that one hasn't been pressed yet and move on.

kuan3:
Thanks! Is there a way to halt the program and only move on until the SELECT button is pressed?

A while loop. While the button is not select, read the button again.

Thanks Delta_G! I think I got it to work!

I moved uint8_t buttons = lcd.readButtons() inside the second while loop

//ask users if they want a new entry
  delay(1000);
  lcd.clear();
  lcd.print("Press SELECT for");
  lcd.setCursor(0, 1);
  lcd.print("for new entry");
  //second while loop
  while (reset < 2) {
    //declare buttons
    uint8_t buttons = lcd.readButtons();
    if (buttons) {
      if (buttons & BUTTON_SELECT) {
        Serial.println("new entry worked");
        delay(500);
        // Reverse Motor direction
        digitalWrite(dirPin, LOW);
        // Resets the motor position to its start
        for (int x = 0; x < numberOfStep; x++) {
          digitalWrite(stepPin, HIGH);
          delayMicroseconds(1000);
          digitalWrite(stepPin, LOW);
          delayMicroseconds(1000);
        }
        reset = ++reset;
        Serial.print("reset #2: ");
        Serial.println(reset);
      }
    }//buttons end
  }