2Q's: Pause during sequence & Wait for Button state at the end

Hi all. This is my first post. I've always been a great PC builder and power user, but I never really got much into coding past Microsoft Basic. That actually works great for me since I'm a CNC programmer by trade and a lot of my coding is manual and some of the advance g-coding I have to use consists of While/Do statements and loops. I've been playing around with the Arduino a bit and have been thinking of trying to automate a couple of our simple processes that we do manually that, in short, suck for the operator. I've ran into a bit of a standstill due to my lack of knowledge and was hoping I could get a bit of help.

Although I have a stepper motor and driver ordered and on the way, I've been testing out my code and process using LED blinks. My code is still programmed to blink the LED, but it will eventually be replaced with a command to rotate the stepper motor one full revolution.

My first problem in this code is that I need to blink the LED 20 times. However, I need to be able to pause during the middle and then resume. Let's say the operator pushes the button and it blinks 10 times--they need to be able to press the button, pause the blinking, and then press the button again to resume--with the next blink still being the 11th. If I need to, I can hookup a 2nd button instead of the first to be the pause button, so one button can be Start, and the other can be Pause/Resume. (Side question--how can I turn the number 10 for number of blinks into a variable set at the top?)

Here's my current code that works (with my test button) to flash the LED:

void setup(){
  //start serial connection
  Serial.begin(9600);
  //configure pin2 as an input and enable the internal pull-up resistor
  pinMode(2, INPUT_PULLUP);
  pinMode(13, OUTPUT); 
}

void loop(){
  //read the pushbutton value into a variable
  int sensorVal = digitalRead(2);
  //print out the value of the pushbutton
  Serial.println(sensorVal);
  //LED on when not pressed
  if (sensorVal == LOW) {
    digitalWrite(13, LOW);  
  } 
  else {
    for(int i = 0; i < 10; i++)
{
  digitalWrite(13, HIGH);
  delay(200);
  digitalWrite(13, LOW);
  delay(500);
  }
}
  }

My 2nd problem is, I have another process almost identical except the rotation/blink will occur one time---BUT I'm using an optical sensor and based on the nature of the process at the end of the loop I need to make sure that the sensor is not still blocked. The process is that an arm is moved into a position that the sensor is NOT blocked. It then moves back to where the sensor is blocked. Then the rotation/blink should occur one time. In the above code, after the blinking is done, it checks the button again. If it is still pressed down it immediately starts blinking another sequence. ON this setup, after the moving in/out is done a number of times the operator pulls the arm back (sensor still blocked) and has to manually change a part out. I do not want the rotation to happen again until the sensor is unblocked, and then blocked again. I do not know how to make the end of the program wait until the sensor is unblocked again before it loops to the top and waits for the sensor to be blocked.

In short:

  1. How can I pause during the middle of my blinking sequence, and then resume? (Also how can I change the number of blinks into a variable?)
  2. How can I make the end of a loop wait for the button state to change again?

Thanks in advance for all the help. I know this should be a simple problem. If it were CNC C-Code I would be able to solve it pretty simply. I may just be overthinking the problem in this coding.

There are a couple of fairly fundamental problems with your approach.

You shouldn't use the delay() function because the Arduino can do nothing else during the delay period. Look at technique for managing time in the Blink Without Delay example sketch and in the demo several things at a time.

Also, you should not use a FOR (or WHILE) loop to go through the full series of steps. In each iteration of loop() the code should do one step which means that between each step it can check for a button press. This concept should also be visible in several things at a time.

You may also find some useful stuff in Planning and Implementing a Program

Make sure you are using a proper stepper motor driver board which just needs step and direction signals and not some sort of h-bridge such as a motor shield or L298.

...R

Thanks for the response. Regarding the delay, it's only in there for testing. It was the simplest way I saw to blink with a pause in between for my testing. The delay will not be in there when the actual function of the setup is being performed, but there's no need to overcomplicate a program needlessly, especially when testing. I don't need to do several things at a time in this scenario. Still, even after reviewing the "several things at a time" thread, I'm not sure how the alternative method would function, or be better, in terms of my needs for this program.

My problem seems to be more a problem of lack of knowledge of commands/variable usage and syntax sequencing for this language. I need an action to happen XX times, then stop. My 2 problems are:

  1. How can I pause between 2 increments (it is ok to finish the current blink/rotation, then pause) and then resume the incrementation?
  2. How can I wait for a button state, or check for a button state, before continuing back to the top of the loop?

If this were CNC G-code it would be a simple function of:
#140=(Button State 0 or 1)
N1(Main Loop)
IF[#140EQ1]GOTO20
GoTo50

N20 (Blink Loop)
#500=10(number of blinks)
#501=0 (Counter Reset)
#502=(Pause Button State 0 or 1)
While(#501LT#500)DO1
(LED On)
(LED Off)
IF[#502EQ1]GOTO30
GOTO40

N30(PAUSE TO ALLOW OPERATOR TO RELEASE BUTTON)
G4P3000
WHILE[#502LT1]DO2
G4P500
END2
N40(CONTINUE)
#501=#501+1
END1
N50 M99(End of PGM, Repeat)

And for my 2nd problem at the end, I would instead have:
(CHECK BUTTON STATE 0 BEFORE CONTINUING)
N50 WHILE[#501EQ1]DO1
G4P500
END1
N60M99 (End of PGM,Repeat)

With the proper M codes for LED states and system register locations for the button state, the above would work like I want. I just need to be able to translate that into code the arduino will take.

Oh, and I'm unsure on what you mean regarding "proper" driver board. For this project--since it's my first--I was just wanting to go cheap and easy. I've already ordered the Adafruit Motor Shield V2 and Stepper motor to go along with the Uno on my desk.

Maybe if you write the GCode as a series of one-line English statements I will understand what you mean.

If you have a series of events that follow one after the other and never need to be interrupted there is nothing wrong with using delay(). However most users here want to be able to press a button while something else is in progress and have the Arduino respond to the button before the something finishes. That is how I interpreted your original question.

If you want your code just to stop until a button is pressed you can use this (assuming a button press drives the pin LOW)

while (digitalRead(buttonPin) == HIGH) {
}

...R

I guess that I didn't make it clear above. The LED blinking function is only serving currently as a placeholder and testing section.

digitalWrite(13, HIGH);
delay(200);
digitalWrite(13, LOW);
delay(500);

Will not be in the final code. It will be replaced with a command for the stepper motor to rotate one full revolution. In terms of testing, this was the simplest method for me to turn the LED on and then back off with a small pause to be able to count.

I do not have to have a function in the while command? I figured I could dummy it with a delay or something, but the lack of having to have an command there simplifies it.

Here's the goal (let's say 100 revolutions):

  1. Start button pressed.
  2. Motor starts to rotate.
  3. If operator notices a problem on rotation 34 they can push the start button (or another button) to pause. They can hold this until the motor stops since I am doing a full revolution.
  4. They release the button, and then when the problem is fixed, press it again to resume.
  5. Next rotation continues counting where it left off.
  6. End of program & repeats.

On the other setup I need to make, similar function with no pause function needed--only a single rotation in this case. However, at the end, I do NOT want the program to loop back around until the start button has been released (it's an optical sensor, but let's assume that they held the button down the whole time the thing rotated) and then pressed again.

Ovrclck350:
3. If operator notices a problem on rotation 34 they can push the start button (or another button) to pause. They can hold this until the motor stops since I am doing a full revolution.

That is exactly what I had in mind when I said

However most users here want to be able to press a button while something else is in progress and have the Arduino respond to the button before the something finishes. That is how I interpreted your original question.

Using the technique in several things at a time can easily accommodate that. And it would not be necessary to wait for a revolution to complete unless you wanted to.

On the other setup I need to make, similar function with no pause function needed--only a single rotation in this case. However, at the end, I do NOT want the program to loop back around until the start button has been released (it's an optical sensor, but let's assume that they held the button down the whole time the thing rotated) and then pressed again.

I'm not sure I understand this so maybe this comment is wide of the mark. If you want something just to happen once you need a variable to record whether it has happened or not - for example jobDone = false. Your code only runs if (jobDone == false) and when the code is finished it sets jobDone = true; so it won't run a second time.

...R