Help with Timer Library usage for completion of device functions!

Eyy Arduino guys! So we have a project to finish and I'm not well-versed into coding, even some of the simple ones most experienced people here could do.

I need to incorporate a timer logic into many of our functions for a wireless fire and panic alarm POC and I could only manage to execute some in a not-so-elegant way. The timers are based on the NFPA 72's specs for alarm transmission, alarm silencing, restoration and reset, which I'm going to add as features in our system.

I've downloaded the TaskScheduler library and even tried a number of similar libraries but failed to use them effectively, which the former managed otherwise in some ways specifically for alarm transmission. So no problem with that. However, the last three still give me headaches because I know the logic (do I?), but can't write them well in code effectively.

Here's the link to describe the three functions but just to sum it up for our system's context: 1. Silence - temporarily disable the device for 5 minutes from running into the main loop of functions, disable timers which send an alarm signal and activate the LEDs and buzzer. 2. Restore - bring back the device back to operation after being disabled or silenced. 3. Reset - put the device back to normal operating conditions after the networked fire alarm [all devices activating their LEDs and buzzers whether if they sensed the origin of fire or not] has been mobilized.

I could think of how to use the timers for the three functions but could not write them in code. Could someone help? Thank you very much. :D

Here’s the code, sorry it might be too long.

#include <VoltageReference.h> 
#include <XBee.h>             
#include <Printers.h>         
#include <AltSoftSerial.h>    
//#include "binary.h"           
//#include <Battery.h>             
//#include "LowPower.h"
//#include <ResponsiveAnalogRead.h> 
#include <TaskScheduler.h>  
#define DebugSerial Serial    
#define XBeeSerial SoftSerial 
#define VREF_EEPROM_ADDR (E2END -2)

byte activateBuzzer = 11, ledAlarm = 12, ledStatus = 13; 
byte manOpt = 4, manAct = 5, tamperCheck = 6, smokeCheck = 7, mainsCheck = 10; 
int battPin = A6, tempPin = A2; 
//ResponsiveAnalogRead analog(battPin, true); //comes with responsive analog read library for battery reading
XBeeWithCallbacks xbee; //This comes with the XBee.h, Printers.h, according to BO3778_Code Bundle examples from Chapter 2
VoltageReference vRef = VoltageReference(); //This comes with the voltage reference library
AltSoftSerial SoftSerial; 
  float battAve = 0.0, intRefRaw, intRefCalc;
    long prev_secs_held;    
    long millis_held;      
    long secs_held;     
    byte previous = LOW;
    unsigned long firstTime;
      int reading;
      float tempC;
        byte counter, powOnFlag, lowBatFlag, tempFlag, tampFlag, silFlag, manFlag; 

void autoFireTrans();
void manuFireTrans();
void powrTrans();
void tampTrans();
void letGo();

Task esA(3000, TASK_FOREVER, &autoFireTrans); //1 minute or less
Task esM(3000, TASK_FOREVER, &manuFireTrans); //1 minute or less
Task tsP(4000, TASK_FOREVER, &powrTrans); //every 24 hours or less
Task tsT(5000, TASK_FOREVER, &tampTrans); //every 24 hours or less
Task releaseHold(10000, 2, &letGo); //countdown timer for the silence and restore function
Scheduler runner;
          
void autoFireTrans() { 
  deployAlarm(1,0,0);
  sendPacket("autoFireDet");
}
void manuFireTrans() { 
  deployAlarm(1,0,0);
  sendPacket("manFireAct");
}
void powrTrans() { 
  deployAlarm(0,1,0);
  sendPacket("lowBatt");
}
void tampTrans() { 
  deployAlarm(0,0,1);
  sendPacket("tamperDet");
}
void letGo(){
  Serial.println("Initializing sequence..");
  if (releaseHold.isLastIteration()) {
    Serial.println("Releasing silence duration.");
    silFlag = 0;
    runner.addTask(esA);
    runner.addTask(esM);
    runner.addTask(tsP);
    runner.addTask(tsT);    
  }
}
   
void setup() {
  pinMode(ledAlarm, OUTPUT); 
  pinMode(ledStatus, OUTPUT);       
  pinMode(activateBuzzer, OUTPUT); 
  pinMode(mainsCheck, INPUT);
  pinMode(smokeCheck, INPUT);
  pinMode(tamperCheck, INPUT);   
  digitalWrite(manAct, LOW);
  digitalWrite(manOpt, LOW); 
    DebugSerial.begin(115200); 
    XBeeSerial.begin(9600);
    xbee.begin(XBeeSerial);
    DebugSerial.println(F("Initializing DebugSerial.."));
    delay(1);
       xbee.onPacketError(printErrorCb, (uintptr_t)(Print*)&DebugSerial);
       xbee.onResponse(printErrorCb, (uintptr_t)(Print*)&DebugSerial);
       xbee.onZBRxResponse(processRxPacketz);
          vRef.begin(EEPROM.read(VREF_EEPROM_ADDR), EEPROM.read(VREF_EEPROM_ADDR + 1), EEPROM.read(VREF_EEPROM_ADDR + 2));
          intRefRaw = vRef.internalValue();
          intRefCalc = intRefRaw/1000;
              runner.init();
}

void processRxPacketz(ZBRxResponse& rx, uintptr_t) {
  int actCodeNetAlrm = 11, actCodeNodeStat = 12, actCodeSilence = 13, actCodeRestore = 14;
  ...
  Buffer b(rx.getData(), rx.getDataLength());
  uint8_t type = b.remove<uint8_t>();
  XBeeAddress64 addr = rx.getRemoteAddress64();
    
    if (addr == 0x0013A200410407BC && type == 1 && b.len() == 2)
    {
      int codeSqnce = b.remove<int>();
        if (codeSqnce == actCodeNetAlrm){
          DebugSerial.println(F("Fire Alarm: Networked alarm sent by coordinator!!"));
          deployAlarm(1,0,0);
          return;         
        }
        else if (codeSqnce == actCodeNodeStat){
          DebugSerial.println(F("Poll received. Sending reply..."));
          sendPacket("pollStatus");
          return;         
        }
        else if (codeSqnce == actCodeSilence){
          silenceNode();
          return;         
        }
        else if (codeSqnce == actCodeRestore){
          DebugSerial.println("Restoring system to normal operation...");
          //restorationSequence(); 
          return;
        }
        else{    
          DebugSerial.println(F("Unknown or invalid packet"));
          printResponse(rx, DebugSerial);
        }  
    }
}

void sendPacket(String messageType){ 

   int actMsgAutoFire= 2; 
   int actMsgTamper  = 4;
   ...
  
   ZBTxRequest txRequest;
   txRequest.setAddress64(0x0000000000000000); 
   AllocBuffer<3> packet;
   packet.append<uint8_t>(1);
    if (messageType == "autoFireDet"){ 
      packet.append<int>(actMsgAutoFire);
      DebugSerial.println("Automatic detection fire alarm sent!");
    }
    else if (messageType == "tamperDet"){ 
      packet.append<int>(actMsgTamper);
      DebugSerial.println("Tampering alarm sent!");
    ...
    }
   txRequest.setPayload(packet.head, packet.len());
   xbee.send(txRequest);
   delay(10);
}

void deployAlarm(...){
...activate LEDs and buzzer
}

void notifUnits(...){
... activate LEDs for some purpose
}

I’ll post the second half in a while

Here it is.

void chckCasing (byte caseUnopened){
  if (caseUnopened == HIGH){
   tampFlag = 0;
   tsT.disable();
  }
  else if (caseUnopened == LOW){
    if (tampFlag == 0){
      DebugSerial.println("Tampering alarm transmission initialized..");
      runner.addTask(tsT);
      tsT.enable();
      tampFlag = 1;
    }
  }
}

void manCallPt(byte pressB1){
  if (pressB1 == HIGH){
    if (manFlag == 0){
      DebugSerial.println("Manual control options toggled!!");
      runner.addTask(esM);
      esM.enable();
      manFlag = 1;
    }
    runner.deleteTask(tsP);
    runner.deleteTask(tsT);
  }
  else if (pressB1 == LOW){
    runner.addTask(tsP); 
    runner.addTask(tsT); 
  }
}

void manCtrl(byte pressB2){     //pass the parameter stated in the function declaration to the function parameter int pressB
  if (pressB2 == HIGH && previous == LOW && (millis() - firstTime)>200){
    firstTime = millis();
  }
  millis_held = (millis()-firstTime);
  secs_held = millis_held/1000;
  if (millis_held > 50){
    if (pressB2 ==  HIGH && secs_held  > prev_secs_held){
      notifUnits(1,50,50,activateBuzzer,ledStatus);
    }
    if (pressB2 == LOW && previous  ==  HIGH){
      if (secs_held<=0){
       notifUnits(1,500,500,activateBuzzer,ledStatus);
      }
      else if (secs_held < 1 && secs_held > 9){
        notifUnits(2,250,250,activateBuzzer,ledStatus);
        DebugSerial.println("Invalid counts.");
      }
      else if (secs_held >= 1 && secs_held <= 3){
        silenceNode();
      }
      else if (secs_held >= 4 && secs_held <= 6){
        restoreNode();
      }
      else if (secs_held >= 7 && secs_held <= 9){
        resetNode();
      }
    }
 }
 previous = pressB2;
 prev_secs_held = secs_held;
}

void checkPowerState (byte powerCheckPin){ 
float battFull = 4.2, battNominal = 3.7, battEmpty = 3.2;
 if (counter==20){
  analogReference(INTERNAL);
  LowPower.adcNoiseReduction(SLEEP_15MS, ADC_ON, TIMER2_OFF);
  float battV_raw = analogRead(battPin);
  float battV_cal = battV_raw * 10.82;
  battAve = (battV_cal * 1.1) / 1024;  
  if (powerCheckPin == HIGH) {
    if (powOnFlag == 0){
      DebugSerial.println("Restoring from power failure - ");
      sendPacket("powStatOn"); //Power state change alert; from power failure to power restoration notify monitoring center
      powOnFlag = 1;
    } 
    DebugSerial.print("\n\nNormal Mode - Charge stdby: ");
    if (battAve<=battFull && batt>battNominal){
      DebugSerial.print("Ready.");
    }
    else if (battAve<=battNominal){
      if (battAve > (battEmpty + 0.100)){
        DebugSerial.print("Low Batt.");
      }
      else if (battAve <= battEmpty){
        DebugSerial.print("Batt empty.");
      }
    }
  }
  else if (powerCheckPin == LOW){
  DebugSerial.print("\n\n Battery Mode - Charge unavail: ");
  if (powOnFlag == 1){
    DebugSerial.print("Initial power failure - ");
    sendPacket("powStatOff");
    powOnFlag = 0;
  }
  if (battAve <= battFull && battAve >= battNominal){
    DebugSerial.print("Battery = Ready: ");
    sendPacket("battOkay");
    lowBatFlag = 0;
  }
  else if (battAve <= battNominal){
    if  (battAve > (battEmpty+0.100)){
    DebugSerial.print("Battery = Approaching low.");
    }
    else if (battAve < battEmpty){ //last and single trouble signal at fire alarm control unit when battery catastrophically fails. 
      DebugSerial.print("Battery: Critical. Node shutdown imminent.");
      sendPacket("powFail");
      //LowPower.powerDown(SLEEP_8S, ADC_ON, TIMER2_OFF);   to be addedd   
      }}}
  counter=0;
 }
 counter++;
}
unsigned long last_tx_time = 0;
float chckSensors (){
  reading = 0;
  for (int i = 0; i < 10; i++) { // Average 10 readings for accurate reading
    analogReference(INTERNAL);
    LowPower.adcNoiseReduction(SLEEP_15MS, ADC_ON, TIMER2_OFF);
    reading += analogRead(tempPin); 
    delay(10);
  }
  tempC =  (1.1 * reading * 10) / 1024;
  byte smokeFlag = digitalRead(smokeCheck);
  //tempC =  (internalRefCalculated * reading * 10) / 1024; 
  if (tempC>=32.00){
    if (tempFlag == 0 && smokeFlag == 0){
      Serial.println("Initial high temperature detected w/ smoke!");
      runner.addTask(esA);
      esA.enable();
      tempFlag = 1;
    }
    runner.deleteTask(tsP);
    runner.deleteTask(tsT);
    Serial.println("High temperature!");
  }
    else if (tempC<32.00 && smokeFlag == 1){  
    Serial.println("Temperature normal.");
    esA.disable();
    runner.addTask(tsP); 
    runner.addTask(tsT); 
    tempFlag = 0;  
  } 
}

void silenceNode (){ //temporarily disable other functions
  //Insert code dapat:
  //1. Set the silence flag to '1' so that the program flow wouldn't be able to enter the function below in the void loop()
  //2. Disable other timers included in the program
  //3. Enable the timer which sets the countdown to 5-10 minutes until the silence flag is set back to '0' again and the timers in the program would be enabled once again
  DebugSerial.println("Silencing device.");
  silFlag = 1;
  runner.addTask(releaseHold);
  releaseHold.enable();
  esA.disable();
  esM.disable();
  tsP.disable();
  tsT.disable();
}

void restoreNode(){ //reset other timers such as tempState, powrStateLowBatteryLow, turn output LED and buzzer pins low, etc. Instant reboot. System reboot is the restoration of all system devices. Singular = restoration, plural = reboot.
//Insert code dapat:
//1. Enable all disabled timers to resume operation
//2. Remove the "silence" condition of the device
  DebugSerial.println("Initializing restoration sequence...");
  silFlag = 0;
  runner.deleteTask(releaseHold);
}

void resetNode(){
//Insert code dapat:  
//1. Disable all enabled annunciator units during a fire alarm. I guess you have to activate a timer separate from the "fire alarm transmission" for activating the annunciator units
//, which would be used for the nodes which did not detect the fire itself, but activated the annunciator units due to a network alarm. Tampering and low battery alarms cannot be 
//reset.
}

void loop() {    
  xbee.loop();
  runner.execute();
    if (silFlag == 0){ //not ko alam if kailangan ko ilagay dito. Bale need ko kasi na kapag '1' yung silence flag [which is ginagawa ng isang function with timer sa taas],
      byte integState = digitalRead(tampChck);
      chckCasing(integState);
      byte powerState = digitalRead(mainsChck);
      chckPower(powerState);
      chckSensors();
      byte bttnState1 = digitalRead(manAct); //manual call point function with sending alert and buzzer activation
      manCallPt(bttnState1);   
    }    
 byte bttnState2 = digitalRead(manOpt); //nilagay ko siya sa labas ng " if (silFlag == 0) " kasi dapat always active yung input mo for the manual control button regardless 
 manCtrl(bttnState2);  //if nakasilence man siya, which is satisfied by the condition stated above. 
}