Alarm.timeronce not calling function

I have a relay and push button hooked up to my arduino. Basically i want to hold down the pushbutton for a certain amount of time, and then switch the relay for several minutes. For testing purposes I only switch it for a couple o seconds though.

The odd thing is, while my calculations and the switching on of the relay works, the alarm timer does not trigger the OnceOnly function, and thus my relay does not switch back off. For testing purposes you can also use a LED instead of relay.

The code uses this library: Arduino Playground - Time

Here is my code.

#include <Time.h>
#include <TimeAlarms.h>

AlarmId timerId = 0;

int relayPin = 5;
int btnPin = 4;

int outLevel = HIGH; // MUST BE INVERTED FOR THIS SPECIFIC RELAY MODULE

boolean buttonDown = false;
int starttime = 0;

boolean alwaysOnMode = false;


void setup()
{
  Serial.begin(9600);
  setTime(0,0,1,1,1,11);
  
  pinMode(relayPin, OUTPUT);
  pinMode(btnPin, INPUT);
  
  switchRelay();
}

void setTimerSeconds(int delayInSec) {
  cancelTimer();
  outLevel = LOW;
  Serial.println("Timer switching on");
  switchRelay();
  timerId = Alarm.timerOnce(delayInSec, OnceOnly);
}

void cancelTimer() {
  if (timerId != 0) {
    Alarm.disable(timerId);
    timerId = 0;
  }
}

void OnceOnly(){
    Serial.println("Reseting relay");

  alwaysOnMode = false;
  outLevel = HIGH; //OFF
  switchRelay();
}

void switchRelay() {
  digitalWrite(relayPin, outLevel);
}

boolean isRelayOn() {
  return digitalRead(relayPin) == LOW;
}

void loop()
{
  // Chick is button pressed
  if (digitalRead(btnPin) == HIGH) {
    Alarm.delay(10);
    if (buttonDown != true) {
      buttonDown = true;
      starttime = millis();
    }
  } else if (buttonDown == true) { // If not pressed but previously down
    buttonDown = false;
    if (isRelayOn() && timerId != 0) {
      OnceOnly(); // Button press when relay on switches it off.
    } else {
      int stoppedat = millis();
      int ellapsed = stoppedat - starttime;
      int pressed = (int)(ellapsed)/1000;
      alwaysOnMode = true;
      setTimerSeconds(pressed);
    }
  }
 
}
  pinMode(btnPin, INPUT);

No use of the internal pullup resistor. So, you have an external pullup or pulldown resistor, right? How IS the switch wired?

  if (digitalRead(btnPin) == HIGH) {

This implies a pulldown resistor.

int starttime = 0;

      int stoppedat = millis();

millis() returns an unsigned long, not an int. After running 32.7 seconds, your code is hosed.

PaulS:
This implies a pulldown resistor.

Correct. since i will port this to an attiny and i need 2 buttons doing the same thing, i actually have 2 buttons set up like this: both buttons hooked up to 5V at one end. Both other ends each grounded with resistor and both connected to pin 4.

PaulS:
millis() returns an unsigned long, not an int. After running 32.7 seconds, your code is hosed.

Ok. Good to know. But so far i have tested this within first few seconds of startup, and the timing works up to that point. (32.7 seconds) i have not tried thereafter.

But the alert still does not trigger my switch off function.

I can't quite follow the logic to initiate the timer, or when it is supposed to fire.

I really don't see the need for the timer interrupt, either.

You can debug your code with (lots) more Serial.print() statements, or you can get rid of the interrupts and timer, and simply use millis() to time how long the switch is pressed and whether it is time to turn the relay off again.

My own timer there measures 2 things. 1. Cheks if the button was pressed while the relay is on, in order to switch it off. 2. It measures the seconds the button was held down, in order to switch the relay on.

For each second the button is pressed i want to actually turn on the relay for 30 minutes.
For testing purposes though i set the interrupt timer to only a couple of seconds. To be exact, the number of seconds the button was pressed. This could be any fixed value though. For production i will have to multiply this pressed time x 60 (seconds) x 30 (minutes).

I thought it might be easier to use the alarm timer than to implement a timing function using millis to time such a long period. I might just have to do this though if i can not get the alarm timer to work.