Pages: [1]   Go Down
Author Topic: 2 button fade control  (Read 2759 times)
0 Members and 1 Guest are viewing this topic.
MD, USA
Offline Offline
God Member
*****
Karma: 2
Posts: 663
A jack of all trades and a master of none!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm working on this to use 2 buttons to control fading of an LED. One button is used to increase the brightness of the LED in increments of 5 while the other button will decrease the brightness by 5.

The end goal is to set up 6 buttons and have full control of the color an RGB led produces. So maybe someone already has a better method of doing this.

Here is what i have so far.
Code:
 int redled = 10;    // assign LED to pin 10
  int button2 = 2;    // assign pushbutton 2 to pin 2
  int button3 = 3;    // assign pushbutton 3 to pin 3
  
  
  int button2State = 0;    // variable for reading the pushbuttons
  int button3State = 0;
  int fadered = 0;    // LED set to be off to start
  
 
  void setup () {
    pinMode(button2, INPUT);    //initialize pushbutton pins as input:
    pinMode(button3, INPUT);
  }
      
  void loop() {
    
    int button2State = digitalRead(button2);    //check button states
    int button3State = digitalRead(button3);
    
    if(button2State == HIGH && fadered <=250) { // if button is pressed increase brightness by 5
      fadered = fadered + 5;    // as long as brightness isn't greater then 250
      analogWrite(redled, fadered);    // lights LED at current brightness level
    
    }
        
    if (button3State == HIGH && fadered >=5) {    // if button is pressed decrease brightness by 5
      fadered = fadered - 5;    // as long as brightness isn't less then 5
      analogWrite(redled, fadered);    // lights LED at current brightness level
    
    }
   }

But all it does is turn the LED full on when the decrease button is pressed and off when the increase button is pressed. So what is wrong or what am i missing?
Logged

UK
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2884
Gorm deficient
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

See my reply to your query in "Bugs" and don't forget that "loop" will execute many times whilst your button is pressed.

Quote
have full control of the color an RGB led produces. So maybe someone already has a better method of doing this.
Use three pots and the "map" function.
« Last Edit: January 14, 2010, 10:22:56 am by GrooveFlotilla » Logged

Per Arduino ad Astra

MD, USA
Offline Offline
God Member
*****
Karma: 2
Posts: 663
A jack of all trades and a master of none!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Flipped the LED. That helped allot thanks.

Is there a better way to have the sketch see only one press per push without adding a delay to each of the if statements?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 631
Posts: 50107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Add another variable to keep track of the button state.

Read the button state.

If it is HIGH and it was LOW, do something. If it is LOW and it was HIGH, do something else.

Set the new variable to the current button state.
Logged

MD, USA
Offline Offline
God Member
*****
Karma: 2
Posts: 663
A jack of all trades and a master of none!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great idea. Thanks

But i think the delay will work best for now. That way the delay is set so a single push is registered only once but if i hold the button down i can still get multiple executions.
Logged

MD, USA
Offline Offline
God Member
*****
Karma: 2
Posts: 663
A jack of all trades and a master of none!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

one last question. For the buttons, do you have to have a 10k resistor or will most any resistor due. I have noticed that the Arduino errors out if there is no resistor but seams to do fine when i use a 100 ohm in place of the 10k.
Logged

UK
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2884
Gorm deficient
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Assuming you're talking about pull-ups, you don't need any external pull-ups, simply use the AVR's built-in ones, enabled by a "digitalWrite" to the appropriate input pin (after you've set the "pinMode").
Connect the switches between the input and ground, and remember this will invert your logic; a closed switch will read LOW.
« Last Edit: January 14, 2010, 11:20:33 am by GrooveFlotilla » Logged

Per Arduino ad Astra

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you are interested (Not sure it suits your application) here's some code that uses a single button to set the color of an LED then fade it in/out.

Click = Fade up
Double Click = Fade down

Press and hold puts you in a "menu" to set the color.
While in the setting mode, a single click steps up the current color (Reg. green or blue) in incriments of 10% from off to 100%. (11 steps) and a double click moves to the next color. Press and hold to exit the setting menu.

In practice, you go in to menu mode, then click-click-click-click until red is where you want it, then double-click to move to green, and click-click-click to set greens brightness, and double-click to start setting blue, etc. Press and hold to exit.

NOTE: the code is not very clean... it could use some tweaking/cleanup, etc. It's part of a larger project I'm working on, so it's not fully developed yet. At least, it may give you some ideas. (Atually, I like your press and hold to automatically step through values.... I may use that and require 2 press and hold events to exit the menu instead.)

Code:
/* 3-Way Button: Click, Double-Click, Press+Hold RGB Test Sketch
 By Jeff Saltzman
 Oct. 13, 2009
 Modified by Troy Ollom
 Jan. 6, 2010
 
 To keep a physical interface as simple as possible, this sketch demonstrates generating three output events from a single push-button.
 1) Click: rapid press and release
 2) Double-Click: two clicks in quick succession
 3) Press and Hold: holding the button down
 */

#define buttonPin 2 // analog input pin to use as a digital input
#define redPin 3 // digital output pin for LED 1
#define grnPin 5 // digital output pin for LED 2
#define bluPin 6// digital output pin for LED 3

// RGB LED variables
int rgbX [3] = {
  11,2,2};           // RGB Array
int rgbFactor = 11;      // Value to factor by.. IE, 100 would provide 100 steps 255 is Max
int randFlicker = 10;
int fadeValue = 0;       //tracks the current state of the fade value
boolean fadeDirection = false; // in this case, true means fade up, false means fade down
int colorMode = 0;
boolean menuMode = false;

//=================================================
// RGB Timing Variables
long rgbMillis = 0;      // Store millis to keep track of the last time rgb was updated
int rgbInterval = 30;    // How often to update the rgb values
//=================================================
void setup()
{
  // Set button input pin
  pinMode(buttonPin, INPUT);
  digitalWrite(buttonPin, HIGH );
  // Set LED output pins
  pinMode(redPin, OUTPUT);
  digitalWrite(redPin, 0);
  pinMode(grnPin, OUTPUT);
  digitalWrite(grnPin, 0);
  pinMode(bluPin, OUTPUT);
  digitalWrite(bluPin, 0);
}

void loop()
{
  // Get button event and act accordingly
  int b = checkButton();
  if (b == 1) clickEvent();
  if (b == 2) doubleClickEvent();
  if (b == 3) holdEvent();

  if (menuMode == true)
  {
    fadeValue =255;
  }
  if (millis () - rgbMillis >= rgbInterval){             // if it's been 30 ms since last time, lets update the LED
    rgbMillis = millis ();                               //reset so we know the last time
    if (fadeDirection == true){                          //This is gonna happen is we are fading UP
      if (fadeValue <=250) {                             // If fadeValue is less than or equalls 250
        fadeValue = fadeValue +5;                        // Lets add 5 to it
      }
      else {
        randFlicker = random(41);            
        fadeValue = 255 - randFlicker;                  // or else if it's already there, just make it 255 and flicker it there
      }
    }
    if (fadeDirection == false){                         //This is gonna happen if we are fading down
      if (fadeValue >=5) {                               // if its over or = to 5
        fadeValue = fadeValue - 5;                       // subtract 5 from it
      }
      else {
        fadeValue = 0;                                   // if it's less than 5 hold it at zero
      }

    }
    updateLED ();
  }
}

void updateLED ()
{
  analogWrite(redPin, fadeValue * rgbX[0] / rgbFactor);   //Now that the math has been done, update the LED
  analogWrite(bluPin, fadeValue * rgbX[1] / rgbFactor);
  analogWrite(grnPin, fadeValue * rgbX[2] / rgbFactor);
}

//=================================================
// Events to trigger by click and press+hold

void clickEvent() {
  if (menuMode == false){
    fadeDirection = true;
  }
  if (menuMode == true){
    rgbX[colorMode] = rgbX[colorMode]++;
    if (rgbX[colorMode] >= rgbFactor){
      rgbX[colorMode] = 0;
    }
    updateLED();
  }
}
void doubleClickEvent() {
  if (menuMode == false){
    fadeDirection = false;
  }
  if (menuMode == true) {
    colorMode = colorMode ++;
    if (colorMode >=3){
      colorMode = 0;
    }  
  }
}
void holdEvent() {
  menuMode = !menuMode;
 colorMode = 0;
}


/*
MULTI-CLICK: One Button, Multiple Events
 
 Oct 12, 2009
 Run checkButton() to retrieve a button event:
 Click
 Double-Click
 Hold
 Long Hold
 */

// Button timing variables
int debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 250; // max ms between clicks for a double click event
int holdTime = 2000; // ms hold period: how long to wait for press+hold event
int longHoldTime = 5000; // ms long hold period: how long to wait for press+hold event

// Other button variables
boolean buttonVal = HIGH; // value read from button
boolean buttonLast = HIGH; // buffered value of the button's previous state
boolean DCwaiting = false; // whether we're waiting for a double click (down)
boolean DConUp = false; // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true; // whether it's OK to do a single click
long downTime = -1; // time the button was pressed down
long upTime = -1; // time the button was released
boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false; // when held, whether to wait for the up event
boolean holdEventPast = false; // whether or not the hold event happened already

int checkButton()
{
  int event = 0;
  // Read the state of the button
  buttonVal = digitalRead(buttonPin);
  // Button pressed down
  if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce) {
    downTime = millis();
    ignoreUp = false;
    waitForUp = false;
    singleOK = true;
    holdEventPast = false;
    if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true) DConUp = true;
    else DConUp = false;
    DCwaiting = false;
  }
  // Button released
  else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce) {
    if (not ignoreUp) {
      upTime = millis();
      if (DConUp == false) DCwaiting = true;
      else {
        event = 2;
        DConUp = false;
        DCwaiting = false;
        singleOK = false;
      }
    }
  }
  // Test for normal click event: DCgap expired
  if ( buttonVal == HIGH && (millis()-upTime) >= DCgap && DCwaiting == true && DConUp == false && singleOK == true) {
    event = 1;
    DCwaiting = false;
  }
  // Test for hold
  if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
    // Trigger "normal" hold
    if (not holdEventPast) {
      event = 3;
      waitForUp = true;
      ignoreUp = true;
      DConUp = false;
      DCwaiting = false;
      //downTime = millis();
      holdEventPast = true;
    }
  }
  buttonLast = buttonVal;
  return event;
}



Logged

MD, USA
Offline Offline
God Member
*****
Karma: 2
Posts: 663
A jack of all trades and a master of none!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks TroyO i'll have a look threw your code.

Well everything is working great. I only have 5 10k resistors so one of the buttons has a 100 ohm on it. I'm not sure of what Groove is referring too. Do i add lines to the void setup or in the loop to tell it to digital write the buttons?

I found one other problem with my sketch. It seams pin 12 doesn't do analogWrite. so i adjusted things so the leds are on pins 9, 10, and 11.

Here is the final code for those interested.
Code:
/*
  RGB Color Wheel
  
  Indivigually control the brightness of a Red LED, Blue LED and
  Green LED using 6 pushbuttons attached to pins 2 thru 7. The
  pushbuttons on the even number pins will brighten the corosponding
  LED and the odd numbered ones will dim them. LEDs will be attached
  to pins 10, 11, and 12.
  
  The Circuit:
  * Red LED from pin 9 to ground threw a 220 Ohm resistor
  * Blue LED from pin 10 to ground threw a 220 Ohm Resistor
  * Green LED from Pin 11 to ground threw a 220 Ohm Resistor
  * pushbutton 1 attached to pin 2 from +5V
  * 10k resistor attached to pin 2 from ground
  * pushbutton 2 attached to pin 3 from +5V
  * 10k resistor attached to pin 3 from ground
  * pushbutton 3 attached to pin 4 from +5V
  * 10k resistor attached to pin 4 from ground
  * pushbutton 4 attached to pin 5 from +5V
  * 10k resistor attached to pin 5 from ground
  * pushbutton 5 attached to pin 6 from +5V
  * 10k resistor attached to pin 6 from ground
  * pushbutton 6 attached to pin 7 from +5V
  * 10k resistor attached to pin 7 from ground
  
  
  created 13 Jan 2010
  by digimike
  modified 14 jan 2010
  by digimike
  */
  
  
  int redled = 9;    // assign LEDs to pins
  int greenled = 10;
  int blueled = 11;
  int button2 = 2;    // assign pushbuttons to pins
  int button3 = 3;
  int button4 = 4;
  int button5 = 5;
  int button6 = 6;
  int button7 = 7;
  
  int button2State = 0;    // variable for reading the pushbuttons
  int button3State = 0;
  int button4State = 0;
  int button5State = 0;
  int button6State = 0;
  int button7State = 0;
  int fadered = 0;
  int fadegreen = 0;
  int fadeblue = 0;
 
 
 
  void setup () {
    pinMode(button2, INPUT);    //initialize pushbutton pins as input:
    pinMode(button3, INPUT);
    pinMode(button4, INPUT);
    pinMode(button5, INPUT);
    pinMode(button6, INPUT);
    pinMode(button7, INPUT);
  }
  
  void loop() {
    button2State = digitalRead(button2);    //check button state
    if(button2State == HIGH && fadered <= 250) {
      // if button is pressed increase brightness by 5
      // as long as brightness isn't greater than 250
      fadered +=5;
      analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    
    button3State = digitalRead(button3);    //check button state
    if (button3State == HIGH && fadered >= 5) {
      // if button is pressed decrease brightness by 5
      // as long as brightness isn't less than 5
      fadered -=5;
      analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    
    button4State = digitalRead(button4);    //check button state
    if (button4State == HIGH && fadegreen <= 250) {  
      // if button is pressed increase brightness by 5
      // as long as brightness isn't greater than 250
      fadegreen +=5;
      analogWrite(greenled, fadegreen);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    
    button5State = digitalRead(button5);    //check button state
    if (button5State == HIGH && fadegreen >= 5) {  
      // if button is pressed decrease brightness by 5
      // as long as brightness isn't less than 250
      fadegreen -=5;
      analogWrite(greenled, fadegreen);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    
   button6State = digitalRead(button6);    //check button state
    if (button6State == HIGH && fadeblue <= 250) {  
      // if button is pressed increase brightness by 5
      // as long as brightness isn't greater than 250
      fadeblue += 5;
      analogWrite(blueled, fadeblue);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
    
    button7State = digitalRead(button7);    //check button state
    if (button7State == HIGH && fadeblue >= 5) {  
      // if button is pressed decrease brightness by 5
      // as long as brightness isn't less than 250
      fadeblue -= 5;
      analogWrite(blueled, fadeblue);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }
  }    

Hope its as simple and clean as i wanted it to be. I like to try and keep things as simple as possible. The last time i did any amount of programing was on my old TI-85 calc using TIBasic. Doesn't take long for basic to eat up the little memory the calc had.

EDIT:
After reviewing TroyO's code i think i figured out what you meant about the buttons.
So my setup will now look like this, right?
Code:
void setup () {
    pinMode(button2, INPUT);    //initialize pushbutton pins as input:
    pinMode(button3, INPUT);
    pinMode(button4, INPUT);
    pinMode(button5, INPUT);
    pinMode(button6, INPUT);
    pinMode(button7, INPUT);
    digitalWrite(button2, HIGH);
    digitalWrite(button3, HIGH);
    digitalWrite(button4, HIGH);
    digitalWrite(button5, HIGH);
    digitalWrite(button6, HIGH);
    digitalWrite(button7, HIGH);    
  }
Then of course the if statements will be looking for the button to read LOW.  It works like a charm. Thanks.

Next i think i'll have the leds blink a couple of times if i hit the 255 max. Its hard to tell if its on full. its seams to be as bright as it will get at around 150. guess i should have it report back to the PC what teh level is. but i havn't gotten that far in learning this yet.
« Last Edit: January 14, 2010, 12:48:56 pm by digimike » Logged

Sussex UK / CT USA
Offline Offline
Edison Member
*
Karma: 0
Posts: 1028
Forums forever
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

In this sort of application, the problem of "switch bounce" can be a factor. Lots of things about that on the web. A less than perfect one at...

http://sheepdogguides.com/arduino/FA1inp1.htm
Logged

MD, USA
Offline Offline
God Member
*****
Karma: 2
Posts: 663
A jack of all trades and a master of none!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As of now all the kinks in the sketch are worked out. I went from using a red, a green, and a blue LED to using a single RGB LED. Problem was the RGB uses a common Anode and the sketchup was writen for the LEDs having a common Cathode. So i had to do some tweeking. For a while there i did have commands in there that blinked the LEDs once when it hit the 255 max. But took that out. I had it so that if the fade value was 255 it would use a digitalWrite to turn the LED off then back on again with a 1 second delay. But i didn't want any possible conflicts between the arduino using those pins as analogWrite then digitalWrite.

I'm at work right now but will post the completed code when i get home tonight. Overall the project isn't completed quite yet. When it is i'll post it in exhibition.

Next part that i'll be asking help on will be comunicating the brightness levels of the LEDs back to the PC. Fortunatly my wife has had some schooling on C and C++ so she is able to help. But since she doen't understand the hardware at all she has trouble with figuring out the initial code. But she is good with troubleshooting existing code for me.
Logged

UK
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2884
Gorm deficient
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But i didn't want any possible conflicts between the arduino using those pins as analogWrite then digitalWrite
So, you've already worked out which values for "analogWrite" set the LED full on, and those values that turn it off, so instead of blinking the LED with digitalWrite, use analogWrite instead.
Logged

Per Arduino ad Astra

MD, USA
Offline Offline
God Member
*****
Karma: 2
Posts: 663
A jack of all trades and a master of none!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Not sure if i'll incorperate that or not. But it was hlepful to have that blink to indicate full on. Once i get the unit reporting the values back to the PC there will be no need for the blink.

Here is the working code from the thread in the hardware section that just uses the red side of the RGB. Full code will be posted some time around 1 AM eastern.

Code:
/*
  created 14 Jan 2010
  by digimike
  modified 15 jan 2010
  by digimike
  */


  int redled = 9;    // assign LED to pin 9
  int redup = 2;    // assign pushbuttons to pins
  int reddown = 3;

  int r_btn_up = 0;    // variable for reading the pushbuttons
  int r_btn_down = 0;
  int fadered = -5;    // starting brightness values for each led


  void setup () {
    pinMode(redup, INPUT);    //initialize pushbutton pins as input:
    pinMode(reddown, INPUT);
    digitalWrite(redup, HIGH);
    digitalWrite(reddown, HIGH);
  }

  void loop() {
// increase the brightness
    r_btn_up = digitalRead(redup);    //check button state
    if(r_btn_up == LOW && fadered >= -250) {
      if(fadered == 255) {fadered = 0;} // if fade value is 255 (off) set it to 0
      // if button is pressed increase brightness by 5
      // as long as brightness isn't greater than -250
      fadered -=5;
      analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }

// decrease brightness
    r_btn_down = digitalRead(reddown);    //check button state
    if(r_btn_down == LOW && fadered <= -5) {
      // if button is pressed decrease brightness by 5
      // as long as brightness isn't less than -5
      fadered +=5;
      if(fadered == 0) {fadered = 255;}
      // when the fade value reaches 0, 255 is stored to the fade value to turn off the LED
      analogWrite(redled, fadered);  // lights LED at current brightness level
      delay(250);  // allows time so button won't be detected multiple times
    }

  }    
« Last Edit: January 15, 2010, 05:47:01 pm by digimike » Logged

Pages: [1]   Go Up
Jump to: