Go Down

Topic: button toggle (Read 2392 times) previous topic - next topic

chopeone1

i have had a look at a few pieces of code on 'toggling' and as i dont understand the use of boolean commands very well i opted to read the button state and use a counter to toggle between outputs, though i'm not sure if its the best way! I have written this piece of code but it doesn't quite work yet. when the button is pressed once the first led comes on and toggles off, the second led doesn't light up. when the first led is on it flickers.
Also the serial monitor only shows up a message when button press is 0 (every two button presses) which suggests that the button presses are being counted ok.

Code: [Select]
int button = 2;
int val;        
int val2;
int state;            
int press = 0;  
int led1Pin = 12;
int led2Pin = 13;


void setup() {
 pinMode(button, INPUT);
 Serial.begin(9600);        
 state = digitalRead(button);

}


void loop(){
 val = digitalRead(button);
 delay(10);          // wait 10 millis to counter debounce
 val2 = digitalRead(button); //check again to see if button is pressed
 

 
 if ((val == val2) && (val != state) && (val == HIGH)) {              
     press++;
   }
   if (press >1) {
   press = 0;
   Serial.print("press number");
   Serial.println (press);
 }
   if (press == 0) {
     digitalWrite(led1Pin, HIGH);
     delay (100);
     digitalWrite (led1Pin, LOW);
     
     
   }
   else {if (press == 1) {
     digitalWrite(led2Pin, HIGH);
     delay (100);
     digitalWrite (led2Pin, LOW);
   }
   }
 
 state = val;
}



this is what I am trying to do; one momentary push button input to toggle between two outputs.  the first button press and release to cause pin 13 HIGH for 100 millis. the second button press to cause pin 12 HIGH for 100 millis. these outputs just need to be single brief pulses to trigger another event.

thanks in advance for any suggestions.

PaulS

I'd start by declaring the led pins to be output pins, in setup.

I'm not sure what the reference to boolean commands is about, since you use no boolean variables.

Your code would be a lot easier to follow it it was uniformly indented. The IDE provides a tool to do that.

You might try turning one LED on when the button is pressed once, and turning the other one off.
When it is pressed again, reverse which one is on.

If all else fails, use the button library.

chopeone1

Thanks for that.  I don't know how i missed the setup mistake, i think i've been looking at the screen for too long!

The led's toggle as they're supposed to now. The only problem left is the flicker. i guess this is caused by the
Code: [Select]
if (press == 0) {
   digitalWrite(led1Pin, HIGH);
   delay (100);
   digitalWrite (led1Pin, LOW);
code running in a loop rather than just running once, is there a way to stop this?

chopeone1

#3
May 18, 2010, 10:55 pm Last Edit: May 18, 2010, 10:59 pm by chopeone1 Reason: 1
2nd problem: when i upload the sketch and it starts running the led on pin 12 lights up and stays on before a button has been pressed!

here is the code now
Code: [Select]
int button = 2;
int val;        
int val2;
int state;            
int press = 0;  
int led1Pin = 12;
int led2Pin = 13;


void setup() {
 pinMode(button, INPUT);
 pinMode(led1Pin, OUTPUT);
 pinMode(led2Pin, OUTPUT);
 Serial.begin(9600);        
 state = digitalRead(button);

}


void loop(){

 val = digitalRead(button);
 delay(10);          // wait 10 millis to counter debounce
 val2 = digitalRead(button); //check again to see if button is pressed

 if ((val == val2) && (val != state) && (val == HIGH)) {              
   press++;
 }
 if (press >1) {
   press = 0;
   Serial.print("press number");
   Serial.println (press);
 }
 if (press == 0) {
   digitalWrite(led1Pin, HIGH);
   delay (100);
   digitalWrite (led1Pin, LOW);


 }
 else {
   if (press == 1) {
     digitalWrite(led2Pin, HIGH);
     delay (100);
     digitalWrite (led2Pin, LOW);
   }
 }

 state = val;
}





Grumpy_Mike

Quote
the led on pin 12 lights up and stays on before a button has been pressed


So look at the initial states you gave your variables when you declared them.

chopeone1

i tried removing the 0 value declared at the start, also i tried setting it to a number other than 0 or 1 but the same thing still happens. i guess it is because the way i have designed the code there are only two possible states for it to be.

chopeone1

#6
May 19, 2010, 01:17 am Last Edit: May 19, 2010, 01:20 am by chopeone1 Reason: 1
fixed that one, i added an extra factor to switch the led on, so it couldnt be triggered till a button had been pressed. thanks.

Any ideas on how to stop the leds flicker? i just want them to send out one pulse.

PaulS

The loop function should not do anything unless a button is (being) pressed. When the button is being pressed, and was not before, do something.

You are already testing this. But, you need to move all the code for flashing the LED into that if block, instead of after it.

chopeone1

thanks for the advice, though im not sure what you mean by
Quote
But, you need to move all the code for flashing the LED into that if block, instead of after it.
could you explain a bit more? thanks.

chopeone1

#9
May 19, 2010, 12:18 pm Last Edit: May 19, 2010, 12:20 pm by chopeone1 Reason: 1
i worked it out eventually... thanks for all the help. Here is the working
Code: [Select]
/* button toggle - use one button to toggle between two outputs on different pins
  momentary push button attached to pin 2
  leds connected to pins 12 & 13
*/

int button = 2;  //button attached to pin 2
int val;        // reads the button state in loop
int val2;       // reads the button state a second time
int state;      // reads the button state in setup and stores it  could have called this button old    
int press = 1; // press counter, i set this to 1 so when the first button is pressed it will give a value of 0 activating the first pin
int led1Pin = 12; // led output 1
int led2Pin = 13; // led output 2
int button1hit = 0;  // secondary code switch stops code running before a button has been pressed


void setup() {
 pinMode(button, INPUT);
 pinMode(led1Pin, OUTPUT);
 pinMode(led2Pin, OUTPUT);
 Serial.begin(9600);        
 state = digitalRead(button);  // read button state and store it to reference against later
 
}


void loop(){

 val = digitalRead(button);
 delay(10);          // wait 10 millis to counter debounce
 val2 = digitalRead(button); //check again to see if button is pressed

 if ((val == val2) && (val != state) && (val == HIGH)) {              
   press++; // counts button presses
   button1hit = 1; //secondary code switch put in place
 }
 if (press > 1) {
   press = 0;    //when button press count passes 1 it resets to zero
   Serial.print("press number");
   Serial.println (press);
 }
 if (press == 0 && button1hit == 1) {
   digitalWrite(led1Pin, HIGH);
   delay (100);                  // send one pulse
   digitalWrite (led1Pin, LOW); // then stop
   button1hit = 0;              // wait for button to be pressed before doing anything else
   


 }
 else {
   if (press == 1 && button1hit == 1) {
     digitalWrite(led2Pin, HIGH);
     delay (100);
     digitalWrite (led2Pin, LOW);
     button1hit = 0;
   }

 }

 state = val;
}





I hope its useful to others!

PaulS

You could make this simpler.

This code:
Code: [Select]
 if (press > 1) {
   press = 0;    //when button press count passes 1 it resets to zero
   Serial.print("press number");
   Serial.println (press);
 }

can go inside this block:
Code: [Select]
 if ((val == val2) && (val != state) && (val == HIGH)) {              
   press++; // counts button presses
   button1hit = 1; //secondary code switch put in place
   // Put the above block here.
 }


Then, notice that you only set button1Hit to 1 in one place. Then, you test, in two places that it is == 1. You could make loop like this:
Code: [Select]
void loop()
{
 val = digitalRead(button);
 delay(10);          // wait 10 millis to counter debounce
 val2 = digitalRead(button); //check again to see if button is pressed

 if ((val == val2) && (val != state) && (val == HIGH))
 {              
   press++; // counts button presses
   if (press > 1)
   {
     press = 0;    //when button press count passes 1 it resets to zero
     Serial.print("press number");
     Serial.println (press);
   }

   if (press == 0)
   {
     digitalWrite(led1Pin, HIGH);
     delay (100);                  // send one pulse
     digitalWrite (led1Pin, LOW); // then stop
   }
   else
   {
     digitalWrite(led2Pin, HIGH);
     delay (100);
     digitalWrite (led2Pin, LOW);
   }
 }

 state = val;
}

Go Up