Pages: [1]   Go Down
Author Topic: help with buttons switching with number of pushes  (Read 373 times)
0 Members and 1 Guest are viewing this topic.
America
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a background in electronics and Circuit design but I'm new to micro-controllers and programming on the arduino. I'm still on the basics programming projects, but what i'm trying to do is get a single "button switch" to toggle between different LEDs and execute different functions.
can anyone tell me what i am doing wrong? I've tried multiple variations with no luck.

Code:
//Button Switch Circuit w/ Button Counter

const int greenled = 6;
const int buttonPin = 9;
const int yellowled = 10;
const int redled = 11;
int lastbuttonState = LOW;
int buttonPushCounter = LOW;
int buttonState = LOW;

void setup()
{
  pinMode(buttonPin, INPUT);
  pinMode(redled, OUTPUT);
  pinMode(yellowled, OUTPUT);
  pinMode(greenled, OUTPUT);
}

void loop ()
{
 buttonState = digitalRead(buttonPin);{
   if (buttonState == HIGH)
   {
    buttonPushCounter = (buttonPushCounter++);
   }
  if (buttonPushCounter = 0); {
    digitalWrite(redled, LOW);
    digitalWrite(yellowled, LOW);
    digitalWrite(greenled, LOW);
  }
  if (buttonPushCounter == 1) {
    digitalWrite(redled, HIGH);
  }
  if (buttonPushCounter == 2) {
    digitalWrite (yellowled, HIGH);
    digitalWrite (redled, HIGH);
  }
  if (buttonPushCounter == 4) {
    digitalWrite(greenled, HIGH);
    digitalWrite(yellowled,HIGH);
  }
  if (buttonPushCounter == 3) {
    digitalWrite (greenled, HIGH);
    digitalWrite (yellowled, HIGH);
    digitalWrite (redled, HIGH);
  }
  if (buttonPushCounter == 5) {
    digitalWrite (greenled, LOW);
    digitalWrite (yellowled, HIGH);
    digitalWrite (redled, LOW);
  }
  if (buttonPushCounter == 6) {
    digitalWrite (greenled, HIGH);
    digitalWrite (yellowled, LOW);
    digitalWrite (redled, LOW);
  }
  if (buttonPushCounter == 7) {
    digitalWrite (greenled, HIGH);
    digitalWrite (yellowled, LOW);
    digitalWrite (redled, HIGH);
  }
 }
}
this code was my attempt to get different combinations of LEDs to come on with the same button pressed over and over... sadly with no luck smiley-sad
« Last Edit: January 03, 2013, 11:02:15 pm by xpeerimental1 » Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3382
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  if (buttonState == HIGH)
   {
    buttonPushCounter = (buttonPushCounter++);
   }

Your loop will be running thousands of times per second, so the variable will increment very quickly. You need to detect transitions, not states. That is, you want to increment the variable when the switch goes from HIGH to LOW or LOW to HIGH. To do this, you need to keep track of the switch's last state and compare it to the current one. The StateChangeDetection (I think that is what it is called) tutorial under the Digital section shows you how to do this.

It looks like you have declared a last state variable but don't ever check it or update it.

  
Code:
if (buttonPushCounter = 0); {

All your other if statements look correct, but this one doesn't.

Code:
buttonState = digitalRead(buttonPin);{
...
}

These set of curly brackets are unnecessary and distracting.
« Last Edit: January 02, 2013, 02:25:03 pm by Arrch » Logged

Malaysia
Offline Offline
Sr. Member
****
Karma: 7
Posts: 393
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

well first you need to debounce the switch. you can do it in software or even hardware which ever you prefer.
then you need to make the arduino remember button state previous and current state compare them both if its not the same something must have happen. so lets say that if you push the switch and the arduino register it as a low then what you should do is if the previous high and current low increment switch press count.
ok now for the fun bit if the switch is 0 do something,1 do something,3 do something and lastly 4 do something. howver you need some programming wonder to make after 4 become a 0. i hope this help as a guide.
btw if im not mistaken ladyada have something along that line that you want to do
heres the link http://www.ladyada.net/learn/arduino/lesson5.html
Logged

Barcelona
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
Indeed
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Right so I cleaned up your program and added three functions one light (Lighter(boolean, boolean, boolean), one to detect the button has been pressed (ButtonChange()) and the last is simply a debounce function. I used a switch case stament to select LED pattern, though not the nicest or shortest it is way faster than using an array.

Code:
//LED Pins
const int greenLED = 6;
const int yellowLED = 10;
const int redLED = 11;

//Button Pin
const int buttonPin = 9;

//Variables for Debounce (Button has to be pressed for a certain amount of time for press to count)
const int debounceDelay = 10;                                           //miliseconds the button has to be pressed for press to count
boolean state;                                                          //actual state of button (for debounce)
boolean previousState;                                                  //last state of button  (for debounce)

int buttonPushCounter = 0;                                              //counts presses
boolean buttonState = 0;                                                //actual state of button, LOW
boolean lastButtonState = 0;                                            //last state of button, LOW
int numberofPatterns = 7;                                               //number of patterns indexed to whatever cases are (this case 0 indexed, 0 to 7)
void setup() {
  pinMode(buttonPin, INPUT);
 
  pinMode(redLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
}

void loop () {
  if (ButtonChange() == HIGH) {                                          //if button has been pressed
    if (buttonPushCounter > numberofPatterns) {                          //if counter exeeds max reset to index(0)
      buttonPushCounter = 0;
    }
    switch (buttonPushCounter) {                                         //depending on counter value choose a case
      case 0:
        Lighter(0,0,0);
        break;
      case 1:
        Lighter(1,0,0);
        break;
      case 2:
        Lighter(1,1,0);
        break;
      case 3:
        Lighter(1,1,1);
        break;
      case 4:
        Lighter(0,1,1);
        break;
      case 5:
        Lighter(0,1,0);
        break;
      case 6:
        Lighter(0,0,1);
        break;
      case 7:
        Lighter(1,0,1);
        break;
    }
    buttonPushCounter++;                                                 //increment counter by one
  }
}

boolean ButtonChange() {                                                 //returns HIGH if there has been a change in button state from last scan
    lastButtonState = buttonState;                                       //store latest state
    buttonState = debounce(buttonPin);                                   //update buttonState with debounced value of buttonPin
    if (lastButtonState != buttonState && buttonState == HIGH) {         //if there is a change in button state and it is now HIGH(pressed)
      return HIGH;
    }
  return LOW;
}

void Lighter(boolean redState, boolean yellowState, boolean greenState) {//lights the threeLEDs to the values redState, yellowState and greenState
  digitalWrite (redLED, redState);
  digitalWrite (yellowLED, yellowState);
  digitalWrite (greenLED, greenState);
}

boolean debounce(int pin) {                                              //returns HIGH if button if HIGH for debounceDelay in miliseconds
  previousState = digitalRead(pin);                                      //store pin state
  for (int i = 0; i < debounceDelay; i++) {                              //make sure button is pressed every milisecond debounceDelay times
    delay(1);
    state = digitalRead(pin);
    if (state != previousState) {                                        //reset if change in state
      i = 0;
      previousState = state;
    }
  }
  return state;                                                          //return stable state
}

I commented everything to be sure you get it cause I'm not sure of your programing level. I've compiled this and tested it so I'm sure it works. Hope I help.
Keep making!!
Logged

America
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

my programming level is still pretty low at this point, but thanks for the help Ron! I've been doing my best with a few bits and bobs here and there along with several youtube videos. but that helped me out a ton!  smiley
i'm gonna dissect the code you provided and try and wrap my head around what i was doing wrong.
(wrong approach probably).
I do have a question about how the "lighter" and "case" aspect of the code came to be and what those actually do..
sorry if that's a dumb question...
--
i just did some research before posting what i have written and may have answered my own question.
"case" = a function and "lighter" is just the label you chose?
you may have just opened my eyes to a new world of functions! lol
Thanks again!
Code:
switch (buttonPushCounter) {                                         //depending on counter value choose a case
      case 0:
        Lighter(0,0,0);
        break;
      case 1:
        Lighter(1,0,0);
        break;
      case 2:
        Lighter(1,1,0);
        break;
      case 3:
        Lighter(1,1,1);
        break;
      case 4:
        Lighter(0,1,1);
        break;
      case 5:
        Lighter(0,1,0);
        break;
      case 6:
        Lighter(0,0,1);
        break;
      case 7:
        Lighter(1,0,1);
        break;
    }
    buttonPushCounter++;                                                 //increment counter by one
  }
« Last Edit: January 03, 2013, 11:01:23 pm by xpeerimental1 » Logged

America
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

im a noob, and as i look over the code provided i have more questions.

Quote
void loop () {
  if (ButtonChange() == HIGH) {                                          //if button has been pressed
    if (buttonPushCounter > numberofPatterns) {                          //if counter exeeds max reset to index(0)
      buttonPushCounter = 0;
    }
    switch (buttonPushCounter) {                                         //depending on counter value choose a case
      case 0:
        Lighter(0,0,0);
        break;
      case 1:
        Lighter(1,0,0);
        break;
 

if i were to add more LEDs in the circuit would i just extend the code.after adding the values to setup and making "int".. for example=lighter(0,0,0,0,0)
and are the "breaks" necessary? is that what sustains the value and keeps that portion of the program running?
« Last Edit: January 03, 2013, 11:03:15 pm by xpeerimental1 » Logged

Malaysia
Offline Offline
Sr. Member
****
Karma: 7
Posts: 393
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

if you want to extend it you need to edit the function call first if not you will get error.
for the break u need that so that it will not over flow to the next call.
Code:
      case 0:
        Lighter(0,0,0);
      case 1:
        Lighter(1,0,0);
        break;
if case 0 happen, first it will follow  Lighter(0,0,0) immediately after that it will go to Lighter(1,0,0) since most dont like that to happen, you should put a break in it to control the flow.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
// let's suppose a pushbutton is connected between pin 4 and ground
// the button is active low (LOW when pressed)
byte btnPin = 4;
byte btnState = HIGH;
byte btnPrevState = HIGH;

unsigned long btn_prevMillis;
unsigned long btn_interval = 30;        // check the button every 30 ms


void btnPressed() {
    buttonPushCounter++
    if (buttonPushCounter > numberofPatterns) {                          //if counter exeeds max reset to index(0)
        buttonPushCounter = 0;
    }
}


void btnReleased() {
}


void setup() {
    pinMode(btnPin, INPUT);
    digitalWrite(btnPin, HIGH);        // activate internal pullup
}


void loop() {

    // button section
    if (millis() - btn_prevMillis >= btn_interval) {
        btnState = digitalRead(btnPin);

        if ((btnPrevState == HIGH) && (btnState == LOW)) {
            btnPressed();
        }
        else if ((btnPrevState == LOW) && (btnState == HIGH)) {
            btnReleased();
        }

        btnPrevState = btnState;
    }

   
    // pattern section
    switch (buttonPushCounter)  {
        // etc.
    }
}
Logged

Barcelona
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
Indeed
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Right,
so switch case stament (no case without switch):
Code:
switch (nameofVar) {
  case 0:            //if (namodVar == 0) {}
    digitalWrite(redLED, HIGH);
    digitalWrite(greenLED,LOW);
    digitalWrite(yellowLED, HIGH);
    break;           //stop reading here and exit switch
  case 1:
    digitalWrite(redLED, LOW);
    digitalWrite(greenLED,LOW);
    digitalWrite(yellowLED, HIGH);
    break;
  case 2:
  [...]
Instead of copying all that (
Quote
digitalWrite(redLED, LOW);
    digitalWrite(greenLED,LOW);
    digitalWrite(yellowLED, HIGH);
)over and over
since all that changes is whether (name)LED goes HIGH or LOW
you call a function and feed it the variables nad it'll fit them into the
repeated part. So Lighter(1, 0, 1) would do the same as all the digitalWrites() and the order of the values determines the color(first red, then yellow, then green);

If you were to add more LEDs (as ash901226 posted) you'd modify the function
Code:
void Lighter(boolean redState, boolean yellowState, boolean greenState/*, add boolean colorState as much as needed*/) {
  digitalWrite (redLED, redState);
  digitalWrite (yellowLED, yellowState);
  digitalWrite (greenLED, greenState);
  //add digitalWrites() for every new LED;
}
and of course declare pins, variables, set pin mode() etc...
Logged

Barcelona
Offline Offline
Jr. Member
**
Karma: 0
Posts: 58
Indeed
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

To me though there is a nicer way to do this (add LEDs and/or patterns): using MULTIDIMENSIONAL ARRAYS!!  smiley-cool and Arrays

From http://arduino.cc/en/Reference/Array:
An array is a collection of variables that are accessed with an index number.
All of the methods below are valid ways to create (declare) an array.
Code:
  int myInts[6];
  int myPins[] = {2, 4, 8, 3, 6};
  int mySensVals[6] = {2, 4, -8, 3, 2};
  char message[6] = "hello";

So a MULTIDIMENSIONAL ARRAY would be one array with other arrays inside it: in this case, to hold patterns:
Code:
LEDPattern[numberofPatterns][numberofLEDs] {
  {0, 0, 0} ,
  {1, 0, 0} ,
  {1, 1, 0} ,
  {1, 1, 1} ,
  {0, 1, 1} ,
  {0, 1, 0} ,
  {0, 0, 1} ,
  {1, 0, 1}
};

We'll use a array to store LEDPins to make the code even shorter.
Thanks to both arrays mentioned a simple for(){} loop can get the job done and adding and changing patterns or LEDs will be much easier (and faster)
Note:(didn't post this yesterday cause for some reason it was slow).

We'd end up with:
Code:
//LED Pins
const int numberofLEDs = 3;
const int LEDPin[numberofLEDs] = {22, 23, 24};                          //array for pin numbers in color order of pattern (red, yellow, green)
//Button Pin
const int buttonPin = 3;

//Variables for Debounce (Button has to be pressed for a certain amount of time for press to count)
const int debounceDelay = 10;                                           //miliseconds the button has to be pressed for press to count
boolean state;                                                          //actual state of button (for debounce)
boolean previousState;                                                  //last state of button  (for debounce)

int buttonPushCounter = 0;                                              //counts presses
boolean buttonState = 0;                                                //actual state of button, LOW
boolean lastButtonState = 0;                                            //last state of button, LOW
const int numberofPatterns = 7;                                         //number of patterns indexed to whatever cases are (this case 0 indexed, 0 to 7)

const int LEDPattern[(numberofPatterns + 1)][numberofLEDs] = {          //multidimensional array ([var] in declaration, index 1. When accessing, index 0
  { 0, 0, 0 } ,                                                           //LEDPattern[0][0] will access the first value in this row
  { 1, 0, 0 } ,
  { 1, 1, 0 } ,
  { 1, 1, 1 } ,
  { 0, 1, 1 } ,
  { 0, 1, 0 } ,
  { 0, 0, 1 } ,
  { 1, 0, 1 }
};

void setup() {
  pinMode(buttonPin, INPUT);
 
  for (int i = 0; i < numberofLEDs; i++) {                               //Taking advantage of LEDPin array(when you add more LEDs this stays the same)
    pinMode(LEDPin[i], OUTPUT);
  }
}

void loop () {
  if (ButtonChange() == HIGH) {                                          //if button has been pressed
    if (buttonPushCounter > numberofPatterns) {                          //if counter exeeds max reset to index(0)
      buttonPushCounter = 0;
    }
    for (int i = 0; i < numberofLEDs; i++) {                             //once per LED
      digitalWrite(LEDPin[i], LEDPattern[buttonPushCounter][i]);         //access array to know Pin, acces multidimesional to know state
    }                                                                      //(depends on pattern number and Led number)
    buttonPushCounter++;                                                 //increment counter by one
  }
}

boolean ButtonChange() {                                                 //returns HIGH if there has been a change in button state from last scan
    lastButtonState = buttonState;                                       //store latest state
    buttonState = debounce(buttonPin);                                   //update buttonState with debounced value of buttonPin
    if (lastButtonState != buttonState && buttonState == HIGH) {         //if there is a change in button state and it is now HIGH(pressed)
      return HIGH;
    }
  return LOW;
}

boolean debounce(int pin) {                                              //returns HIGH if button if HIGH for debounceDelay in miliseconds
  previousState = digitalRead(pin);                                      //store pin state
  for (int i = 0; i < debounceDelay; i++) {                              //make sure button is pressed every milisecond debounceDelay times
    delay(1);
    state = digitalRead(pin);
    if (state != previousState) {                                        //reset if change in state
      i = 0;
      previousState = state;
    }
  }
  return state;                                                          //return stable state
}

Don't get this:
Quote
making "int"..
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18806
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@xpeerimental1

Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the # button above the posting area.
Logged


Pages: [1]   Go Up
Jump to: