Can not get button press recognized with in do while loop

this is an exorcise where i am pushing a button to open a gate, then press it again to close.

the push button works fine in the loop() function to get started

but within the sub Move_The_Motor I want the push button to interrupt the movement and return
but it ignores it.

I do not have the open/close sensors hooked up yet … I want to get this working first
(besides, I cant get those switches to be seen in that function either … ???)

whatever the problem is here, it is messing me up with several projects.


const int Request_Button = 4;      // this is the open and close button
const int Pot_Setting = A1;          // pin where we get the requested spd
const int Motor_Spd_Pin = 5;       // this is the pin where we send the speed
const int Gate_Direction = 7;       // this is the pin where we send dir info
const int Closed_Sensor = 11;      // these pins are from the limit switches
const int Open_Sensor = 2;
unsigned long Previous_Time = 0; // the time var's are for timing the opening
unsigned long Current_Time = 0;   // and closing making sure it isn't stuck
int Gate_Speed = 0;                    // var to hold pot setting
int(Requested_Action) = 0;           // open or close variable
void setup()
  pinMode(Gate_Direction, OUTPUT);             // pin 7
  pinMode(Closed_Sensor, INPUT_PULLUP);        // pin 11
  pinMode(Open_Sensor, INPUT_PULLUP);          // pin 2
  pinMode(Request_Button, INPUT_PULLUP);       // pin 4
  pinMode(Pot_Setting, INPUT);                 // pin A1

void loop()
  if (digitalRead(Request_Button) == 0)     //  Pin 4 grounded
    Move_The_Gate(Requested_Action);      // call the motor mover
    if (!Requested_Action)
      Requested_Action = 1;                      // toggle the open/close var
      Requested_Action = 0;

void Move_The_Gate(int request)
  Previous_Time = millis();
  if (request == 1)
    digitalWrite(Gate_Direction, HIGH);
    digitalWrite(Gate_Direction, LOW);
    Gate_Speed = analogRead(Pot_Setting);        // pin A1 - get requested speed
    Current_Time = millis();
    if (Current_Time - Previous_Time >= 4000)   // after 6 secs turn motor off and return
      analogWrite(Motor_Spd_Pin, 0);
    analogWrite(Motor_Spd_Pin, Gate_Speed);     // if it gets this far we can turn motor on
    if (digitalRead(Request_Button) == 0)           // trying to stop movement with another push
    {                                                             // of the button. It ignores this for some reason.
      analogWrite(Motor_Spd_Pin, 0);
  while (true);

The answer is very easy: ‘Don’t use while or for loops! (And don’t use delay).’

Or less restrictive, use for and while to iterate, not for any timing.

Use the ‘Blink Without Delay’ principle to handle normal timing,
if the timing has to be extremly accurate, use hardware timer.

The demo Several Things at a Time is an extended example of BWoD. It may help with understanding the technique.


thanks guys ... Robin .. studied your code .. I think it will help a lot thanks.

Mandall .. wow, I am so disappointed that you can't turn a motor on and and check for the switches inside a while or for loop.

I'm not asking for timing. Just for the things in the loop to work.

Anyways ..

Thanks 'MIke

MikeAmick: wow, I am so disappointed that you can't turn a motor on and and check for the switches inside a while or for loop.

You can. What Whandall is saying that it's not the correct approach. The loop() function is already called thousands of times per second so there is no need for a while loop for this purpose.

Whatever your problem exactly is, I suspect the following happens:

When you push the button, you call Move_The_Gate() from loop()

In your while loop, you check the time Not time yet, control the motor using analogWrite Check button

Now this takes a less than a microsecond, so more than likely your button is still detected as being pressed (leaving bouncing out of the equation). So you return to loop() and change the direction (requestedAction).

And as the button probably is still detected as pressed, you will call Move_The_Gate() again.

And so on and so on.

Not to mention that if you release the button while in loop(), Move_The_Gate() is never called and your gate will keep on moving.

You need to go back to the drawing board ;) You might also want to consider that you want to wait till you detected that the button is released before detecting that it is pressed again (and take bouncing into account).

PS Adding Serial.print statements at strategic places in your code will help you to understand what your code is actually doing.

Ok Thanks Starretje ..

and no .. I wasn't insinuating that Whandall was saying it can't be done .. but .. that it is a bad technique. I do understand that. Sorry if I made it sound that way.

the button press is actually a remote controlled relay. Momentary contact. not that .. that would prevent bounce.

I have been working on new code that does the ol time comparison for debounce.

thanks again Mike

MikeAmick: wow, I am so disappointed that you can't turn a motor on and and check for the switches inside a while or for loop.

I'm commenting on this AFTER reading Reply #5

I think the confusion here is because we humans multi-task unconsciously (yes, even men) whereas an Arduino is very strictly a single-tasking computer.

The way to get a single-tasking computer to appear to multi-task is to break each task into tiny pieces that each takes only a few micro- or millisecs to complete so that loop() can repeat very frequently.

And there is another issue - it is not a good idea to duplicate code, for example by repeating a line of code for reading a button in two different places. It is too easy to get confused and, when changes are needed, forget to update one of the copies. If the program is designed to allow loop() to repeat frequently it will only be necessary to read the button in one place.