Back to Basics - blink without delay using button

OK, so I'm giving up on my original project and going back to the basics. And even that isn't going well...

Here's my code

// constants won't change. Used here to 
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

int buttonState = 0;         // variable for reading the pushbutton status

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);   
  pinMode(buttonPin, INPUT);   
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the 
  // difference between the current time and last time you blinked 
  // the LED is bigger than the interval at which you want to 
  // blink the LED.
  unsigned long currentMillis = millis();
    buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) { 

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
  }
  else
      ledState = LOW;
}

What I get is, when the unit is reset I have no blinking. When I push the button, the light blinks. When I release the button the light blinks a couple more times (at the same rate) and then stays on.

EDIT... Sometimes it stays lit, sometimes it goes out.

My last line is "else ledState = LOW" so why does it stay high?

You haven't said anything about haw the switch is wired. Without that information, it doesn't even make sense to consider a software problem.

Using the internal pullup resistor, and connecting one leg of the switch to ground and one leg to a digital pin is far simpler than using external pullup or pulldown resistors. You are using external resistors, right?

  1. You only check ledState if the switch is pressed, therefore you only blink the LED while the switch is HIGH

  2. You will be left in whichever state was active the last time through the IF, before the switch was released.

  3. setting ledState to LOW does not turn the LED off. Have a look at your code in the if. Ask yourself "What turns the LED on or off?" If you say it turns on and off because ledState changes, think again.

Right now the switch is just between pin 2 and 5v. I'm using the onboard LED at pin 13.

I see what you are saying about the button release not resetting the LEDSTATE but how do I fix that? I tried modifying the off command for the button release and I no longer had a blink at all, just a steady LED

Right now the switch is just between pin 2 and 5v. I'm using the onboard LED at pin 13.

So, when the switch is not pressed, the pin floats. Really bad idea.

I see what you are saying about the button release not resetting the LEDSTATE

No, that's not true. ledState IS set, but ledState is not applied to the pin.

Bittsen: Right now the switch is just between pin 2 and 5v. I'm using the onboard LED at pin 13.

I agree with PaulS. Bad idea. Really BAD idea. if you insist on putting a switch from the pin to +5v, you'll need a pulldown resistor. If you're ok with the active level of the switch being LOW, you can use pinMode to set INPUT_PULLUP, eliminating the need for an external resistor. Otherwise, noise will get you.

I see what you are saying about the button release not resetting the LEDSTATE but how do I fix that? I tried modifying the off command for the button release and I no longer had a blink at all, just a steady LED

    if (ledState == LOW)
      ledState = HIGH;  // does this statement turn the LED ON?
    else
      ledState = LOW;  // does this statement turn the LED OFF?

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);  // why is this statement here? Could it be that the comment on the previous line gives you a hint?

PaulS:

Right now the switch is just between pin 2 and 5v. I'm using the onboard LED at pin 13.

So, when the switch is not pressed, the pin floats. Really bad idea.{/quote]

So is this what's wrong or is it just a generally bad idea, and why?

PaulS:

I see what you are saying about the button release not resetting the LEDSTATE

No, that's not true. ledState IS set, but ledState is not applied to the pin.

Why is the ledState not applied to the pin?

And why can't someone just answer a question without being cryptic about it?

Bittsen:
Why is the ledState not applied to the pin?

And why can’t someone just answer a question without being cryptic about it?

Because we want you to learn. We won’t write code for you, so we want to point you in the right direction. One way of doing that is to hint at what’s wrong, sometimes we make that STRONGLY HINT, like when I asked you which line out of three in your code actually sets the LED pin to HIGH or LOW. Heck, there’s even a comment right above the appropriate line that does it, that TELLS you what it’s going to do.

ledState is an integer variable. Think of it like a piece of paper, where you write a bit of information. Then, when you want to do something with that information, you pass it to someone, and that someone will do something with it.

Let’s write “Bring home some bread” on the paper. Now look into your pantry. Is the bread there yet? Don’t think so. Now hand it to your spouse, and after she executes the instruction, your bread will be there.

So you write ledState = HIGH, but the LED is not on. So, you pass ledState to a function called digitalWrite(ledPin, ledState); which is an instruction to the digitalWrite function to make ledPin go to the state written to ledState. And would you look at that! The LED is ON.

So it works, but man, you gotta tell that darned computer EVERYTHING! Every little detail. That’s the nature of the beast.

lar3ry:

Bittsen: Why is the ledState not applied to the pin?

And why can't someone just answer a question without being cryptic about it?

Because we want you to learn. We won't write code for you, so we want to point you in the right direction. One way of doing that is to hint at what's wrong, sometimes we make that STRONGLY HINT, like when I asked you which line out of three in your code actually sets the LED pin to HIGH or LOW. Heck, there's even a comment right above the appropriate line that does it, that TELLS you what it's going to do.

ledState is an integer variable. Think of it like a piece of paper, where you write a bit of information. Then, when you want to do something with that information, you pass it to someone, and that someone will do something with it.

Let's write "Bring home some bread" on the paper. Now look into your pantry. Is the bread there yet? Don't think so. Now hand it to your spouse, and after she executes the instruction, your bread will be there.

So you write ledState = HIGH, but the LED is not on. So, you pass ledState to a function called digitalWrite(ledPin, ledState); which is an instruction to the digitalWrite function to make ledPin go to the state written to ledState. And would you look at that! The LED is ON.

So it works, but man, you gotta tell that darned computer EVERYTHING! Every little detail. That's the nature of the beast.

BUT, I thought that's what I did when I told it, at the end of the loop, if the button isn't "on" then all that crap pertaining to the ledState should be eliminated and it should just go OFF.

THIS is where I'm locked up.

I probably just have a bad bracket somewhere, is my first guess.

(In the meantime I have been working on my breadboard adding in necessary resistors to bleed off extra current when the button is released. I'm using 220K resistors. This should be sufficient, correct?)

I think this might be what I need to do...

else 
  if (buttonState == LOW)
      ledState = LOW;

Bittsen: BUT, I thought that's what I did when I told it, at the end of the loop, if the button isn't "on" then all that crap pertaining to the ledState should be eliminated and it should just go OFF.

No, when you "digitalWrite" a value to the pin, it stays there until you "digitalWrite" a different value. Part of the problem here is you are changing your state variable without changing the state of the hardware. I think you should write a function that helps you keep that straight...

void setLedState(int s) {
   ledState = s;
   digitalWrite(ledPin, s);
}

Then, never change the LED with anything but that function. Do not ever just change the variable or write to the pin, only call the function. That way the two things stay in sync and you can never accidentally change one without the other.

I wish I hadn't used up all those brain cells remembering girlfriends birthdays. Maybe I'd have some left to comprehend stuff that should be childs play for me.

Your last comment doesn't compute no matter which direction I look at it.

OK I will be explicit...

This line of code...

else
      ledState = LOW;

Doesn't do anything but change the value of that variable. That does not change the hardware state. You have to "digitalWrite" something to change the hardware state. If you were using a function to control the two things together, you would not be able to mess that up by changing one thing without changing the other.

Got it. This worked.

if (buttonState == LOW)
    digitalWrite(ledPin, LOW);

And with the added 220K resistor, between the button and ground, I no longer have remnant blinking.

Thanks for the help.

I don't know if the code I ended up with will help me in the long run but it's a start to further understanding the logic of the code.

So, now you're changing the hardware without changing the state variable? That's not really an improvement. You need to always change the two things together. Otherwise your value of the state variable is meaningless. If you change the pin to LOW and you leave the "ledState" variable HIGH, then your program logic is broken. That's why I'm saying use a function that changes both at the same time. That way, you don't screw it up. Programmers always do that - we write functions, we use defines, we use enums, we use long variable names. All that is done so we won't screw it up. Programming is hard, so we need to use those tricks.

jasmine2501: So, now you're changing the hardware without changing the state variable? That's not really an improvement. You need to always change the two things together. Otherwise your value of the state variable is meaningless. If you change the pin to LOW and you leave the "ledState" variable HIGH, then your program logic is broken. That's why I'm saying use a function that changes both at the same time. That way, you don't screw it up. Programmers always do that - we write functions, we use defines, we use enums, we use long variable names. All that is done so we won't screw it up. Programming is hard, so we need to use those tricks.

I have to learn to walk before I can learn to run.

The only real hardware change is that I moved the LED13 output to a breadboard and instead of jumping a couple pins with a wire, I added a 220K resistor to stop the feedback (which, oddly, I didn't think would be so severe)

But, I have something that works now and the pressure (and, I LITERALLY mean pressure) in my head is easing up.

Also, after what I have been through today, what you said in the quotes isn't registering as anything but gobbledy-gook. Perhaps tomorrow evening, after a day of manual labor, it will make sense.

what you said in the quotes isn't registering as anything but gobbledy-gook. Perhaps tomorrow evening

It's the difference between writing down on a piece of paper "the light is ON" and actually flipping the switch.

The comment about changing the hardware without changing the variable referred to the fact that the program changes the physical state of the LED without changing the variable that holds its state.

If you post your new, working code, I am sure that we can give you some more ideas to improve it.

Bittsen, how is your background knowledge of electricity? Do you know current from voltage? Do you know and understand Ohm's Law? Does the expression "floating input" mean something definite to you? Or pullup or pulldown?

Are you sure that you are using a 220K resistor or do you mean 220 ohms, what we often use for LEDs?

Arduino's with AVR chips (almost all) have multi-mode I/O (Input/Output) pins. I/O does not describe the direction that current flows to or from the pin (which can go either way, depending on mode) but rather Input is for reading and won't let much current flow through the pin and output is not usually for reading and can source or sink more current than the pin or chips can take (so protect output with resistors).

Also, you can switch the mode in about a microsecond which lets you do amazing circuit tricks like using a LED that shines most of the time to also serve as a light level sensor to adjust how bright to shine the same LED! Mode switching is also key for making your own capacitive proximity/touch sensors work. Ooh yeah, who needs buttons that will wear out on you?

When you "do a button" there is an input mode that will save you a resistor and be pin-safe, INPUT_PULLUP. http://arduino.cc/en/Reference/PinMode Put a pin in this mode and if the pin is not grounded (through a resistor or not) it will read HIGH. If you ground the pin (push the button that connects to ground) it will read LOW. INPUT_PULLUP mode puts 5V through an internal resistor (20K to 50K ohms) to the pin itself which is why it reads HIGH when not grounded and is easy to ground since 5V through 20K ohms is a very small, pin safe current.

I feel bad enough for you learning code and hardware at the same time, I hope to help clear it up a bit.

One thing to do is set up an organized set of bookmarks. My IDE (Mozilla Seamonkey) makes it easy with folders. I don't have to hunt for the bookmarks I want. It took a little time to save a lot of time and eye/head strain.

Have you seen the pages I link below? If any of it is new to you, bookmark it! http://arduino.cc/en/Tutorial/Foundations http://arduino.cc/en/Tutorial/HomePage http://arduino.cc/en/Reference/HomePage http://www.nongnu.org/avr-libc/user-manual/modules.html http://arduino.cc/en/Hacking/HomePage http://playground.arduino.cc/

On the products page, click on your board and you get specific information and links. You find your pin map there. http://arduino.cc/en/Main/Products

Any site I find good info, I link. It sucks when your memory keeps taking breaks on you.

Bittsen: I have to learn to walk before I can learn to run.

Sure, everyone does. The thing is, what I'm talking about is logical correctness, and it's a skill that is below walking level. Your program is not logically correct because sometimes the variable does not represent the actual state of the LED. Sometimes the LED can be on, and your state variable still says "LOW" - which means your program will perform logic on incorrect information. The coding error that leads to that logical problem is not using a function to manage both things together.

Making functions to keep things like that from happening is Day 2 in a programming class.

Also, after what I have been through today, what you said in the quotes isn't registering as anything but gobbledy-gook. Perhaps tomorrow evening, after a day of manual labor, it will make sense.

That's gonna be a big problem for you. Read each word. Figure out what I meant - every word is important, I do proofread my posts and I make several edits before posting, to make sure it's absolutely clear. My posts were about a very simple concept, that is fundamental to all programming not just Arduino, so if you're having trouble with those concepts, maybe programming isn't your bag. Some people just think in a different way, that isn't conducive to programming, and that is a valuable skill which I can't do. If you are one of those kind of people, you will never understand this stuff. There's nothing wrong with that.

Programming is hard - I make $10 more per hour than my mom does, SAVING LIVES. If programming was easy, I wouldn't be worth that much. So, don't get down on yourself and don't try to push through the stress, walk away and think about something else for a while.