How do I set up multiple interrupt cycle timers to control separate relays.

Hey Gang! :slight_smile:

I am three days into learning my programming for Arduino and I have hit a wall....repeatedly. :blush:

I am trying to program a timer to control four different pumps attached to relays. I would like each relay to cycle at separate time intervals from eachother. I need each relay timer to have an adjustable time on and time off. (i.e. 5 min on and 1 min off)

I have worked out a basic code and have them slightly working, but I have not had any luck finding resources to further my efforts. I would appreciate any constructive help in programming and explaining what I am doing right and or wrong. I would like to learn as much as possible about all of this. Of course, if someone is really bored and would create the code itself or an example for me to follow that would be great too! Please keep in mind that I am less than a week into all of this but not unfamiliar with electronics just the coding for Arduino.

I am using:
1 - Arduino Uno R3 board
1 - Quad relay module board (with opto-couplers)
1 - 5v usb power supply

Here is the code I have worked up so far as practice. (I have noticed my current code loses sync over about a minute. I do not understand why.)

//Cycle timer for quad relay module no delay function. 


//Define relay pins
#define R1 7
#define R2 6
#define R3 5
#define R4 4


// DEFINE RELAY STATE
int R1State = LOW;
int R2State = LOW;
int R3State = LOW;
int R4State = LOW;


// Millis setup
long previousMillis1 = 0;
long previousMillis2 = 0;
long previousMillis3 = 0;
long previousMillis4 = 0;
 
//Interval setup
long interval1 = 2000;
long interval2 = 1000;
long interval3 = 500;
long interval4 = 250;


// Setup functions
void setup()
{
  
  // Pin functions
  pinMode (R1, OUTPUT);
  pinMode (R2, OUTPUT);
  pinMode (R3, OUTPUT);
  pinMode (R4, OUTPUT);

}

// Loop Setup
void loop()
{
  
  unsigned long currentMillis1 = millis();
  unsigned long currentMillis2 = millis();
  unsigned long currentMillis3 = millis();
  unsigned long currentMillis4 = millis();
  
  
  // Relay 1
  if(currentMillis1 - previousMillis1 >interval1) {
    previousMillis1 = currentMillis1;
   
    
    if (R1State == LOW)
    R1State = HIGH; 
    else
    R1State = LOW;
    
    digitalWrite(R1, R1State);}
    
    
    // Relay 2
     if(currentMillis2 - previousMillis2 >interval2) {
    previousMillis2 = currentMillis2;
    
     
    if (R2State == LOW)
    R2State = HIGH;
    else
    R2State = LOW;
    
    digitalWrite(R2, R2State);}
    
     
  // Relay 3   
     if(currentMillis3 - previousMillis3 >interval3) {
    previousMillis3 = currentMillis3;
    
     
    if (R3State == LOW)
    R3State = HIGH;
    else
    R3State = LOW;
  
    
    digitalWrite(R3, R3State);}
    
  // Relay 4  
      if(currentMillis4 - previousMillis4 >interval4) {
    previousMillis4 = currentMillis4;
    
     
    if (R4State == LOW)
    R4State = HIGH;
    else
    R4State = LOW; 
    
    digitalWrite(R4, R4State);}
   
 }

Cheers,

Will

I am three days into learning my programming for Arduino

Then, that's far too early to be dealing with interrupts.

Tools + Auto Format, yes.
Reading the stickies, and learning how to post code correctly, yes.
Learning about arrays, yes.

Interrupts, no.

The time values should be stored in unsigned long variables, not long variables.

You only need one variable to hold currentMillis.

Any time you find yourself numbering similar variables to tell them apart, you should consider whether you should be using arrays. The answer in this case is yes. With the time values held in arrays, you can use a single for loop to apply the same log to each pin.

You code layout is unconventional and IMO not very clear. It would be better if you get into the habit of always using a { and } compound statement after each conditional expression (even when there is only one statement in the block), always put each { and } on separate lines with matching pairs indented by the same amount and the lines between the indented one extra level. If you get the code on the right lines, the tools/autoformat option will sort out the indentation for you.

At the moment you are using the same value for the on duration and off duration for each pin. You said that you want different on and off times. In that case you will need to hold these separately and use the appropriate value according to the current pin state when you are checking the timer.

I don't know how accurately you expect to maintain sync over a minute or how much it's slipping by, but there is a slight change to the timing code which will eliminate one cause of slip. Replace:

previousMillis1 = currentMillis;

with

previousMillis1 += interval1;

(Of course you will also want to change this code to use arrays instead of numbered variables.)

you can use my timer library, very simple to use. no delays, small footprint.

after you import the library, check the sample and test it.

/*
      Title: Simple Switch Timer
      Library: sstimer.ino
      Description: 
      Created Date: January 17, 2015
      Created By: Rolly Falco Villacacan
      Released into the public domain.
*/

#include <sstimer.h>

//WATER_PUMP SETUP
int PIN_NO1 = 13;
long unsigned OFF_DURATION = 500; //in milliseconds HOW LONG YOU WANT THE PIN TO BE OFF STATE
long unsigned ON_DURATION = 500; //in milliseconds //HOW LONG YOU WANT THE PIN TO BE ON STATE

//LIGHTHING SETUP
int PIN_NO2 = 12;
long unsigned OFF_DURATION2 = 1000; //in milliseconds
long unsigned ON_DURATION2 = 1000; //in milliseconds


sstimer WATER_PUMP(PIN_NO1, ON_DURATION, OFF_DURATION); //create instance for water pump
sstimer LIGHTHING(PIN_NO2, ON_DURATION2, OFF_DURATION2);//create instance for lighting

void setup(){
//...  
}


void loop(){
//...
WATER_PUMP.check();
LIGHTHING.check();
//..  
}

The demo several things at a time shows how to manage timing using millis().

Also look at how it organizes the code into small functions.

...R