How to read an input immediately

Hello all,

Please forgive me for being new but I am overwhelmed with the amount of resources out there for the arduino. This is my first project and was working fine until it wasn’t. A little background: This code was designed to execute a timer (two actually) to ring a bell and activate a light in a firehouse. It is triggered by an already existing system. When the existing system activates, the arduino closes two relays for a 2 and 60 seconds, respectively.

This issue that I have is that when the existing system is triggered, it holds 24VAC for 10 seconds. That signal throws a relay that gives the arduino 5vdc on pin 2. With my current code, the timers don’t start counting until pin 2 is low again; Meaning, 10 seconds of “button being pressed” + 2 seconds of coded timer = 12 seconds of output.

How can I execute a timer immediately before the “button press” is released? I’ve tried an interrupt, and a timed button (e.g. long press vs short press). I am unable to get either working correctly. Below is my original code that works fine once the button on pin 2 is released. Any help you can provide is greatly appreciated.

/* Firehouse Alerting Timer
    version 1
    by Brian Clarke
    written 11/22/2016 at 23:24

    This sketch uses an input from the existing alerting system to trigger two independent timers.  One for the bells & horn, and another for the strobe lights.
*/
const int Bell =  13;      // the pin of the Bell relay
const int Strobe = 12;     // the pin of the Strobe relay
const int triggerPin = 2;    // the number of the system trigger pin


int triggerState = LOW;           // triggerState used to set initial trigger position


unsigned long timerA;            //create timer to be defined in loop
unsigned long timerB;

const long intervalBell = 2000;    //Set individual timer length 
const long intervalStrobe = 60000;

void setup() {
  pinMode(Bell, OUTPUT);
  pinMode(Strobe, OUTPUT);
  pinMode(triggerPin, INPUT);
}

void loop() {
  triggerState = digitalRead(triggerPin);

  if (triggerState == HIGH) {
    timerA = millis();
    digitalWrite(Bell, HIGH);
  }
  if (millis() - timerA >= intervalBell) {
    digitalWrite(Bell, LOW);  // Close Bell relay
  }
  if (triggerState == HIGH) {
    timerB = millis();
    digitalWrite(Strobe, HIGH);
  }
  if (millis() - timerB >= intervalStrobe) {
    digitalWrite(Strobe, LOW);  // Close Strobe relay
  }

}

No, the timers do start counting.

You just reset the timers to millis() every round through loop as long as the pin is HIGH.

You need to store the last state of the button, so you can see when it's HIGH and the last time it went through loop, it was low, then you set the timers - but not if the button is HIGH and was HIGH last round through loop.

Thank you so much for your help. The code works wonderfully now. I added a lastState variable and updated the loop to this:

void loop() {
  triggerState = digitalRead(triggerPin);
   if (triggerState != lastState) {
    lastState = HIGH;
  }
  else {
    lastState = LOW;
  }

  if (triggerState == HIGH && lastState == HIGH) {
    timerA = millis();
    digitalWrite(Bell, HIGH);
  }
  if (millis() - timerA >= intervalBell) {
    digitalWrite(Bell, LOW);
  }
  if (triggerState == HIGH && lastState == HIGH) {
    timerB = millis();
    digitalWrite(Strobe, HIGH);
  }
  if (millis() - timerB >= intervalStrobe) {
    digitalWrite(Strobe, LOW);
  }
  lastState = triggerState;
}

Thanks again!