How to combine several conditions within one if statement

Hi, I've following code, it works as expected but just out of curiosity I wonder how would I do it without needing "else if" statement.

In my code, Arduino jumps to this ISR multiple times a second.

void CheckAlarmCondition()
{
  DateTime now = RTC.now();
  if(enableAlarm==true && now.hour()== alarmHour && now.minute()>=alarmMinute && now.minute()<alarmMinute+periodMin)
     {
      alarmActivated=true;
      digitalWrite(AlarmOut,LOW);
     } 
     else if(enableAlarm==true && now.hour()==alarmHour && now.minute()==alarmMinute+periodMin && now.second()<periodSec)
            {
            } 
            else if(alarmActivated==true)
                  {
                   digitalWrite(AlarmOut,HIGH);  //Deactivate Relay
                   lcd.clear();
                   alarmActivated=false;
                  }
}

I've set an alarm at 18:30(alarmHour:AlarmMinute)
I've set alarm duration as 3 minutes and 30 seconds(periodMin, periodSec)
I've enable the alarm(enableAlarm==true)

So my first if statement checks if alarm is enabled and it is 18 o'clock and current minute is >=30 and at the same time current minute is < 33;
Then Arduino change alarmActivated bool variable to true and activate(LOW is active in my case) AlarmOut pin.

So this if will be true when the time is 18:30 and 18:31 and 18:32. There is no need to check the seconds value yet so I dont check it in first if statement.

But when it is 18:33 now I need to check if there is periodSec to count. For this case as I set alarm period as 3 minutes 30 seconds so alarm should be still active for 30 more seconds. This condition is checked in "else if" statement. But as this condition might be true only in case the first if statement was true before, I dont need to activate the AlarmOut, as I didnt deactivate it yet.

After 30 seconds "else if" statement is also false, so arduino checks if alarmActivated was true meaning the first "if" statement run before. Then it deactivates AlarmOut.

This code should work, but it also does not make sense to have an else if condition that is actually empty. There should be more logical way to do this. What would be your recommendation?

I believe I need something like this:

if(a and b and c and d are true || or a and b and c and e are true)
{do this}

I'm not sure I completely understand what you want to achieve but I suspect you would be better cascading the IF statements rather than trying to combine them. It can be confusing to figure out an ELSE that follows a compound IF.

Something like this (I may have the logic wrong but you should get the idea

void CheckAlarmCondition()
{
    DateTime now = RTC.now();
    if(enableAlarm == true) {
        if (now.hour() == alarmHour) {
            if (now.minute() >= alarmMinute && now.minute() < (alarmMinute + periodMin)) {
                alarmActivated = true;
                digitalWrite(AlarmOut,LOW);
            } 
            else if(now.minute() == (alarmMinute + periodMin) && now.second() < periodSec)
            {
            } 
            else if(alarmActivated == true)
            {
                digitalWrite(AlarmOut,HIGH);  //Deactivate Relay
                lcd.clear();
                alarmActivated=false;
            }
        }
    }
}

However it seems to me that this much simpler version would work just as well

void CheckAlarmCondition()
{
    DateTime now = RTC.now();
    if(enableAlarm == true) {
        if (now.hour() == alarmHour) {
            if (now.minute() >= alarmMinute && now.minute() < (alarmMinute + periodMin)) {
                alarmActivated = true;
                digitalWrite(AlarmOut,LOW);
                alarmStartTime = millis();
            }
        }
    }

    if(alarmActivated == true and millis() - alarmStartTime >= alarmDuration) {
        digitalWrite(AlarmOut,HIGH);  //Deactivate Relay
        lcd.clear();
        alarmActivated=false;
    }
}

Also, if this was my project, I think I would convert the time to a number of seconds from some start date so I could test the whole thing with a single IF

Finally, you said "Arduino jumps to this ISR multiple times a second". I can't think of any reason to use an interrupt to check something that happens no more frequently than once per second?

...R

The goal shouldn't be to minimize the number of 'if' statements but to make the code easy to read and work on. Comments help.

void CheckAlarmCondition()
{
  DateTime now = RTC.now();


  // Was the alarm disabled while activated?
  if (alarmActivated && !alarmEnabled)
  {
    digitalWrite(AlarmOut, HIGH); // Deactivate Relay
    alarmActivated = false;
    lcd.clear();
  }


  // Are we in the alarm window?
  if (now.hour() == alarmHour &&
      ((now.minute() >= alarmMinute && now.minute() < (alarmMinute + periodMin)) ||
       ((now.minute() == (alarmMinute + periodMin) && (now.second() < periodSec)))))
  {
    // If the alarm is enabled but not yet activated:
    if (alarmEnabled && !alarmActivated)
    {
      // Activate it
      alarmActivated = true;
      digitalWrite(AlarmOut, LOW);  // Activate the relay
    }
  }
  else // Outside the alarm window
  {
    // If the alarm was active, deactivate it
    if (alarmActivated)
    {
      digitalWrite(AlarmOut, HIGH); //Deactivate Relay
      alarmActivated = false;
      lcd.clear();
    }
  }
}

Robin2:
I'm not sure I completely understand what you want to achieve but I suspect you would be better cascading the IF statements rather than trying to combine them. It can be confusing to figure out an ELSE that follows a compound IF.

Something like this (I may have the logic wrong but you should get the idea

Also, if this was my project, I think I would convert the time to a number of seconds from some start date so I could test the whole thing with a single IF

Finally, you said "Arduino jumps to this ISR multiple times a second". I can't think of any reason to use an interrupt to check something that happens no more frequently than once per second?

...R

Dear Robin2, thanks for the suggestion, using millis to compare the time makes sense. I belive first I need to convert period minutes and seconds to millis and compare it with current millis to activate or deactivate the output.

Dear Johnwasser, thank you as well, I'll add more comments to make it more clear but I'm still building the functions. I'm planning to simplify it and add comments in the end after making sure it works perfectly. Still changing too many things actually.

gunaygurer:
Dear Robin2, thanks for the suggestion, using millis to compare the time makes sense. I belive first I need to convert period minutes and seconds to millis and compare it with current millis to activate or deactivate the output..

Just to be clear, I was not suggesting that you convert real clock time to millis. I was suggesting that you could convert real clock time to a number of seconds since (say) midnight on 1 January 2019. That way you reduce the combination of days, hours, minutes and seconds to a single number.

Separately, I was suggesting that millis() would probably be a simpler way to manage the length of time the alarm would be ON. I am assuming that a small deviation from real clock time would be of no significance for the duration of the alarm signal.

...R