Pause program mid loop until switch is pressed?

Hello,

I'm trying to create a function that I can call inside my loop that will 'pause' the program and wait (indefinitely) until it receives an input from a limit switch before continuing. I'm using the following function, with the switch sending its input to pin 5.

void drillWait(int drillPin){
  int drillState = 0;
  while(1){
    drillState = digitalRead(drillPin);
    if (drillState == LOW) {
      return;
    }
  }
}

that I found here: arduino uno - Pause code untill a button is pressed - Arduino Stack Exchange, but I can't seem to get it to work and I don't quite understand what it's doing well enough to modify it to fit my needs.

I've added my entire code in case it's something somewhere else messing with it (sorry it's messy, I don't know entirely what I'm doing). I've rewired my entire system twice and just can't find the problem.

i

nt mot1d = 12; //motor 1 direction
int mot1s = 3;  //motor 1 speed
int mot1b = 9;  //motor 1 brake
int pusher = 7; //Pusher air cylinder
int gripper = 4;   //gripper
int drill = 6;  //Drill air cylinder
int tdoor = 2;  //Trap door air cylinder
int IR1 = 10;    //Part present IR switch
int i = 1;
int estop = A5;   //emergency stop 
int mode = A2;   //mode switch
int foots = A3; //foot pedal
int x;
int y;
int ks = 0;
int mmode = 0;

//Function for drill sensor; drill until sensor is activated.
void drillWait(int drillPin){
  int drillState = 0;
  while(1){
    drillState = digitalRead(drillPin);
    if (drillState == LOW) {
      return;
    }
  }
}


void setup() {

pinMode(mot1d, OUTPUT);
pinMode(mot1s, OUTPUT);
pinMode(mot1b, OUTPUT);
pinMode(pusher, OUTPUT);
pinMode(gripper, OUTPUT);
pinMode(drill, OUTPUT);
pinMode(tdoor, OUTPUT);
pinMode(IR1, INPUT);
pinMode(mode, INPUT);
pinMode(foots, INPUT);
Serial.begin(9600);
}

void loop() {

//motors on  
//digitalWrite(mot1d, HIGH);
//analogWrite(mot1s, 255);


//Read e stop pin & mode pin
mmode = digitalRead(A2);  
ks = digitalRead(A5);
  if (ks == 0) {
      ks = digitalRead(A5);

//manual mode program
  while (mmode == 1) {

    digitalWrite(mot1b, HIGH);
    digitalWrite(tdoor, LOW);
    digitalWrite(pusher, LOW);
    digitalWrite(gripper,LOW);
    digitalWrite(drill, LOW);
    digitalRead(A5);
  
//If manual mode is selected, wait for signal from foot switch. After foot switch is activated, close grippers, short delay, drill until drill sensor activates, retract drill and release gripper then wait for foot switch again.
  if (digitalRead(foots) == HIGH) {       
        
        digitalWrite(gripper,HIGH);
        delay(1000);
        digitalWrite(drill, HIGH);
        delay(500);
        drillWait(5);
        digitalWrite(drill, LOW);
        delay(2000);
        digitalWrite(gripper, LOW);
       delay(1000);
        digitalWrite(tdoor, HIGH);
        delay(2000);
        digitalWrite(tdoor, LOW);
        
}
mmode = digitalRead(A2);
}


  if (i == 0) {
    x = millis();
    while ((x - y) <= 1000) {
   digitalWrite(mot1d, HIGH);
   analogWrite(mot1s, 255);
    i = 1;
    x = millis();
    }
  
//if stick is present, stop motors and activate pusher. Delay 1 sec, then activate gripper and push down solenoid. Delay 1 sec and activate drill. Time based drilling then exit loop. Need to add sensor for drill position.

}
   if (digitalRead(IR1) == LOW) {
    digitalWrite(mot1b, HIGH);               
    digitalWrite(pusher, HIGH);
    delay(1000);
    digitalWrite(gripper,HIGH);
    delay(1000);
    digitalWrite(drill, HIGH);
    delay(100);
    drillWait(5);
    digitalWrite(drill, LOW);
    digitalWrite(pusher, LOW);
    delay(2000);
    digitalWrite(gripper, LOW);
    delay(1000);
    digitalWrite(tdoor, HIGH);
    delay(2000);
    digitalWrite(tdoor, LOW);
    digitalWrite(mot1b, LOW);
    digitalRead(IR1);
       }
  else{
    i = 0;
    y = millis();       
  }
  }


// estop program 
//if (ks == 1) {
//   digitalWrite(mot1b, HIGH);               
//   digitalWrite(pusher, LOW);
//   digitalWrite(gripper,LOW);
//   digitalWrite(tdoor, LOW);
//   digitalWrite(drill, LOW);
//   delay (2000);
//   ks = digitalRead(A5);   
//      while (ks == 0) {
//        ks = digitalRead(A5);
//      }
//   delay (1000);   
//   ks = digitalRead(A5);
//   digitalWrite(mot1b, LOW);
}

Basically what's happening is the program runs fine but once the switch is hit the program stays paused. I wasn't sure if maybe I'm telling it to look for the wrong thing (my switch sends a LOW signal when activated), so I tried changing the line in the function to if (drillState == HIGH) just to see what would happen and the program doesn't pause at all, it just continues through the loop.
Any help would be greatly appreciated!

What you are seeing is EXACTLY what is programmed for. Look at this line"

 while(1){
    drillState = digitalRead(drillPin);

Do you see the while(1) line. That says to wait here FOREVER. 

Perhaps change the code to:

void drillWait(int drillPin){
  int drillState = 0;
  int pauser = 1;
  while(pauser == 1){
    drillState = digitalRad(drillPin);
    if (drillState == LOW) {
      pauser = 0;
    }
  }

Or maybe change it to

Thank you both for the responses! I will try your suggestions :slight_smile:

Um, he has a RETURN statement inside the loop. That should work fine, even if it's not considered the best coding practice...

I'm betting that they need to set pinMode(5, INPUT_PULLUP);

Would you mind explaining what while(drillState ! = 0) is telling the program to do?

It reads while the variable drillState is not equal to zero carry on doing the next statement repeatedly. As there are braces { } round a few lines those make the lines just look like one statement.

Thank you! I tried this and it seems to be doing the same thing; it appears to be pausing when the switch is activated instead of starting back up when it's activated. Could there be something else in the code messing with this?

You have not set pinMode for drillPin.

Also I would make the loop an even more obvious 'busy wait'

void drillWait(int drillPin)
{
  do { /* nothing */ } while (digitalRead(drillPin) == HIGH);
}

Well all pins by default are inputs.

Yes, or it could be that you have wired your switch up wrong.

How is it wired up? Does it have any resistors associated with it?

That tells me you have wired the switch up wrong.
Please post a schematic of how you have wired the switch.

That is functionally equivalent to:

void drillWait(int drillPin)
{
  while(digitalRead(drillPin) != LOW)
    {/* Do Nothing */}
}

I followed this schematic for the wiring (only difference is mine is connected to pin 5)

Thanks, that looks wired OK to me.
However, is that picture of a switch like yours, and is it on solderless bread board. If so it could be faulty connections on the board because those lugs don't fit into the board very well.

I have a very similar switch, but I have the wires soldered to the terminals (it's mounted to a drill press and is acting as a limit switch once the drill reaches a certain point)

I figured I'd try to simplify things and just test the portion of code in question in a smaller setup, just lighting LED's. This is the code I used:


void drillWait(int drillPin){
  int drillState = 1;
  while(drillState  != 0){
    drillState = digitalRead(drillPin);
    }
  }
  
void setup() {
  // put your setup code here, to run once:
pinMode(1, OUTPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(5, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:

digitalWrite(1, HIGH);
delay(1000);
digitalWrite(2, HIGH);
delay(1000);
digitalWrite(3, HIGH);
delay(1000);
drillWait(5);
digitalWrite(3, LOW);
digitalWrite(2, LOW);
digitalWrite(1, LOW);
delay(1000);

}   

This mini program worked just fine, so the problem must lie somewhere else in the main code, but I can't seem to find it. I cleaned the code up a bit and removed some sections that weren't being used, if you have any suggestions I would be incredibly grateful!

int mot1d = 12; //motor 1 direction
int mot1s = 3;  //motor 1 speed
int mot1b = 9;  //motor 1 brake
int pusher = 7; //Pusher air cylinder
int gripper = 4;   //gripper
int drill = 6;  //Drill air cylinder
int tdoor = 2;  //Trap door air cylinder
int IR1 = 10;    //Part present IR switch
int i = 1;
int mode = A2;   //mode switch
int foots = A3; //foot pedal
int x;
int y;

//Function for drill sensor; drill until sensor is activated.

void drillWait(int drillPin){
  int drillState = 1;
  while(drillState  != 0){
    drillState = digitalRead(drillPin);

  }
}


void setup() {

pinMode(mot1d, OUTPUT);
pinMode(mot1s, OUTPUT);
pinMode(mot1b, OUTPUT);
pinMode(pusher, OUTPUT);
pinMode(gripper, OUTPUT);
pinMode(drill, OUTPUT);
pinMode(tdoor, OUTPUT);
pinMode(IR1, INPUT);
pinMode(mode, INPUT);
pinMode(foots, INPUT);
Serial.begin(9600);
}

void loop() {


//manual mode program
int mmode = 0;
mmode = digitalRead(A2);
  while (mmode == 1) {

    digitalWrite(mot1b, HIGH);
    digitalWrite(tdoor, LOW);
    digitalWrite(pusher, LOW);
    digitalWrite(gripper,LOW);
    digitalWrite(drill, LOW);
  
//If manual mode is selected, wait for signal from foot switch. After foot switch is activated, close grippers, short delay, drill until drill sensor activates, retract drill and release gripper then wait for foot switch again.
  if (digitalRead(foots) == HIGH) {       
        
        digitalWrite(gripper,HIGH);
        delay(1000);
        digitalWrite(drill, HIGH);
        drillWait(5);
        digitalWrite(drill, LOW);
        delay(2000);
        digitalWrite(gripper, LOW);
       delay(1000);
        digitalWrite(tdoor, HIGH);
        delay(2000);
        digitalWrite(tdoor, LOW);    
          }
mmode = digitalRead(A2);
}

//Auto program

  if (i == 0) {
    x = millis();
    while ((x - y) <= 1000) {
   digitalWrite(mot1d, HIGH);
   analogWrite(mot1s, 255);
    i = 1;
    x = millis();
    }
  }
//if stick is present, stop motors and activate pusher. Delay 1 sec, then activate gripper and push down solenoid. Delay 1 sec and activate drill. Time based drilling then exit loop. Need to add sensor for drill position.

   if (digitalRead(IR1) == LOW) {
    digitalWrite(mot1b, HIGH);               
    digitalWrite(pusher, HIGH);
    delay(1000);
    digitalWrite(gripper,HIGH);
    delay(1000);
    digitalWrite(drill, HIGH);
    drillWait(5);
    digitalWrite(pusher, LOW);
    digitalWrite(drill, LOW);
    delay(2000);
    digitalWrite(gripper, LOW);
    delay(1000);
    digitalWrite(tdoor, HIGH);
    delay(2000);
    digitalWrite(tdoor, LOW);
    digitalWrite(mot1b, LOW);
    digitalRead(IR1);
       }
  else{
    i = 0;
    y = millis();       
  }
}

With a few comments mostly just added inline....

const int mot1d   = 12; //motor 1 direction
const int mot1s   = 3;  //motor 1 speed
const int mot1b   = 9;  //motor 1 brake
const int pusher  = 7;  //Pusher air cylinder
const int gripper = 4;  //gripper
const int drill   = 6;  //Drill air cylinder
const int tdoor   = 2;  //Trap door air cylinder
const int IR1     = 10; //Part present IR switch
int i             = 1;  /* Don't mix declarations of variables and constants - it makes it harder to see what is what. */
const int mode    = A2; //mode switch /* you've declared this, but still use A2. Don't do that... */
const int foots   = A3; //foot pedal
int x;
int y;
/* 
   The names of all the variables here are terrible names for global variables. 
   Adopt a consistent and distinct naming convention for constants that represent pins, 
   and preferably variables in general. I do WHATEVER_PIN (ex, PUSHER_PIN) for pins, 
   and ALL_CAPS for global constants in general (whether they're declared normally or 
   #define'ed), and ProperCase for global variables that vary and static variables. 
   And don't be shy about using whitespace to improve readability 
 */

//Function for drill sensor; drill until sensor is activated.
/* 
   This is a weird function - will it ever be used with a different pin?
   If not, why pass the switch pin as an argument? 
   If so, then declare named constants for the pins, and use those. 
   When anyone sees an integer literal passed to a function with "wait" in the name, they'll think the number is some unit of time. 
*/
void drillWait(int drillPin){
  int drillState = 1;
  while(drillState  != 0){
    drillState = digitalRead(drillPin);

  }
}

void setup() {

pinMode(mot1d, OUTPUT);
pinMode(mot1s, OUTPUT);
pinMode(mot1b, OUTPUT);
pinMode(pusher, OUTPUT);
pinMode(gripper, OUTPUT);
pinMode(drill, OUTPUT);
pinMode(tdoor, OUTPUT);
pinMode(IR1, INPUT);
pinMode(mode, INPUT); /* mode for a pin connected to a swtich should be INPUT only when you have some way (usually a pullup or pulldown resistor) to ensure that it's in a defined state when the switch is off. */
pinMode(foots, INPUT); /* normally people use a 10k or 4.7k resistor as a default pullup or pulldown (INPUT_PULLUP pullup strength is less, like a 30-50k resistor). On occasionally sees a 1meg+ resistor used as a pullu
Serial.begin(9600);
}

This is poor practice:

    variable = digitalRead(pin);
    while(variable) {
      ...
      ...
      variable = digitalRead(pin);
    }

it's easy to write bugs where you aren't reading a pin when you thought you were

void loop() {

//manual mode program
int mmode = 0; 
mmode = digitalRead(A2); /* this line and the preceding one could be combined into one. */
  while (mmode == 1) {
    digitalWrite(mot1b, HIGH);
    digitalWrite(tdoor, LOW);
    digitalWrite(pusher, LOW);
    digitalWrite(gripper,LOW);
    digitalWrite(drill, LOW);
  
  // If manual mode is selected, wait for signal from foot switch. After foot switch is activated, close grippers, short delay, drill until drill sensor activates, retract drill and release gripper then wait for foot switch again.
  if (digitalRead(foots) == HIGH) {       
        
        digitalWrite(gripper,HIGH);
        delay(1000);
        digitalWrite(drill, HIGH);
        drillWait(5);
        digitalWrite(drill, LOW);
        delay(2000);
        digitalWrite(gripper, LOW);
       delay(1000);
        digitalWrite(tdoor, HIGH);
        delay(2000);
        digitalWrite(tdoor, LOW);    
          }
mmode = digitalRead(A2);
}

//Auto program

  if (i == 0) { 
    x = millis();
    while ((x - y) <= 1000) {
    digitalWrite(mot1d, HIGH);
   analogWrite(mot1s, 255);
    i = 1;
    x = millis();
    }
  }
  /* 
   I think your braces don't match your expectations. 
   Ctrl+T autoformat and you'll see what I refer to - maybe that's what you mean, but I don't think so.
   Then again, I also can't figure out what the intent here is with x, y, and i...
   other than that it's probably not what it does. 
*/
//if stick is present, stop motors and activate pusher. Delay 1 sec, then activate gripper and push down solenoid. Delay 1 sec and activate drill. Time based drilling then exit loop. Need to add sensor for drill position.

   if (digitalRead(IR1) == LOW) {
    digitalWrite(mot1b, HIGH);               
    digitalWrite(pusher, HIGH);
    delay(1000);
    digitalWrite(gripper,HIGH);
    delay(1000);
    digitalWrite(drill, HIGH);
    drillWait(5);
    digitalWrite(pusher, LOW);
    digitalWrite(drill, LOW);
    delay(2000);
    digitalWrite(gripper, LOW);
    delay(1000);
    digitalWrite(tdoor, HIGH);
    delay(2000);
    digitalWrite(tdoor, LOW);
    digitalWrite(mot1b, LOW);
    digitalRead(IR1);
       }
  else{
    i = 0;
    y = millis();       
  }
}

@DrAzzy Thank you so much for that thorough feedback! Could you please explain a little bit more what you mean about this? I don't quite understand how exactly it's wrong to begin to address the problem.

The Fritzy does not show whether the switch is wired NO or NC.

It's wired NO.

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