Unexpected behavior from my LED/PushButton sketch.

This is my first post here. I'm new to the Arduino, but not to programming.

#define BUTTON_PIN 7
#define LED_PIN 9

unsigned long pressed_time = 0;
unsigned long unpressed_time = 0;
unsigned long last_toggle_time = 0;
int button_state = LOW;
int previous_button_state = LOW;
int led_state = 0;

void setup()
{
    pinMode(BUTTON_PIN, INPUT);
    pinMode(LED_PIN, OUTPUT);
}

void loop()
{
    button_state = digitalRead(BUTTON_PIN);
    
    if (button_state == HIGH && previous_button_state == LOW && millis() - unpressed_time > 100)
    {
        pressed_time = millis();
    }
    else if (button_state == LOW && previous_button_state == HIGH)
    {
        unpressed_time = millis();
    }
    
    previous_button_state == button_state;
    
    if (button_state == HIGH && millis() - pressed_time <= 200 && pressed_time != last_toggle_time)
    {
        last_toggle_time = pressed_time;
        if (led_state > 0)
        {
            led_state = 0;
        }
        else
        {
            led_state = 255;
        }
    }
    else if (button_state == HIGH && millis() - pressed_time > 200)
    {
        led_state += constrain(millis() - pressed_time / 100, 0, 255);
        analogWrite(LED_PIN, led_state);
    }
    else if (button_state == LOW && millis() - unpressed_time > 100)
    {
        analogWrite(LED_PIN, led_state);
    }
    analogWrite(LED_PIN, led_state); // added for testing, demonstrates a blinking behavior while button is held
}

I want my sketch to toggle the LED from zero to full brightness every time I press the button for a short amount of time. If I hold the button down I want the LED to gradually brighten until it reaches full. What really happens is that the LED randomly turns on and off for short presses and if the button is held the light will toggle on and off every 200 milliseconds.

Any help is appreciated. I'm also open to suggestions on my code/style in general. Thanks.

Have you got any external pull-ups or pull-downs on the button pin?
You're not using the internal pull-ups.

I'm not sure what you mean. I'll look it up on google.

I do know that when I had a simple program like so:
if button down: led on
if button up: led off

it worked perfectly. It appears to me the button is working and connected properly to the Arduino, as demonstrated in this case. What am I missing?

Update:

I believe I am using a "pull-down," although I might have that backwards. The button is wired as shown here http://www.arduino.cc/en/Tutorial/Button . The 5v power is connected to the button first, and the button is then connected to the input pin and the ground. There is a resistor between the button and the ground.

I do know that when I had a simple program like so:
if button down: led on
if button up: led off

it worked perfectly.

If that worked OK, then the problem is most likely a logic flaw in your program (I'm more a hardware type).

It's a little too complex for me to figure out quickly and as you stated you have programming experiance, I suggest you simplify your code until you figure it out.

Lefty

"previous_button_state == button_state;"

The shame!!! :-[

Hi there

How about a more simpel button decection approch:

// Button_fade_in
// Buttonpress makes the led fade in
// Button connected between pin 12 and ground. Internal pull-up resistor is used
// Led + 220 ohm resistor is connected between pin 10 and ground


// Constants
const int buttonPin = 12;    // Pin connected to the button
const int ledPin = 10;     // Pin connected to the led
const int fadeRate = 25;   // ms: lower number = faster

// Variables
unsigned long clickTime = 0;
int power;

// *** Setup ***
void setup(){
  pinMode(buttonPin, INPUT);
  digitalWrite(buttonPin, HIGH);  // Enable pull-up resistor
  pinMode(ledPin, OUTPUT);
}

// *** Main program ***
void loop(){
  if (digitalRead(buttonPin) == LOW) { // Button is pressed
      power = (millis()-clickTime)/fadeRate; // We need more power Scotty
      if (power > 255) power = 255; // Not sure what happens if pwm is "overloaded"
      analogWrite(ledPin, power);
  }
  else {
    clickTime = millis();  //Button is unpressed
    digitalWrite(ledPin, LOW);
  }
}

-Fletcher

Pull ups/ downs explained at....

NOT covered there: The Arduino is very, very clever. Each pin has a pull up built into the Arduino, but the are not connected in the Arduino's default state.

If you have a pin configured as an input (the default state, or you can be explicit and say pinMode(2,INPUT) to be sure pin 2 is set for input, if you then (once, during setup is sufficient) say....

digitalWrite(2,HIGH)

... then you will connect an internal 20k pull up resistor to the line.

Really neat!

#define BUTTON_PIN 7
#define LED_PIN 9

unsigned long pressed_time = 0;
unsigned long unpressed_time = 0;
unsigned long last_toggle_time = 0;
int button_state = LOW;
int previous_button_state = LOW;
int led_state = 0;

void setup()
{
    pinMode(BUTTON_PIN, INPUT);
    pinMode(LED_PIN, OUTPUT);
}

void loop()
{
    button_state = digitalRead(BUTTON_PIN);
    
    if (button_state == HIGH && previous_button_state == LOW && millis() - unpressed_time > 100)
    {
        pressed_time = millis();
    }
    else if (button_state == LOW && previous_button_state == HIGH)
    {
        unpressed_time = millis();
    }
    
    previous_button_state = button_state;
    
    if (button_state == HIGH && millis() - pressed_time <= 500 && pressed_time != last_toggle_time)
    {
        last_toggle_time = pressed_time;
        if (led_state > 0)
        {
            led_state = 0;
        }
        else
        {
            led_state = 255;
        }
    }
    else if (button_state == HIGH && millis() - pressed_time > 500)
    {
        led_state = constrain(pow(((millis() - pressed_time - 500) / 100), 2) / 40, 0, 255);
        analogWrite(LED_PIN, led_state);
    }
    else if (button_state == LOW && millis() - unpressed_time > 100)
    {
        analogWrite(LED_PIN, led_state);
    }
}

Here is my final code, and it works as I wanted. I do have a physical pull down resistor connected to the button input.

When the button is pressed quickly it will toggle the light on and off. When held down the light will start dim and gradually get brighter.

@Fletcher
Your code doesn't implement the same behavior from what I can tell. There is no debouncing, and you must hold down the button for the light to stay on.