Go Down

Topic: Need delay after digitalRead to make variables work (Read 14772 times) previous topic - next topic

freakdaddy

I went through a lot of trouble trying to get this code to work.  The program moves a motorized arm which has a limit switch to stop it in it's deployed position and a limit swith to stop it in it's retracted position.  There are two momentary buttons "deploy" and "retract".  I press deploy once and the sequence starts.  The arm extends then stops.  The problem is that the section of code that sets deploying=true; gets executed after the arm stops in its' deployed position.  There is no way possible for that code to execute unless the deploy button is pressed.  Watching the variables with a bunch of serial.print statements I could see that deployPressed (and armDown) remained true even though pin 6 was high. (internal pullups)  The arm takes 20 seconds to deploy so it isn't a bounce issue.  I eventually fixed it by creating a delay(20) right after I read the pins.  Now the variables deployPressed and armDown reflect the proper values.  Why is this delay necessary?  I makes me nervous that I may need one somewhere else and not know it.

Code: [Select]

boolean armDown=false;
boolean armUp=false;

boolean deployPressed=false;
boolean retractPressed=false;
boolean deploying=false;
boolean retracting=false;

void setup() {               
  //switches
  pinMode(9, INPUT);  // arm down
  digitalWrite(9, HIGH);
  pinMode(7, INPUT);  // arm up
  digitalWrite(7, HIGH);
  pinMode(6, INPUT);  // deploy
  digitalWrite(6, HIGH);
  pinMode(5, INPUT);  // retract
  digitalWrite(5, HIGH);

  //motors
  pinMode(8,OUTPUT); // arm motor
  digitalWrite(8, HIGH); 
}

void armMotorOn() {
   digitalWrite(8,false);
}

void armMotorOff() {
   digitalWrite(8,true);
}

void loop() {
  armDown=!digitalRead(9);
  armUp=!digitalRead(7);
  deployPressed=!digitalRead(6);
  retractPressed=!digitalRead(5);

  delay(20);  // This delay makes the variables reflect the correct value.
   
  if (deployPressed && !deploying && armDown && !retracting) {
    deploying=true;
  }

  if (retractPressed && !deploying && armUp && !retracting) {
    retracting=true;
  }

  if (!armUp && deploying) {
    armMotorOn();  //arm motor on
  }

  if (armUp && deploying) { //fully deployed - end deploy sequence
    armMotorOff();  //arm motor off
    deploying=false;
  }

  if (!armDown && retracting){
    armMotorOn();
  }

  if (armDown && retracting){
    armMotorOff();
    retracting=false;
  }
}


Brad Burleson

Code: [Select]
  delay(20);  // This delay makes the variables reflect the correct value.


I'm sorry, but I simply can't believe the above is true.

While a delay may make your program work, it's not because a delay is needed to set the variables.

Could you post the complete code and any info about external libraries used?

Brad (KF7FER)

nickgammon

I've stared at this code for 10 minutes and I'm still confused. Can't you rewrite with less "if" tests?

For example, instead of:

Code: [Select]

if (!armDown && retracting){
    armMotorOn();
  }

  if (armDown && retracting){
    armMotorOff();
    retracting=false;
  }


Code: [Select]

if (retracting)
  {
  if (armDown)
    {
    armMotorOff();
    retracting=false;
    }
  else
    armMotorOn();
  }  // end of retracting


My gut feeling is it is switch bounce. Who cares how long it takes the arm to retract? You are back at the start of loop a millisecond later. I suggest that if either switch changes state, then wait 10 or 20 milliseconds. That's your debounce.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics

freakdaddy


Code: [Select]
  delay(20);  // This delay makes the variables reflect the correct value.


I'm sorry, but I simply can't believe the above is true.

While a delay may make your program work, it's not because a delay is needed to set the variables.

Could you post the complete code and any info about external libraries used?

Brad (KF7FER)


You're looking at the whole program.

freakdaddy


I've stared at this code for 10 minutes and I'm still confused. Can't you rewrite with less "if" tests?

My gut feeling is it is switch bounce. Who cares how long it takes the arm to retract? You are back at the start of loop a millisecond later. I suggest that if either switch changes state, then wait 10 or 20 milliseconds. That's your debounce.


We care how long it takes for the arm to retract because in 20 seconds any bounce would surely be settled.  Look at the code...
Code: [Select]

if (deployPressed && !deploying && armDown && !retracting) {
    deploying=true;
}


Once you've started the arm moving by pressing deployPressed...  you step back and watch it happen.  deployPressed and armDown will never get touched again by either the device or a human.  Yet somehow deployPressed and armDown are still true 20 seconds later even though the pins are false.  I caught this because I put a serial.print statement right after reading the pins for debugging and it started working correctly.  So I switched in a delay and it worked too.   I can't stress enough that there should be no bounce 20 seconds later from both switches.

cmiyc

The problem is that what you are describing is the bouncing of the buttons.  The fact that a delay() settles out the input values highly suggests bouncing.

Because of all your if-and conditions, if the button pressed bounces a little or the button indicators for your arm bounces a little, your status variables might be "corrupted."

Try adding a cap to the buttons.  If a cap across the buttons solves the problem (without a delay()) then you know its bouncing.
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

freakdaddy


The problem is that what you are describing is the bouncing of the buttons.  The fact that a delay() settles out the input values highly suggests bouncing.

Because of all your if-and conditions, if the button pressed bounces a little or the button indicators for your arm bounces a little, your status variables might be "corrupted."

Try adding a cap to the buttons.  If a cap across the buttons solves the problem (without a delay()) then you know its bouncing.


I really don't understand how a switch could be bouncing 20 seconds after it is pressed.

mrdovey

Has something as simple as the following been tried?

Code: [Select]
void setup(void)
{  pinMode(9, INPUT);                  // arm down
   digitalWrite(9, HIGH);
   pinMode(7, INPUT);                  // arm up
   digitalWrite(7, HIGH);
   pinMode(6, INPUT);                  // deploy
   digitalWrite(6, HIGH);
   pinMode(5, INPUT);                  // retract
   digitalWrite(5, HIGH);
   pinMode(8,OUTPUT);                   // arm motor
   digitalWrite(8, HIGH); 
}

void loop(void)
{  while (digitalRead(6)) ;            /* Wait for deploy button              */
   digitalWrite(8,LOW);                /* Arm motor on                        */
   while (digitalRead(7)) ;            /* Wait for extended limit switch      */
   digitalWrite(8,HIGH);               /* Arm motor off                       */
   while (digitalRead(5)) ;            /* Wait for retract button             */
   digitalWrite(8,LOW);                /* Arm motor on                        */
   while (digitalRead(9)) ;            /* Wait for retracted limit switch     */
   digitalWrite(8,HIGH);               /* Arm motor off                       */
}

freakdaddy


Has something as simple as the following been tried?

Code: [Select]
void setup(void)
{  pinMode(9, INPUT);                  // arm down
   digitalWrite(9, HIGH);
   pinMode(7, INPUT);                  // arm up
   digitalWrite(7, HIGH);
   pinMode(6, INPUT);                  // deploy
   digitalWrite(6, HIGH);
   pinMode(5, INPUT);                  // retract
   digitalWrite(5, HIGH);
   pinMode(8,OUTPUT);                   // arm motor
   digitalWrite(8, HIGH); 
}

void loop(void)
{  while (digitalRead(6)) ;            /* Wait for deploy button              */
   digitalWrite(8,LOW);                /* Arm motor on                        */
   while (digitalRead(7)) ;            /* Wait for extended limit switch      */
   digitalWrite(8,HIGH);               /* Arm motor off                       */
   while (digitalRead(5)) ;            /* Wait for retract button             */
   digitalWrite(8,LOW);                /* Arm motor on                        */
   while (digitalRead(9)) ;            /* Wait for retracted limit switch     */
   digitalWrite(8,HIGH);               /* Arm motor off                       */
}



The deploy and extend buttons are momentary contact.

PeterH


I really don't understand how a switch could be bouncing 20 seconds after it is pressed.


If you're referring to the delay(20), that is 20 milliseconds, not 20 seconds.

mrdovey

Quote
The deploy and extend buttons are momentary contact.


That's what the code I posted is depending on (Don't hold 'em down - just press and release).

freakdaddy



I really don't understand how a switch could be bouncing 20 seconds after it is pressed.


If you're referring to the delay(20), that is 20 milliseconds, not 20 seconds.


No incorrect.  The arm takes 20 SECONDS to deploy after deployPressed is pressed.  There could be no switch bounce after 20 SECONDS. 

freakdaddy


Quote
The deploy and extend buttons are momentary contact.


That's what the code I posted is depending on (Don't hold 'em down - just press and release).


My mistake.  However this program will be expanded to do more.  First a door needs to open, arm extend, then turn on a light.  Then the process needs to reverse.  Light off, arm retract, door close.  I would have to see if that would all fit in the way you did it.  This part was only the first step.

mrdovey

You may have a different set of rules - but my rule #1 to to first verify that I have working hardware, and my rule #2 is to verify that it works the way I think it works.   :smiley-mr-green:

I'm not trying to write your application - I'm just trying to help you with those verifications. My tiny test loop doesn't depend on debounce or any of the fine touches you'll probably want to include later - it just exercises the buttons, motor, and limit switches in the most simple and idiot-proof way I could imagine (what I shoot for in my own projects).

I agree that you shouldn't need a delay.

freakdaddy

I think I have followed your rules.  My hardware works.  It works the way I think it should.  I do think there is an arduino bug here however.  Is there an issue reporting system in place for arduino?

Go Up