using push button pulse width to set output delay()

Hi everyone.
I’m totally new to both the arduino and to C.
I’m trying to use the time a push button is pressed to set the time an output should stay LOW.
I have wired the push button to digital pin 2 with a 10k pull up resistor and a LED to digital pin 12 with 330 ohm resistor to test the output.
At first I tried using the pulseIn () function but I had the same result as this guy, so I used his code as the core for what I needed.

I have two issues:

  1. after I set the first delay pressing the button, whenever I want to set a new delay, it will not work if I do it while the LED is LOW. I need to cut in while the LED is blinking for it to work.
  2. sometimes (I haven’t detected what’s the condition) when pressing the button (more than a sec.) it’ll stop working.
    I’m using an arduino uno.
    Here’s what I have:

int buttonPin = 2;
int ledPin = 12;
unsigned long pulseWidth, pulseBegin;

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

}

void loop()
{

while (digitalRead(buttonPin) == HIGH){} //do nothing if initally push button is not pressed

if (digitalRead(buttonPin) == LOW)
{
pulseBegin = millis();
while (digitalRead(buttonPin) == LOW){} //do nothing while push button is being pressed
pulseWidth = millis()-pulseBegin; //record pulse width of button being pressed
if (pulseWidth < 1000){} //turn off if the button is pressed less than a second
else
{

while (digitalRead(buttonPin) == HIGH)
{
digitalWrite(ledPin,HIGH);
delay(1000);
digitalWrite(ledPin,LOW);
delay(pulseWidth); //use last recorded pulse width as the time the output should stay LOW
}
}
}
}

Any help would be gladly appreciated.
Sam.

During the calls to delay your board is busy doing "delay" and nothing else. SO for a second + whatever your pulseWidth variable holds your board is not looking at button presses at all. It won't see a button press until it gets back around to that line of code (the while condition) that checks for a button press. See the "Blink Without Delay" example for some inspiration on handling your timing without blocking the rest of your program for some seconds.

if (pulseWidth < 1000){} //turn off if the button is pressed less than a second
        else 
          {

This is just crazy. Make that if pulseWidth > 1000 do all the stuff and then just don’t have an else if you don’t want anything to happen when its less than.

play around with this:

int buttonPin = 2;
int ledPin = 13;
unsigned long pulseWidth, pulseBegin;
byte lastButtonState = HIGH;

void setup()
{
  Serial.begin(115200);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
}

void loop()
{

  bool gotPulse = false;
  int buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState)
  {
    if(buttonState == LOW)
    {
      pulseBegin = millis();
      Serial.println("!");
    }
    else if(buttonState == HIGH)
    {
      pulseWidth = millis() - pulseBegin;
      gotPulse = true;
      Serial.println("!");
    }
  }
  lastButtonState = buttonState;
  if(gotPulse)
  {
    Serial.print("Pulse time=");
    Serial.println(pulseWidth);
    gotPulse = false;
  }
  delay(25);  // cheap debounce
  blink(pulseWidth);
}

void blink(unsigned long duration)
{
  static unsigned long lastMillis;
  if(millis() - lastMillis > duration)
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    lastMillis = millis();
  }
}

It is certainly possible to write a program to measure how long a button is pressed and to take different actions based on that - save the value of millis() when the button is pressed and save it again when it is released and calculate the difference.

However I suspect that you will find it very difficult to use unless you provide some elaborate feedback (a flashing LED, for example) to let the person know when to release the button for the different effects.

The demo Several Things at a Time illustrates the use of millis() to manage timing.

...R

Thanks a lot for all the replies, they've really been helpful. I think I'm getting there.

Delta_G:
See the "Blink Without Delay" example for some inspiration on handling your timing without blocking the rest of your program for some seconds.

I went and did that and after looking at different examples at the web I came to this one.
I adapted the code to my needs and it's working much better.
The thing is that sometimes the program works like a charm; it records the time the button was last pressed and it uses it to make the LED stay LOW that same amount of time and if I press the button less than a second it turns off, but sometimes I press the button (more than a second) and after I release it, it brights the LED and keeps it like that as if the second if() is not running.
Am I totally off the road again, or can I fix this within the same structure??
Here it is:

int buttonPin = 2;
int ledPin = 12;
int ledState = LOW;
unsigned long pulseWidth;
unsigned long pulseBegin = 0;
unsigned long previousMillis = 0;
long OnTime = 1000;

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

void loop()
{

if (digitalRead(buttonPin) == LOW)
{
pulseBegin = millis();
while (digitalRead(buttonPin) == LOW){} //do nothing while push button is being pressed
pulseWidth = millis()-pulseBegin; //record pulse width of button being pressed
}

if ((digitalRead(buttonPin) == HIGH) && (pulseWidth > 1000)) //if button is not pressed and last pulse with of button is greater than a sec. go on.
{
unsigned long currentMillis = millis();
long OffTime = pulseWidth; // time the LED must stay LOW is last pulse width recorded
if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
{
ledState = LOW; // Turn it off
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
{
ledState = HIGH; // turn it on
previousMillis = currentMillis; // Remember the time
digitalWrite(ledPin, ledState); // Update the actual LED
}
}

}

Thanks again, I really appreciate the help.
Sam.