Push Button with two functions

hi,

I do dry this for some time but no luck:

Pushbutton press = LED on for 10min, then off
Pushbutton press within the 10min = LED off

Basically the same button can turn off the led within the 10min.

I can't find a solution so far. It should be simple to use it later on a ATtiny45.

Thanks a lot for any help.

Pe

No surprises there, the compiler doesn't understand psuedo-code. If you want help with your code, you'll actually have to post it. (Read the very top thread).

hi Arrch,

you right, but my question is where to start. The basic code is form the button example. My problem is how the same button can turn of the LED within the delay time. Sure the code "stuck" by the delay.... this will not work

i try again to explain:
I have a LED which i can turn on with a Pushbutton. The LED will be on for, lets say 10min and will then turn off automatically. Here my problem: I would like to be able to switch off with the same Pushbutton the LED within the 10min.

// constants won't change. They're 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

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);     
}

void loop(){
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH);  
    delay(100000);
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
}

[quote author=pe lang link=topic=131076.msg985837#msg985837 date=1352238198]
hi Arrch,

you right, but my question is where to start. The basic code is form the button example. My problem is how the same button can turn of the LED within the delay time. Sure the code "stuck" by the delay.... this will not work

i try again to explain:
I have a LED which i can turn on with a Pushbutton. The LED will be on for, lets say 10min and will then turn off automatically. Here my problem: I would like to be able to switch off with the same Pushbutton the LED within the 10min. [/quote]

So you need to replace Delay with the proper usage of millis(). For an example on how to use millis(), see the Blink Without Delay example. You probably also want to use the button as a toggle, rather than a switch, so you will need to detect the signal edges of the button. Here is an example that integrates Button state change, millis() and even debounce for good measure:

/*
 * Sample sketch to show how to detect the state changes of a momentary switch (button). 
 * Debounce is also implemented without the use of delay and the length that the button
 * is pushed down for is printed to the serial monitor.
 */
 
const int buttonPin = 2;
const unsigned long debounceInterval = 20; // Increase until bouncing stops

unsigned long debounceTime = 0;
unsigned long buttonPushedDownTime = 0;
int lastReading = HIGH;
int lastState = HIGH;
int currentState = HIGH;

void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println("[start]");
}

void loop
{
  // Store the current time in a variable for easy access
  unsigned long currentTime = millis();
  // This variable will be used to store the length of time that the button was depressed for
  unsigned long lengthButtonWasDown = 0;
  // Start by getting the current reading from our button
  int currentReading = digitalRead(buttonPin);
  // If it's different than our last reading, reset the debounce timer
  if (currentReading != lastReading)
    debounceTime = currentTime;
  // If the button has stayed at the same reading for long enough, update the button's state
  if (currentTime - debounceTime > debounceInterval)
    currentState = currentReading;
  // At this point, the debounce is taken care of, we just need to look for the signal edges
  // of the button. That is, when the button goes from LOW to HIGH or HIGH to LOW.
  if (currentState != lastState)
  {
    // First we check if this which transistion we have. If the button is pushed down, then
    // the currentState will be LOW. Otherwise, the button is being released.
    if (currentState == LOW)
    {
      Serial.println("Button pushed down");
      buttonPushedDownTime = currentTime;
    }
    else
    {
      // Calulate how long it was pushed down
      lengthButtonWasDown = currentTime - buttonPushedDownTime;
      // Print the results to the Serial monitor
      Serial.print("Button realeased after ");
      Serial.print(lengthButtonWasDown);
      Serial.print(" seconds");
      
    }
  }
  
  // Update the "last" variables
  lastReading = currentReading;
  lastState = currentState;
}

Thank You!

I am still at the beginning to learn the basics. I am afraid this all makes sense to me in few years. I assumed there must be a simple way to do this. However, i will just simple use the button to switch on the led for a specific time without the switch off function.

BTW: The real application is to switch on a kinetic artwork by pressing a button. To save live time of the work, it needs to be switch off automatically after 5min. It would be a nice add to be a able to switch it off before the 5min ends. This, with the same Button.

I do hope at one time arduino get's just a good tool which is working for me :~

pe

I assumed there must be a simple way to do this.

There is. Perhaps not as simple as you'd like. The debouncing stuff and timed hold stuff in Arrch's code is a bit overkill.

Here's something a bit simpler, but not complete. There are comments though, that explain what else you need to do/add.

int currState;
int prevState = HIGH; // Assumes LOW means pressed
const int somePin = 2; // Connect the switch to this pin and to ground; no other wires or resistors needed

int pressCount = 0;

void setup()
{
   pinMode(somePin, INPUT);
   digitalWrite(somePin, HIGH);
}

void loop()
{
   currState = digitalRead(somePin);
   if(currState != prevState)
   {
      // The switch was just pressed or just released
      if(currState == LOW)
      {
         // Aha, it was just pressed
         pressCount++;
         if(pressCount > 2)
           pressCount = 1;
      }
   }
   prevState = currState;

   // Now, do something based on pressCount
   // 1 means pressed once - turn on LED
   // 2 means pressed twice - turn off LED

   // When you turn the LED on, note the time

   // If LED is on and has been on for the required time,
   // set pressCount to 2, so that next time around, the
   // LED will get turned off
}

Look at the blink without delay example for how to use millis() to determine (relative) times. Use a boolean to keep track of the LED state. Set it to true when you turn the LED on (using that state variable). Set it to false when you turn the LED off. Then, the value will tell you whether the LED is on, or not.

PaulS:
The debouncing stuff and timed hold stuff in Arrch's code is a bit overkill.

I'll give you the debouncing being overkill (for this application), but the timed hold is an example on how to use millis().

but the timed hold is an example on how to use millis().

Well, I recognize that. But, clearly OP didn't. I think that the blink without delay example is a better choice, but only because it is focusing only on one task. Your code shows how to do a number of things, not all of which are on OPs requirements list.

PaulS:

but the timed hold is an example on how to use millis().

Well, I recognize that. But, clearly OP didn't. I think that the blink without delay example is a better choice, but only because it is focusing only on one task. Your code shows how to do a number of things, not all of which are on OPs requirements list.

Hence why I recommended Blink Without Delay first. I didn't just write that code at the OPs request, It just happened to include an example of signal edge detection and using millis(), which is why I posted it.

Hi PaulS and Arrch,

Thanks a lot for your help so far !

i do think i have something (by luck) which is working:

int currState;
int prevState = HIGH; // Assumes LOW means pressed
const int buttonPin = 2; // Connect the switch to this pin and to ground; no other wires or resistors needed
const int ledPin =  13; // My LED

// Variables will change:
long previousMillis = 0;        // will store last time LED was updated
int pressCount = 0;


// 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 = 10000;           // interval for on time (milliseconds)



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

void loop()
{ 
  
 
   currState = digitalRead(buttonPin);
   if(currState != prevState)
   {
      // The switch was just pressed or just released
      if(currState == LOW)
      {
         // Aha, it was just pressed
         pressCount++;
         if(pressCount > 2)
           pressCount = 1;
      }
   }
   prevState = currState;
   

if (pressCount == 1)  // here to switch on the LED
    digitalWrite(ledPin,HIGH);

 // here should be the timmer with millis(), ?
// after 5min i guess pressCount = 2

  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis; 
    pressCount = 2;  //turn off
  }


if (pressCount == 2) // here the switch off within the 5min
    digitalWrite(ledPin,LOW);  


   // Now, do something based on pressCount
   // 1 means pressed once - turn on LED
   // 2 means pressed twice - turn off LED

   // When you turn the LED on, note the time
   // If LED is on and has been on for the required time,
   // set pressCount to 2, so that next time around, the
   // LED will get turned off
}
   currState = digitalRead(buttonPin);
   if(currState != prevState)
   {
      // The switch was just pressed or just released
      if(currState == LOW)
      {
         // Aha, it was just pressed
         // right now we know the button was pressed so
         // if the LED is on turn it off
         // if the LED is off turn it on and get the time
      }
   }
   prevState = currState;
   // if the LED is on and enough time has passed turn it off

You'll need to keep track of the state of the LED but you don't need all that counting stuff you did.

XD

You'll need to keep track of the state of the LED but you don't need all that counting stuff you did.

Actually, you do. The LED needs to be turned off after 10 seconds OR another switch press. That can't happen inside the switch-just-became-pressed block.