Need to use multiple timers, Mega 2560

I have a simple project where I need 20 individual timers. I have 20 inputs (momentary buttons) and 20 outputs (relay activation). I need each output to stay "high" for a certain amount of time when its corresponding button is pressed. The time interval is the same for each output, likely between 60 and 120 minutes.

I just need to know how to set up the code to allow that many timers.

Thanks in advance.

One method quickly comes to mind: Set up 3 variables for each button, one for onTime, one for duration, and one for onState. When a button is pressed make its onTime = millis(), set duration for how long in milliseconds, and set onState to a non-zero value. Each loop through the program compare onTime + duration to millis(), and when millis() is equal or greater clear onState which you use to control the associated relay.

minor update: Instead of 3 variables, just use two. On button press set the duration variable to millis() + how long you want the relay on in milliseconds. Then with each loop compare duration to millis() and if millis() is equal or greater clear the onState variable to turn off the relay.

harralk:
I have a simple project where I need 20 individual timers. I have 20 inputs (momentary buttons) and 20 outputs (relay activation). I need each output to stay "high" for a certain amount of time when its corresponding button is pressed. The time interval is the same for each output, likely between 60 and 120 minutes.

I just need to know how to set up the code to allow that many timers.

Thanks in advance.

If the timing can be to the closest millisecond or two then use millis() for timing but be aware that

The timing variables must be of type unsigned long.

  • Unsigned to not be affected at the dreaded "rollover" that signed integers need limit check for.
  • Long to be able to measure 60+ minutes. unsigned long can time intervals up to 49.71--- DAYS.

unsigned long timeStart;
unsigned long timeElapsed;

..... somewhere during execution, this runs
timeStart = millis(); // millis clock is always running, round and round

..... some time later we want to know how long since start
timeElapsed = millis() - timeStart;

timeElapsed will always be 0 or more, it is unsigned so can't be negative.
It will ALWAYS be the difference between the end time and start time, subtraction yields difference.

If I try to simply add an interval to a start time and then compare current time to that total, as soon as the addition causes rollover the new end time will be less than all current times until current time also rolls over. Only by making the subtraction to get the difference will one simple formula ALWAYS work.

You can make an array of start times and an array of interval times or you can make an array of structs that hold one of each and that's just two good ways to hold the data for 20 timers.

Thanks a lot for the help, guys. Here's the resulting code I have, I guess you can call it a "latch timer" or whatever. I know it's not pretty, but it works. I'm working on building the code for channel 3+, I'm sure there's a way to do this with arrays or something that would probably do the same thing in like 5 lines of code or something, oh well.

int buttonState1;
int buttonState2;
int buttonState3;
int buttonState4;

int buttonState20;

int lastButtonState1;
int lastButtonState2;
int lastButtonState3;
int lastButtonState4;

int lastButtonState20;

unsigned long startTime1;
unsigned long startTime2;
unsigned long startTime3;
unsigned long startTime4;

unsigned long startTime20;

#define relay1Pin  13      // the number of the relay pin
#define relay2Pin  12
#define relay3Pin  11
#define relay4Pin  10

#define relay20Pin  19

int relayState1 = LOW; // relayState used to evaluate relay
int relayState2 = LOW;
int relayState3 = LOW;
int relayState4 = LOW;

int relayState20 = LOW;



long interval = 5000;           // interval for which to hold relay "HIGH" (milliseconds) (1 hour=3600 milliseconds)

void setup() {
  
pinMode(relay1Pin, OUTPUT);
pinMode(relay2Pin, OUTPUT);
pinMode(relay3Pin, OUTPUT);
pinMode(relay4Pin, OUTPUT);

pinMode(relay20Pin, OUTPUT);   

pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
pinMode(A3, INPUT);

pinMode(51, INPUT);

digitalWrite(A0, HIGH);  // set pullup on analog pin A0
digitalWrite(A1, HIGH);
digitalWrite(A2, HIGH);
digitalWrite(A3, HIGH);

digitalWrite(50, HIGH);

digitalWrite(13, LOW);
digitalWrite(12, LOW);
digitalWrite(11, LOW);
digitalWrite(10, LOW);

digitalWrite(19, LOW);

}

void loop()
{
//-------------------------------------------------------------------------------------------------------------------------------------------------
// check for button press (1)
   buttonState1 = digitalRead(A0);                   // read the button state and store
   relayState1 = digitalRead(relay1Pin);
   if (buttonState1 == LOW && lastButtonState1 == HIGH && relayState1 == LOW){     // check for a high to low transition
      // if true then found a new button press while clock is not running - start the clock

      startTime1 = millis();                                   // store the start time
      delay(10);                                               // short delay to debounce switch
      digitalWrite(relay1Pin, HIGH);
      lastButtonState1 = buttonState1;                          // store buttonState in lastButtonState, to compare next time
  
   }
   else if (buttonState1 == LOW && lastButtonState1 == HIGH && relayState1 == HIGH){     // check for a high to low transition
      // if true then found a new button press while clock is running - stop the clock and report
       
        digitalWrite(relay1Pin, LOW);
        lastButtonState1 = buttonState1;                     // store buttonState in lastButtonState, to compare next time

   }
   
   else{
      lastButtonState1 = buttonState1;                         // store buttonState in lastButtonState, to compare next time
   }

  
if ( (millis() - startTime1 > interval) ) {

      if (relayState1 == HIGH){
        
         // if the LED is off turn it on and vice-versa.
         if (relayState1 == HIGH)
            relayState1 = LOW;
         else
            relayState1 = LOW;
         
         digitalWrite(relay1Pin, relayState1);
      
      }
      else{
         digitalWrite(relay1Pin, LOW);                         // turn off LED when not blinking
      }
      
      }


//----------------------------------------------------------------------------------------------------------------------------------------------------
   // check for button press (2)
   buttonState2 = digitalRead(A1);                   
   relayState2 = digitalRead(relay2Pin);
   if (buttonState2 == LOW && lastButtonState2 == HIGH && relayState2 == LOW){     
      
      startTime2 = millis();                                   
      delay(10);                                               
      digitalWrite(relay2Pin, HIGH);
      lastButtonState2 = buttonState2;                    
    }
   else if (buttonState2 == LOW && lastButtonState2 == HIGH && relayState2 == HIGH){     
             
        digitalWrite(relay2Pin, LOW);
        lastButtonState2 = buttonState2;                     
   }
      else{
      lastButtonState2 = buttonState2;                         
   }

  
if ( (millis() - startTime2 > interval) ) {

      if (relayState2 == HIGH){
        
         if (relayState2 == HIGH)
            relayState2 = LOW;
         else
            relayState2 = LOW;
         digitalWrite(relay2Pin, relayState2);
            }
      else{
         digitalWrite(relay2Pin, LOW);                         
      }
      
      }
 //----------------------------------------------------------------------------------------------------------------------------------------------------
         
// check for button press (3)
   buttonState3 = digitalRead(A2);                   
   relayState3 = digitalRead(relay3Pin);
   if (buttonState3 == LOW && lastButtonState3 == HIGH && relayState3 == LOW){     
      
      startTime3 = millis();                                   
      delay(10);                                               
      digitalWrite(relay3Pin, HIGH);
      lastButtonState3 = buttonState3;                    
    }
   else if (buttonState3 == LOW && lastButtonState3 == HIGH && relayState3 == HIGH){     
             
        digitalWrite(relay3Pin, LOW);
        lastButtonState3 = buttonState3;                     
   }
      else{
      lastButtonState3 = buttonState3;                         
   }

  
if ( (millis() - startTime3 > interval) ) {

      if (relayState3 == HIGH){
        
         if (relayState3 == HIGH)
            relayState3 = LOW;
         else
            relayState3 = LOW;
         digitalWrite(relay3Pin, relayState3);
            }
      else{
         digitalWrite(relay3Pin, LOW);                         
      }
      
      }
 //----------------------------------------------------------------------------------------------------------------------------------------------------

}