Stepper motor looping with an If statement

Hey all,

I am trying to automate a fixture at my job using an Arduino, sainsmart motor shield, and NEMA 17 stepper motor.

When I run the code, the motor turns continuously, no matter which button I press or which state the if statement is set to.

I’ve attached my code. Could it have something to do with the while statement I have inside the if clause?

const int start = A15; // Normally HIGH
const int safe = A12;
const int overTravel = A13;
const int testSwitch = A10;
//E-Stop is hooked into power directly
//all single pins set

int startState = 0;
int safeState = 0;
int overTravelState = 0;
int testSwitchState = 0;
//these variables are set to low. They are used as logic indicators for High/Low readings. 

#include <AFMotor.h>
AF_Stepper testStepper(200, 2); // set 1.8 degree, 4 pin stepper motor.
// stepper set

#include <LiquidCrystal.h> //LCD set to library.
LiquidCrystal lcd(51, 53, 43, 45, 47, 49);
// LCD Display set.

void setup() {
  lcd.begin(16,2);
  lcd.print("Unit On");
  //Greeting
  
pinMode(start, INPUT);
pinMode(safe, INPUT);
pinMode(overTravel, INPUT);
pinMode(testSwitch, INPUT);
//these influence button states. 

testStepper.setSpeed(10); //motor swt to 10rpm
}

void loop() {
  startState = digitalRead(start);
  safeState = digitalRead(safe);
  overTravelState = digitalRead(overTravel);
  testSwitchState = digitalRead(testSwitch);
  
if(startState == LOW); // start test function
 { lcd.clear();
   while(safeState == HIGH)
   {testStepper.step(1, BACKWARD, SINGLE);
   }
   int timeA = micros(); //timeA equals time before motor movement
   while(testSwitchState == HIGH)
   {testStepper.step(1, FORWARD, SINGLE);
   }
   int timeB = micros();
   int time1 = timeB-timeA;
   //time1 done
  //end test function
  
  int time = (time1);
  
  int transferHeight = ((time)*(.0000000167)*(60)*(.025)); // ((microseconds)*(min/m.s.)*(rpm)*(in/rev))=inches
  if(.05<transferHeight<.1) 
  {lcd.setCursor(0,0);
  lcd.print("Good Unit");
  lcd.setCursor(0,1);
  lcd.print(transferHeight);
  }
  else
  {
    lcd.setCursor(0,0);
    lcd.print("Bad Unit");
    lcd.setCursor(0,1);
    lcd.print(transferHeight);
  }
 }
}

I appreciate any help you can provide. If I have been unclear about something feel free to ask and I’ll try to be more explanatory.

Thanks,
Nicholas

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Have you got pullup or pulldown resistors on your switches.
If a switch is open and you do not have an appropriate resistor to pull the input to the opposite logic to the closed switch, the input is floating and can have any value, usually that of the switch closed, even though it is open.

This includes limit switches.

What model arduino are you using?

Tom...... :slight_smile:

if(startState == LOW); // start test function
What were you thinking?

Hey Tom,

Sorry for the late reply. Windows 10 update crippled my computer for a few days...

I do have pull-down resistors from one leg of the "on switch" to ground. The same leg is connected to an Arduino input, while the other leg is connected to power.

Note that the switch is normally closed, which is why I have "when start button is low, continue program" line in there. The switch isn't a detent so it's closed until you push it.

I have attached a hand drawing of the circuit that is giving me trouble. There are 3 other switches in the circuit all connected in the same way as the one drawn, but they aren't giving me any trouble.

Thanks for the replies, I appreciate it.

Nicholas

Hey Tom,

Sorry for the late reply. Windows 10 update crippled my computer for a few days…

I do have pull-down resistors from one leg of the “on switch” to ground. The same leg is connected to an Arduino input, while the other leg is connected to power.

Note that the switch is normally closed, which is why I have “when start button is low, continue program” line in there. The switch isn’t a detent so it’s closed until you push it.

I have attached a hand drawing of the circuit that is giving me trouble. There are 3 other switches in the circuit all connected in the same way as the one drawn, but they aren’t giving me any trouble.

Thanks for the replies, I appreciate it.

Nicholas

Hey everybody,

I got the sketch to work! The culprit was the semicolon after the first if statement. For some reason it was skipping the if test. All I did was remove the semicolon and the sketch ran.

Thanks to everybody who replied!

I am actually having a second issue now. I tested each piece of logic in the program and it all functions. However, I am having a “while” issue I think may be related to power or ground.

In the first “while” statement, the motor will move until it hits a switch, then move on to the second "while "statement. If I start the sketch off while the button is pushed by me, the second “while” statement is executed. If I start the sketch and the first while statement is executed, the motor hits the switch but keeps going; it doesn’t read that the “while statement” is now false.

I know that may be confusing, so I am posting my code with the first and second “while” statements identified.

Thanks again for your help Arduino community.

// Need MORE POWER. BOARD CANNOT READ ALL SWITCHES WHILE CONTROLLING MOTOR


const int start = A15; // Normally HIGH
const int safe = A12;
const int overTravel = A13;
const int testSwitch = A10;
//E-Stop is hooked into power directly
//all single pins set

int startState = 0;
int safeState = 0;
int overTravelState = 0;
int testSwitchState = 0;
//these variables are set to low. They are used as logic indicators for High/Low readings. 

#include <AFMotor.h>
AF_Stepper testStepper(200, 2); // set 1.8 degree, 4 pin stepper motor.
// stepper set

#include <LiquidCrystal.h> //LCD set to library.
LiquidCrystal lcd(51, 53, 43, 45, 47, 49);
// LCD Display set.

void setup() {
  lcd.begin(16,2);
  lcd.print("Unit On");
  //Greeting
  
pinMode(start, INPUT);
pinMode(safe, INPUT);
pinMode(overTravel, INPUT);
pinMode(testSwitch, INPUT);
//these influence button states. 

testStepper.setSpeed(10); //motor swt to 10rpm
}

void loop() {
  startState = digitalRead(start);
  safeState = digitalRead(safe);
  overTravelState = digitalRead(overTravel);
  testSwitchState = digitalRead(testSwitch);
  
if(startState == LOW) // start test function. This is the IF statement referred to in my post. 
 {
   lcd.clear(); 
   while(safeState == HIGH) // FIRST WHILE STATEMENT
   {
     testStepper.step(1, BACKWARD, SINGLE);
     digitalRead(safe);
   }                                                          
   int timeA = micros(); //timeA equals time before motor movement

   while(testSwitchState == LOW) // SECOND WHILE STATEMENT
   {testStepper.step(1, FORWARD, SINGLE);
   digitalRead(testSwitch);
   }
   int timeB = micros();
   int time1 = timeB-timeA;
   //time1 done
  //end test function
  
  int time = (time1);
  
  int transferHeight = ((time)*(.0000000167)*(60)*(.025)); // ((microseconds)*(min/m.s.)*(rpm)*(in/rev))=inches
  if(.05<transferHeight<.1) 
  {lcd.setCursor(0,0);
  lcd.print("Good Unit");
  lcd.setCursor(0,1);
  lcd.print(transferHeight);
  }
  else
  {
    lcd.setCursor(0,0);
    lcd.print("Bad Unit");
    lcd.setCursor(0,1);
    lcd.print(transferHeight);
  }
 }
 else {
   lcd.setCursor(0,1);
   lcd.print("Press Start");
 } 
}
   while(safeState == HIGH) // FIRST WHILE STATEMENT
   {
     testStepper.step(1, BACKWARD, SINGLE);
     digitalRead(safe);
   }

It's usually a good idea to actually read the state of the switch during the body of the loop, AND store it. Reading it once, and then going into an infinite loop is rarely a good idea.

PaulS:

   while(safeState == HIGH) // FIRST WHILE STATEMENT

{
    testStepper.step(1, BACKWARD, SINGLE);
    digitalRead(safe);
  }



It's usually a good idea to actually read the state of the switch during the body of the loop, AND store it. Reading it once, and then going into an infinite loop is rarely a good idea.

Paul S,

Thanks for your reply. Does digitalRead not also store the value in the variable safeState? (safeState = digitalRead(safe) as per my code).

I thought that by reading the switch "safe", I was also changing the variable "safeState". Can you tell me how I would store the data so that the "while" loop can read it?

Also, I was under the impression that my digitalRead statement was in the while loop and that it would check to see if the safeState == HIGH statement was True/False and then run the loop, including my digitalRead statement.

Thank you,

Nicholas

[/quote] It's usually a good idea to actually read the state of the switch during the body of the loop, AND store it. Reading it once, and then going into an infinite loop is rarely a good idea.
[/quote]

Paul S,

I see what you're saying actually. I just input this as my code, and it functions perfectly. I see now where I went wrong; I set the safeState variable to digitalRead(safe), but that is only once. It does not update every time I read (safe). I had to input that during the loop.

I appreciate everyone's help, and thanks to Paul S for helping me "crack the code"!

Nicholas

[code]  while(safeState == HIGH)
   {
     testStepper.step(1, BACKWARD, SINGLE);
     digitalRead(safe);
     safeState = digitalRead(safe);
    
   }
     digitalRead(safe);
     safeState = digitalRead(safe);

Read and throw away the value. Then, read and store the value. The purpose of the first call escapes me.

Paul S,

The first call has no purpose. I've been cleaning up the code the last few minutes. It has since been deleted.

Nicholas

Nickefth:
I’ve been cleaning up the code the last few minutes.

When you have finished tidying things post the latest version of the code. It just wastes time asking questions about yesterday’s code.

…R