Push Button as On/ Off Switch

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.

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.

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

// 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

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 8)

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.

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

My full 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?

This:

  digitalRead(buttonpin);

should be:

  button = digitalRead(buttonpin);

Ok

I have working code now, but there is one snag in beginning an input (button) check without if 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 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.

// 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;
  }
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);
         }
      }
   }
}

I'll give this a try.

Its producing an: "expected unqualified-id before 'if' error highlighting this line:

if ((millis() - lastDebounceTime) > debounceDelay) {

My full 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);
         }
      }
   }
}

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

You have:

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:

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);
           }
       }
   }
}

Thanks tbradt, that was simpler and worked great.

Sorry for posting in a dead thread.

But if I want to add a fade effect, how should I do it?

But if I want to add a fade effect, how should I do it?

Use your favorite text editor.

A complete set of requirements would be the first item of business. What should trigger the fade effect? How long should it last? One pin or multiple pins? Fading together, or to produce some special effect?

PaulS:
A complete set of requirements would be the first item of business. What should trigger the fade effect? How long should it last? One pin or multiple pins? Fading together, or to produce some special effect?

Sorry if I was unclear.

I want to turn a fade effect on and off with a button.
It is only from one pin with multiple led lights.
And it should go on until I press the button again.

I want to turn a fade effect on and off with a button.
It is only from one pin with multiple led lights.
And it should go on until I press the button again.

What you turn on, or off, has nothing to do with detecting that that state of the switch has changed.

bool needToFade = false;
byte prevState = HIGH;
void loop()
{
   byte currState = digitalRead(somePin);
   if(currState != prevState)
   {
      // The switch state changed
      if(currState == LOW)
      {
         // to pressed (assuming INPUT_PULLUP configuration)
         needToFade = !needToFade;
      }
   }
   prevState = currState;

   if(needToFade)
   {
      // Write non-blocking code to fade here
   }
}

The comment about writing non-blocking code means that you do not use a for loop or any delay() calls in writing the code.

Sorry but I am not so good at coding and is only doing this for an asignment in school.
When I trie to get the led to fade it fades but stay on when I press the button.

only doing this for an asignment in school.

What class? If it is a programming class, I will NOT write the code for you.

It is for a class where we have to make someting and one of my parts is to add som fadeing lights on my clothes so it is not a programming class. And I don't want to just turn on and off the battery because it will be hidden.
The class is named Situated Making.

I typed all this up before seeing your true situation. You will need to learn some coding to do what I wrote or you will need a friend to write code for you, or hire someone.

Programming Arduinos is not rocket science but it still takes many hours total to get going.

I don't know how brilliant you are, you might be or you might show this to your friend if it's beyond what you are prepared to do.

Phury:
Sorry if I was unclear.

I want to turn a fade effect on and off with a button.
It is only from one pin with multiple led lights.
And it should go on until I press the button again.

Just looking at the fade process, two ways to do it are

  1. a loop inside of void loop() that makes the fade before void loop() can end (to run again).

void loop()
{
// other code, like button code that sets myFadeFlag only when press just happened

if ( myFadeFlag == 1 )
{
for ( byte i = 0; i < 256; i++ )
{
// use PWM to light the led to level i
delay( 100 );
}
}
}

This way has problems. It can't do "And it should go on until I press the button again." because as long as the code is stuck in that for-loop the button code can't run. That is the crux of your problem.

  1. use void loop() as the small wheel that drives the action of all the parts in your sketch.

Imagine that your fade code is a person who watches a light and a clock. If the light is on, the person waits for the second hand to reach 12 and turns the fade up or down a notch. In this way the seconds go by, the person sees, and action is only done if the light is on and the minute is up.

Imagine that the button code is another person who watches the button and turns the light on and off only when the button has just been pressed. The button can be pressed and let go, the light gets switched and stays. One press, light on, next press, light off... not light on if down and light off if up but press-change, press-change.

With Arduino we can tell time by the millis() clock. It uses unsigned long variables to count milliseconds, as a beginner you want all your time variables to be type unsigned long.

unsigned long timeStart, timeWait;

byte fadeFlag; // default is zero

void setup()
{
// code
}

void loop()
{
// button code changes fadeFlag

if ( fadeFlag) // this is the the person seeing if the light is on
{
if ( millis() - timeStart >= timeWait ) // this is the the person watching the second hand
{
// fade the light 1 notch... use a variable to keep track
timeStart = timeStart + timeWait; // set up the timer for the next 'minute'
}
}
}

This is missing pieces of course. It doesn't know when to stop fading. There is nothing to start the fade or about using PWM to control led brightness. A few other details are missing.

All this is to show is a way to let the things run together. There are tutorials that show details, not exactly what you want but close with working code. In my signature space under this post are 3 addresses for Nick Gammon tutorials, the first one can help you more than my post here.
In this forum there is a 'sticky thread' always near the top that has the lesson in another way.

This "only an assignment" could be pivotal in your understanding of automation control. And yes, you can automate fashion and it can serve you well.