a little guidance needed

im working on a simple project that when a switch opens it sounds a buzzer for 5 seconds. but if the switch remains open it will only buzz for 5 seconds then wait for the switch to close and open again before it buzzes again. i can normally sort things out for myself without bothering others but im stuck. thanks for any help you can offer.

int switchPin = 2;              // switch is connected to pin 2
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the last button state
int val2;                       // variable for reading the delayed/debounced status

void setup() {
  pinMode(switchPin, INPUT);    // Set the switch pin as input
buttonState = digitalRead(switchPin);   // read the initial state
}
void loop(){
  val = digitalRead(switchPin);      // read input value and store it in val
   delay(20);                         // 10 milliseconds is a good amount of time
   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
      digitalWrite(13, HIGH);   // turn Buzzer on
       delay (5000);            // keep Buzzer on for 5 seconds
       digitalWrite(13, LOW);   // turn Buzzer off
    } else {                         // the button is -not- pressed...
     }
  }
 buttonState = val;                 // save the new state in our variable
}
}

ukseal: im working on a simple project that when a switch opens it sounds a buzzer for 5 seconds. but if the switch remains open it will only buzz for 5 seconds then wait for the switch to close and open again before it buzzes again.

The two behaviours you mention seem consistent with one another. Explain what you want it to do.

Use the switch opening to trigger a rising or falling interrupt. When the interrupt occurs, set a flag. Then in your main loop, read millis(), turn on the buzzer, and leave it on until millis() has increased buy 5 sec.

jrdoner: Use the switch opening to trigger a rising or falling interrupt. When the interrupt occurs, set a flag. Then in your main loop, read millis(), turn on the buzzer, and leave it on until millis() has increased buy 5 sec.

That would implement the OP's first sentence. If you read the post carefully, you'll see that it is specifically ruled out.

You should move the statement : buttonState = val; // save the new state in our variable up one line so it is executed only when val != buttonState

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

How have you got your switch wired, I notice you do not have pull-ups turned on.

When your switch is open, do you have a 10K resistor to pull the input of the arduino to the gnd if you are switching 5V, or the resistor to 5V if you are switching gnd.

Tom.... :)

@ukseal, do not use delay() anywhere in your code. Use millis() to manage timing without blocking as illustrated in Several Things at a Time

There is no need for interrupts to detect a switch operated by a human.

I think this is the logic you need

void loop() {
   readSwitch();
   operateBuzzer();
   checkTimeExpired();
}

void readSwitch() {
   when switch changes from OFF to ON
      set buzzerOn = true
      save the value of millis() in switchPressedMillis
}

void operateBuzzer() {
   if buzzerOn == true
     make noise
}

void checkTimeExpired() {
   if (millis() - switchPressedMillis >= buzzerDuration
      set buzzerOn = false
}

...R

thank you for your reply's gentlemen. i am using a 10k between ground and D2 and then applying or removing 5 volts to D2. what im finding now is that if i leave the switch closed (as it will be most of the time) the buzzer will sound randomly even if the switch isn't opened.. Im now looking at Mr Robin2's idea. even i with little understanding can see how tidy that looks.

well after lots of reading old posts ive got a very dirty bit of code doing mostly what i want. the bit im having problems with now is debounce. if the switch/relay closes after the buzzer/led has timed out it trips the buzzer again. but im really struggling with debounce. ive read lots but it just wont sink in. does anyone know of a idiots guide to debounce they can point me to.. thanks..

int pin = 3;                    // relay from access system
int led = 13;                   // will be a buzzer if i get it working
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the last button state
int val2;                       // variable for reading the delayed/debounced status

void setup()
{
  pinMode(pin, INPUT);
  pinMode(led, OUTPUT);
  buttonState = digitalRead(pin);   // read the initial state
}
long offAt = 0;
void loop(){

  if( (digitalRead(led) == LOW ) && (digitalRead(pin) == LOW) ) //if LED is off  and button is pressed
 {
    digitalWrite(led, HIGH);
    offAt = millis() + 5000; //store var of now + 5 seconds
 }
    if(digitalRead(led) == HIGH) //if led is on
  {
      if(millis() >= offAt) //see if it's time to turn off LED
      {
         digitalWrite(led, LOW); //it's time. this also re-enables the button
         {
         while(digitalRead(pin) == LOW) digitalWrite(led,LOW); // do nothing
         }
      }
  }
}

A few things (not necessarily all) …

You need to test when the button becomes pressed by comparing the state now with the previous state. Something like

prevButtonState = buttonState;
buttonState = digitalRead(buttonPin);
if (buttonState == LOW && prevButtonState == HIGH) {
    // do stuff

}

You should always test millis() with subtraction to avoid problems when it rolls over from 232-1 to 0. For example

if (millis() - offAtMillis >= 5000)

and don’t add 5000 to get the next time

A short interval (maybe 50 millisecs) between successive digitalRead()s should be sufficient to avoid bounce problems

…R