Go Down

Topic: working on buttons and can't find the problem. (Read 731 times) previous topic - next topic

M_Nateo

So I have some code written and it's triggered by some buttons on my board. I can't figure out why the code just goes on and starts even when the buttons are not pushed. It cycles threw them from the top sequence to the next one. here is a diagram of my wiring and my code. I'm not sure if these are the right switches, but in real life they are just simple momentary normally open pushbuttons. I'm sure I'm missing something easy. If you spot my error please point me in the right direction. Thanks!


Code: [Select]
const int ledpinG = 9; //ledpins
const int ledpinO = 10; //ledpins
const int ledpinHERD = 11; //ledpins
const int button1 = 3; //buttons
const int button2 = 4; //buttons
const int button3 = 5; //buttons
int valGHG = 0; //sets the value for the val
int valGH = 0; //sets the value for the val
int valGOHERD = 0; //sets the value for the val

void setup()  {
 pinMode(ledpinG, OUTPUT); // sets pin as OUTPUT
 pinMode(ledpinO, OUTPUT); // sets pin as OUTPUT
 pinMode(ledpinHERD, OUTPUT); // sets pin as OUTPUT
 pinMode(button1, INPUT); // sets pin as INPUT
 pinMode(button2, INPUT); // sets pin as INPUT
 pinMode(button3, INPUT); // sets pin as INPUT
 Serial.begin(9600); // opens a connection to the computer
}
 void loop()  {
   valGHG = digitalRead(button1); //reads button position
   valGH = digitalRead(button2); //reads button position
   valGOHERD = digitalRead(button3); //reads button position
   
   if(valGHG == HIGH)  {      //Checks to see if the button is "HIGH" and if it is runs the code below until the statement is false
     Serial.print("G");
 digitalWrite(ledpinG, HIGH);
 delay(600);
 Serial.print("O");
 digitalWrite(ledpinO, HIGH);
 delay(600);
 Serial.print("HERD!!!");
 digitalWrite(ledpinHERD,HIGH);
 delay(600);
 digitalWrite(ledpinHERD, LOW);
 digitalWrite(ledpinG, LOW);
 digitalWrite(ledpinO,LOW);
 delay(600);
Serial.print("\n\n\n\n");
   }
   if(valGH == HIGH)  {      //Checks to see if the button is "HIGH" and if it is runs the code below until the statement is false
     Serial.print("\nGO");
 digitalWrite(ledpinG, HIGH);
 digitalWrite(ledpinO,HIGH);
 delay(600);
 digitalWrite(ledpinG, LOW);
 digitalWrite(ledpinO,LOW);
 Serial.print("\nHERD");
 digitalWrite(ledpinHERD, HIGH);
 delay(600);
 digitalWrite(ledpinHERD, LOW);
 Serial.print("\nGO!!!");
  digitalWrite(ledpinG, HIGH);
  digitalWrite(ledpinO,HIGH);
 delay(400);
 digitalWrite(ledpinG, LOW);
 digitalWrite(ledpinO,LOW);
 delay(1000);
 Serial.print("\n\n\n\n");
}
    // end of program and loops
     
 }




crimony

Your inputs are floating when the buttons are open. You need to either:

1. Pull-down your inputs via 4.7k external resistors, or
2. swap your left-hand side connection to GND rather then +5V, enable the internal pull-ups on each input with digitalWrite(inputx, HIGH), and swap your logic so you test for LOW instead of HIGH (since your buttons are now pulling the inputs LOW when pressed.

M_Nateo

What do you mean. I want to solve the problem, but I also want to understand why I had the problem.



and

Code: [Select]
const int ledpinG = 9; //ledpins
const int ledpinO = 10; //ledpins
const int ledpinHERD = 11; //ledpins
const int button1 = 3; //buttons
const int button2 = 4; //buttons
const int button3 = 5; //buttons
int valGHG = 0; //sets the value for the val
int valGH = 0; //sets the value for the val
int valGOHERD = 0; //sets the value for the val

void setup()  {
 pinMode(ledpinG, OUTPUT); // sets pin as OUTPUT
 pinMode(ledpinO, OUTPUT); // sets pin as OUTPUT
 pinMode(ledpinHERD, OUTPUT); // sets pin as OUTPUT
 pinMode(button1, INPUT); // sets pin as INPUT
 pinMode(button2, INPUT); // sets pin as INPUT
 pinMode(button3, INPUT); // sets pin as INPUT
 Serial.begin(9600); // opens a connection to the computer
}
 void loop()  {
   valGHG = digitalRead(button1); //reads button position
   valGH = digitalRead(button2); //reads button position
   valGOHERD = digitalRead(button3); //reads button position
   
  digitalWrite(valGHG = HIGH); //sets the value for the buttons to originally be HIGH
  digitalWrite(valGH = HIGH);  //sets the value for the buttons to originally be HIGH
   
   if(valGHG == LOW)  {      //Checks to see if the button is "HIGH" and if it is runs the code below until the statement is false
     Serial.print("G");
 digitalWrite(ledpinG, HIGH);
 delay(600);
 Serial.print("O");
 digitalWrite(ledpinO, HIGH);
 delay(600);
 Serial.print("HERD!!!");
 digitalWrite(ledpinHERD,HIGH);
 delay(600);
 digitalWrite(ledpinHERD, LOW);
 digitalWrite(ledpinG, LOW);
 digitalWrite(ledpinO,LOW);
 delay(600);
Serial.print("\n\n\n\n");
   }
   if(valGH == LOW)  {      //Checks to see if the button is "HIGH" and if it is runs the code below until the statement is false
     Serial.print("\nGO");
 digitalWrite(ledpinG, HIGH);
 digitalWrite(ledpinO,HIGH);
 delay(600);
 digitalWrite(ledpinG, LOW);
 digitalWrite(ledpinO,LOW);
 Serial.print("\nHERD");
 digitalWrite(ledpinHERD, HIGH);
 delay(600);
 digitalWrite(ledpinHERD, LOW);
 Serial.print("\nGO!!!");
  digitalWrite(ledpinG, HIGH);
  digitalWrite(ledpinO,HIGH);
 delay(400);
 digitalWrite(ledpinG, LOW);
 digitalWrite(ledpinO,LOW);
 delay(1000);
 Serial.print("\n\n\n\n");
}
    // end of program and loops
     
 }


??

crimony

Your pins 3, 4 & 5 of X2 are open-circuit (floating) when the switches are not pressed, this will cause digitalRead() to return HIGH sometimes, and LOW sometimes. To make the reading reliable, you need to pull the inputs definitely LOW when the button is not pressed. You do this with a moderate-value resistor connected between the input pin and ground. When the button is not pressed, the input is pulled LOW. WHen the button is pressed, the input is pulled high by the +5V supply, and a small amount of current flows through the resistor.

See: http://en.wikipedia.org/wiki/Pull-down_resistor

The alternative if you don't want to add more hardware is to utilise the ATMega168's internal pull-up resistors on the input pins. You turn them on by writing a HIGH value to the pins when they are set to INPUT mode. You will need to change the other side of your switches to connect to the GND rather than +5V because when the switch is open, the internal pullup will drive the input HIGH. you will also need to change your code so that it interprets a LOW input value as "button pressed".

There is also an explanation in the Arduino tutorial on buttons, here: http://arduino.cc/en/Tutorial/Button.
.andy

M_Nateo

got it!! thanks so much! I used a 2.2k 1/2watt. It works with that is there any reason why that wouldn't be ok to use?

crimony

2.2k[ch8486] is fine. 1/2 watt is overkill, but won't make any difference. 5V across a 2.2k[ch8486] resistor will dissipate only 33 mW. You'd need to put 33V across it to dissipate 500 mW. (power in a resistor is V^2/R). Also this resistor will cause the arduino to sink 2.3 mA through the resistor when the button is pressed. Even with a 4 buttons pressed, that's only 9 mA, which the IC can easily handle.

retrolefty

#7
Aug 18, 2009, 03:20 am Last Edit: Aug 18, 2009, 03:22 am by retrolefty Reason: 1
Quote
Also this resistor will cause the arduino to sink 2.3 mA through the resistor when the button is pressed. Even with a 4 buttons pressed, that's only 9 mA, which the IC can easily handle.


Actually when using external pull-up or pull-down resistors, virtually no current is being sunk or sourced via the Arduino IC. A AVR input pin is a very high impedance input, so the current flowing through an external resistor is being sourced via the 5vdc regulator IC, not the Arduino. It's only when an AVR I/O pin is programmed as a output pin, does source or sink currents pin specifications come into play.

Lefty



Go Up