trying to create a one touch button

GOAL
I am trying to create a button that once pressed and released will turn a light on or off. My goal is that you can release the button and let is still keep the light on. but, if you press and then release the button a second time it goes off.

PROBLEM
i can run the program and it will work for only one cycle. i can turn the light on once, and then off once more. but after this it wont run again. i dont know whats up.

PROGRAM
int pin12 =12; // this is my LED
int pin2 =2; // this is my button
int pin2status;
int pin2cnt=0; //unused
int pin2firstcnt=0; //unused
int pin12status=0;

void setup ()
{
Serial.begin (9600);

pinMode (pin12, OUTPUT); // sets pin12 as output
pinMode (pin2, INPUT); // sets pin2 as input
pin2status = digitalRead(pin2); // sets a variable for pin2

}
void loop ()
{
pin2status = digitalRead(pin2); // reads pin2
Serial.print ("Button is");
Serial.println (pin2status);
if (pin2status == HIGH) /* if pin2 is on then it turns
led either on or off */
{
if (pin12status == (1))
{digitalWrite (pin12,LOW);
(pin12status +(-1));
Serial.print ("LED is");
Serial.println (pin12status);}
if (pin12status ==0)
{digitalWrite (pin12,HIGH);
(pin12status ++);
Serial.print ("LED is");
Serial.println (pin12status);}
}

delay (1000);

}

Good statement of your goal and problem, complete with sample code. :slight_smile:

If I understand you correctly you are wanting to make your momentary push button act as a "toggle" switch.

I think I have spotted an issue with your handling of the 'pin12status' variable--I would suggest trying the long form of variable assignment (e.g. a = a + 1) rather than the short form (e.g. a++) to see if you can spot where you might have an issue.

--Phil.

yes this is what I was trying to create.

as for the variable assignment, it did seem to make a difference the long for of (a +1) actually made the led turn on once and then as i hit the button again it would not go off.

according to my serial feed it says the led is off when it is actually on.

i'm still trouble shooting. my guess is either i have incorectly told it to add 1 unit. or this is something wrong with my chain of "if" statements

First, wrapping your code in ... blocks helps a lot.

Second, there's a lot of extra unnecessary (and misleading, and probably not functional) punctuation in this part of the code. The +(-1) is probably your error. Remember, source code is for humans, so reformat so it's more like this, for readability:

    if (pin12status == 1)
    {
        digitalWrite(pin12, LOW);
        pin12status--;
        Serial.print("LED is");
        Serial.println(pin12status);
    }
    if  (pin12status == 0)
    {
        digitalWrite(pin12, HIGH);
        pin12status++;
        Serial.print("LED is");
        Serial.println(pin12status);
    }

And so on.

well this was deffinately part of my error. now i can turn the light on and off. However, when the light is off it seems that it will only stay off for one second before it kicks back on. if i hit my button again it goes off again but only for one second.

getting closer. thank you so much for this help. still trouble shooting

my guess is that it is shuting the light off and then immediately turning it back on. this might be a cause of my many simultaneous if statements not to sure how to alter it though

hurray! for any one interested in my beginners work

SOLUTION

int pin12 =12; // this is my LED
int pin2 =2; // this is my button
int pin2status;
int pin2cnt=0; //unused
int pin2firstcnt=0; //unused
int pin12status=0;

void setup ()
{
Serial.begin (9600);

pinMode (pin12, OUTPUT); // sets pin12 as output
pinMode (pin2, INPUT); // sets pin2 as input
pin2status = digitalRead(pin2); // sets a variable for pin2

}
void loop ()
{
pin2status = digitalRead(pin2); // reads pin2
Serial.print ("Button is");
Serial.println (pin2status);
if (pin2status == LOW)
{}
if (pin2status == HIGH) /* if pin2 is on then it turns
led either on or off */
{
if (pin12status == 1)
{digitalWrite (pin12,LOW);
pin12status --;
Serial.print ("LED is");
Serial.println (pin12status);}
else
{digitalWrite (pin12,HIGH);
pin12status ++;
Serial.print ("LED is");
Serial.println (pin12status);}
}

delay (1000);

}

ADDITTIONALLY

my program allows for the light to turn on and off if the button is taped, unfortunately if the button is held to long it blinks on and off. any ideas how to fix this?
also doing the function (a++) how can i do something like "(a+5)"?

finally any more advise on simplyfing code?

These are equivalent:

a = 1 + a;
a = a + 1;
a += 1;
a++;
++a;

The first three forms can be used for accumulating any amount, not just one.

And don't wrap them in parentheses. It's unnecessary and misleading.

And I'll suggest again, wrap your code in <mark>a++;</mark> tags in the forum, so formatting is retained.

Since you are toggling I would use a boolean rather
than incrementing and decrementing an integer.
How about something like --

boolean pin12status = LOW;
.
.
if (pin2status == pin12status) {
   // no changes since we are already in
   // the correct state
} else {
  pin12status = pin12status ? LOW : HIGH;
  digitalWrite(pin12, pin12status);
}
.

(* jcl *)

Take a look at this, see if you can use it.

int led1Pin = 13;
int switchPin = 2;              // switch is connected to pin 2

int val;
int val2;
int lightMode = 0;              // Is the light on or off?
int buttonState;

void setup() {
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  digitalWrite(switchPin, HIGH);    //Set the internal pullup R
  pinMode(led1Pin, OUTPUT);

  buttonState = digitalRead(switchPin);   // read the initial state
}

void loop(){

  val = digitalRead(switchPin);      // read input value and store it in val
  delay(10);                         // 10 milliseconds is a good amount of time for a 'de-bounce'
  val2 = digitalRead(switchPin);     // read the input again to check for bounces
  if (val == val2) {                 // make sure we got 2 consistant readings!
    if (val != buttonState) {          // the button state has changed!
      if (val == LOW) {                // check if the button is pressed
        if (lightMode == 1) {          // is the light on?
          digitalWrite(led1Pin, 0);    // if not, turn light on
          lightMode = 0;              // save condition of light in variable
        }
        else{
          digitalWrite(led1Pin, 1);    //if light is on, turn off
          lightMode = 1;               //save condition of light in variable
        }
      }
    }
    buttonState=val;
  }
}

I can't take credit for it, found the code on Ladyada's site.
http://www.ladyada.net/learn/arduino/lesson5.html

a++;

++a;

Just to be pedantic I do believe there is a subtle difference with the last one.

--Phil.

a++;

++a;



Just to be pedantic I do believe there is a subtle difference with the last one.

I expect phil knows this, but just to clarify:

a++;
++a;
Will compile to exactly the same code.

if(a++ == 5)
if(++a == 5)
Will produce different results because a will be incremented after the check in the first, and before the check in the second.

i tried the advice of using "boolean" and while i dont quite fully understand how booleans work because I'm still quite a beginner. If anyone knows some good tutorials on boolean statements in code please post a link.

however, I was able to learn enough about AND statements to simplify and improve the code. I am now capable of leaving my finger on the button and not have the light blink on and off as the program loops through.

to any one interested. my improved code:

int pin2 = 2;
int pin12 = 12;
int pin12status;
int pin2status;
int pin2prior; // pin2 status from the previous loop

void setup ()
{
pinMode (pin12, OUTPUT);
pinMode (pin2, INPUT);
}
void loop ()
{
pin2status = digitalRead(pin2);
pin12status = digitalRead(pin12);

if (pin2prior == LOW)
{
if (pin2status == HIGH && pin12status == LOW)
{digitalWrite (pin12, HIGH);}

if (pin2status == HIGH && pin12status == HIGH)
{digitalWrite (pin12,LOW);}
}
pin2prior = pin2status;

delay (10);
}

thanks again for all the help everyone.

also thanks for the help with posting code, It took me a while too catch on

Another way of doing this:

if (pin2status == HIGH && pin12status == LOW)
    {digitalWrite (pin12, HIGH);}
   
 if (pin2status == HIGH && pin12status == HIGH)
    {digitalWrite (pin12,LOW);}
 }

would be this:

if (pin2status == HIGH)
    {digitalWrite (pin12, !digitalRead(pin12));} //the '!' inverts a boolean value

I just figured that one out today.