Pages: [1]   Go Down
Author Topic: Push Button as On/ Off Switch  (Read 6068 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm new to Arduino and I'm still just figuring out the basics and I can't seem to figure out what's wrong with the coding or if I'm going about it the wrong way.  I'm trying to make it so when you press a push button a circuit will turn on and stay on until it is pushed again, and be able to do this over and over.



int blue=12;// 1st LED
int red=10;//2nd LED
int yellow=11;//3rd LED
int buttonpin=2;
int reading;//push button state
int ctr=0;//counter for button presses


void setup(){
  pinMode(red, OUTPUT);
  pinMode(yellow, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(buttonpin, INPUT);
}

void loop(){
  reading=digitalRead(buttonpin);//reads the push button

    if(reading==HIGH){
      ctr++;//if button is pressed, counter goes up by one
  }
  //I figured when you want the circuit ON the button
  //will have been pushed an odd amount of times so the
  //LEDs blink on and off when ctr is odd
    if(ctr%2!=0){

    digitalWrite(yellow,HIGH);
    digitalWrite(red,LOW);
    digitalWrite(blue,LOW);
    delay(100);
   
    digitalWrite(yellow,LOW);
    digitalWrite(red,HIGH);
    digitalWrite(blue,LOW);
    delay(100);
   
    digitalWrite(yellow,LOW);
    digitalWrite(red,LOW);
    digitalWrite(blue,HIGH);
    delay(100);
   
    digitalRead(buttonpin);

    }
  //LEDs turn off when ctr is even
  if(ctr%2==0){
  digitalWrite(yellow,LOW);
  digitalWrite(red,LOW);
  digitalWrite(blue,LOW);
}
}
   

Any help that anyone can provide is greatly appreciated.

Thanks. 
   
   
 
   
Logged

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

To use a momentary push-button as a toggle switch, you need to use a technique called signal edge detection. Knowing when the button is HIGH or LOW isn't going to help because the loop will run thousands of times per second. What you need is to find the moment where the button switches states, called the signal edge. To do this, you simply need to keep track of what the last reading was and compare it to the current reading.
Logged

SE USA
Offline Offline
Faraday Member
**
Karma: 41
Posts: 3783
@ssh0le
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

you never reset the button variable so after the first time it is always !=0

your also not keeping track of single pushes, the loop is running millions of times a second so if you printed out your counter to the serial monitor, I bet it skyrockets very quickly (use the serial monitor like it was your air supply when figuring things out!)

so in a practical application ... something like

Code:
// bytes are half the size of int's, but restricted to a max value of 255
byte button;
byte oldbutton = 0;
byte buttonpin = 2;
byte state = 0;

void setup()
{
  pinMode(buttonpin, INPUT);
}

void loop()
{
  digitalRead(buttonpin);
  if(button && !oldbutton) // same as if(button == high && oldbutton == low)
  {
    //we have a new button press
    if(state == 0) // if the state is off, turn it on
    {
      //do stuff
      state = 1;
    }
    else // if the state is on, turn it off
    {
      //do stuff
      state = 0;
    }
    oldbutton = 1;
  }
  else if(!button && oldbutton) // same as if(button == low && oldbutton == high)
  {
    // the button was released
    oldbutton = 0;
  }
}

PS: highlight your code and hit the # icon in the editor for future reference, it makes life much easier
Logged


Johannesburg. UTC+2
Online Online
Faraday Member
**
Karma: 82
Posts: 3840
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You don't say what the problem is!- what's not going right for you here? Difficult to help if we don't know what's wrong...

In principle that would work yep, but switches have bounce in them and so that might be screwing your count.

What you're doing is similar to this but which debounces the switch as also explained here

Have you got a pull-down on the switch as shown in those links?- if not, its state might not be 0 when its not pressed.

And lastly a tip: please wrap your code in the code tags using the # button above the smilies- makes it muuuuuch easier to read.

HTH,

Jim

Edit.... oh yes, and what Osgeld said about the counter  smiley-cool
« Last Edit: July 15, 2012, 12:21:30 am by JimboZA » Logged

Although I answer in good faith, remember always: Your Mileage May Vary.
Get me on LinkedIn: za.linkedin.com/in/jimbrownza/

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

Thanks everyone for the help.  Osgeld I ended up basing my final code on what you put up with some extra things to make it work for my specific project.
Logged

Illinois, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 114
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Osgeld
I can't seem to get your above code working.

My full code:
Code:
// bytes are half the size of int's, but restricted to a max value of 255
byte button;
byte oldbutton = 0;
byte buttonpin = 2;
byte state = 0;

void setup()
{
  pinMode(buttonpin, INPUT);
  pinMode(12, OUTPUT);
}

void loop()
{
  digitalRead(buttonpin);
  if(button && !oldbutton) // same as if(button == high && oldbutton == low)
  {
    //we have a new button press
    if(state == 0) // if the state is off, turn it on
    {
      digitalWrite(12, HIGH);
      state = 1;
    }
    else // if the state is on, turn it off
    {
      digitalWrite(12, LOW);
      state = 0;
    }
    oldbutton = 1;
  }
  else if(!button && oldbutton) // same as if(button == low && oldbutton == high)
  {
    // the button was released
    oldbutton = 0;
  }
}

It does not respond to low or high state input on  pin 2.
What am I missing?
Logged

Offline Offline
Sr. Member
****
Karma: 25
Posts: 499
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This:
Code:
  digitalRead(buttonpin);

should be:
Code:
  button = digitalRead(buttonpin);
Logged

Illinois, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 114
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok

I have working code now, but there is one snag in beginning an input (button) check without if
Code:
if (digitalRead(5) == LOW)


Not having the if (digitalRead(5) == LOW as the first line (of a one button toggle On/Off) lets the full code of the button/Input be read with each Loop, apparently. So the LCD display items in my project, for Only this input are executed with each loop. (omitted LCD ref for brevity)

I have tried adding
Code:
if (digitalRead(5) == LOW)
as the first line, but it prevents the code from working.

There must be an issue with using two digitalRead(Pin#) statements, one after another.
Any suggestions appreciated, please try to be specific.

Code:
// One Button On/Off Toggle
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = LOW;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
int reading;

long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  if (digitalRead(buttonPin)==LOW){  // Added to prevent following code exec if not LOW, causes to fail
   reading = digitalRead(buttonPin); } //Original first line works perfect
   //reading = LOW; }    //Did not work as alternative to above line
     if (reading != lastButtonState) {
       lastDebounceTime = millis();
        if (buttonState == HIGH) {
            ledState = !ledState;
          }
  }
 if ((millis() - lastDebounceTime) > debounceDelay) {
   buttonState = reading;
  }
 digitalWrite(ledPin, ledState);
 lastButtonState = reading;
  }
« Last Edit: May 27, 2013, 10:44:13 am by Ashton » Logged

Offline Offline
Sr. Member
****
Karma: 25
Posts: 499
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
int buttonState = LOW;             // the current reading from the input pin

...

void loop() {
   reading = digitalRead(buttonPin);
   if (reading != lastButtonState) {
      lastDebounceTime = millis();
      lastButtonState = reading;
   }
 
   if ((millis() - lastDebounceTime) > debounceDelay) {
      if (buttonState != lastButtonState) {
         buttonState = lastButtonState;
         if (buttonState == HIGH) {
            ledState = !ledState;
            digitalWrite(ledPin, ledState);
         }
      }
   }
}
« Last Edit: May 27, 2013, 10:58:09 am by TanHadron » Logged

Illinois, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 114
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'll give this a try.

Its producing an: "expected unqualified-id before 'if'  error highlighting this line:
Code:
if ((millis() - lastDebounceTime) > debounceDelay) {

My full code:
Code:
// One Button On/Off Toggle
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = LOW;         // the current state of the output pin
int buttonState = LOW;             // the current reading from the input pin
int lastButtonState = HIGH;   // the previous reading from the input pin
int reading;

long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  reading = digitalRead(buttonPin);
   if (reading != lastButtonState) {
      lastDebounceTime = millis();
      lastButtonState = reading;
          }
  }
 if ((millis() - lastDebounceTime) > debounceDelay) {
      if (buttonState != lastButtonState) {
         buttonState = lastButtonState;
         if (buttonState == HIGH) {
            ledState = !ledState;
            digitalWrite(ledPin, ledState);
         }
      }
   }
}
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks like you've closed your loop() function just before the if statement in question.

You have:
Code:
void loop() {
  reading = digitalRead(buttonPin);
   if (reading != lastButtonState) {
      lastDebounceTime = millis();
      lastButtonState = reading;
          }
  }
 if ((millis() - lastDebounceTime) > debounceDelay) {
      if (buttonState != lastButtonState) {
         buttonState = lastButtonState;
         if (buttonState == HIGH) {
            ledState = !ledState;
            digitalWrite(ledPin, ledState);
         }
      }
   }
}

change it to:
Code:
void loop() {
  reading = digitalRead(buttonPin);
   if (reading != lastButtonState) {
      lastDebounceTime = millis();
      lastButtonState = reading;
   }
 
   if ((millis() - lastDebounceTime) > debounceDelay) {
       if (buttonState != lastButtonState) {
           buttonState = lastButtonState;
           if (buttonState == HIGH) {
                 ledState = !ledState;
                 digitalWrite(ledPin, ledState);
           }
       }
   }
}
« Last Edit: May 27, 2013, 11:36:46 am by tbradt » Logged

Illinois, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 114
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks tbradt, that was simpler and worked great.
Logged

Pages: [1]   Go Up
Jump to: