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.
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;
}
}
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:
if (!armDown && retracting){
armMotorOn();
}
if (armDown && retracting){
armMotorOff();
retracting=false;
}
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.
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.
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.
Has something as simple as the following been tried?
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 */
}
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.
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.
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 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?
I honestly don't know, but if you're certain it isn't you the first board listed on the forum index page is listed as being for Arduino problems. Give it a try.
freakdaddy:
[...]I do think there is an arduino bug here however.
Ok. What I'd do first is try to describe the bug. Then I'd try to write a test sketch that would show the problem.
Sometimes the simple act of trying to explain what you expect from your code and what you get instead makes you understand where the problem (and the solution) lies.
(hint: 99% of times it's not in the platform).
freakdaddy:
Is there an issue reporting system in place for arduino?
freakdaddy:
[...]I do think there is an arduino bug here however.
Ok. What I'd do first is try to describe the bug. Then I'd try to write a test sketch that would show the problem.
Sometimes the simple act of trying to explain what you expect from your code and what you get instead makes you understand where the problem (and the solution) lies.
(hint: 99% of times it's not in the platform).
freakdaddy:
Is there an issue reporting system in place for arduino?
I think you're right into it
If I read the problem description correctly, this really does sound like a =hardware= problem. Not with switch bounce, but possibly with something happening when the motor is operating and/or stopped. Liberal application of capacitors across =all= switches, as well as a beefier cap across the power supply, might help.
For a test, I'd suggest disconnecting the motor, then pressing the various buttons by hand. And I'd still add the caps. Starving children in China need us to buy more capacitors ...
You mean "even though the pins are true" I hope, since you are doing "not" what the pins read.
Pins are not true or false, they are HIGH or LOW. Let's get the terminology straight.
Can you describe the hardware a bit more? Which end is the armUp button? Before you start submitting bug reports about the Arduino, better get straight what is happening. If you swapped the armUp and armDown tests (ie. the switches are mis-wired) this might account for some of what you see.
I recall another thread not that long ago where I suggested a wiring error. "Absolutely not!" the poster declared. "Photo?" I replied. About 4 or 5 pages in (I'm not kidding) there was an "oops, I made a wiring mistake".
{Had to edit... Sorry I posted before I was done typing!!!!]
I will certainly run more tests before submitting a bug. What bothers me is this... I inserted all kinds of serial.print statements to see what was happening. I even put one in the main loops to watch it the whole time to see if I could see bounces. Here is what happened...
(pseudo code)
now because deploying=false the code above will never execute again for the time being. It takes around 20 seconds to fully extend the arm.
4.5 SerialA.print is repeating 0 1 0 0 <- You would think that deployPressed and armDown would be false as well
arm is done deploying and code elsewhere sets deploying=false.
SerialA.print shows 0 0 0 0
code above executes again because deploying is now false AND deployPressed and armDown are STILL TRUE. Remember that deployPressed and armDown were last touched 20 seconds ago.
7 serialB.print shows 1 0 1 0 <- should not be