Timing to turn components on at same time, for dif amount of time

Hi

I am not an expert at this however i feel comfortable with using Millis to control the timings of components. So far i have been operating a 4 channel relay to turn on and off a pump, a mister and a fan for a indoor gardening experiment. The pump controls root watering but im using a mister and a fan for the foliage, so in this sense the mister and fan need to be in sync.

I got this to work with the timings i need using millis, however after seeing it in action i realised the fan needs to stay on for longer than the mister, as there is residue mist left over that i want to move with the fan.

I was previously using a class to neaten the code up, but i think its important to show here what im trying to do to make the fan stay on for longer.

const byte relay1 = 8; //relay pins // this relay is not linked to the others in terms of timing requirement
const byte relay2 = 7; // relay 2 & 3 need to work together, if they fall out of sync exp fails 
const byte relay3 = 4; // relay 2 is a fan relay 3 is a mist maker 

int relay1State = HIGH; // to assess if relays on or off
int relay2State = HIGH;
int relay3State = HIGH;



unsigned long relay1Millis = 0; // keep time for each
unsigned long relay2Millis = 0;
unsigned long relay3Millis = 0;

const long relay1ON = 5000; // on and off intervals
const long relay1OFF = 300000;
const long relay2ON = 20000; // want fan on for 20 secs
const long relay2OFF = 190000;
const long relay3ON = 10000; // want pump on for 10 secs at same time 
const long relay3OFF = 200000; 

void setup() {
  // put your setup code here, to run once:
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);

  digitalWrite(relay1, HIGH);
  digitalWrite(relay2, HIGH);
  digitalWrite(relay3, HIGH); 
  

}

void loop() {
  // put your main code here, to run repeatedly:
  unsigned long   currentMillis = millis(); 

  if ((relay1State == LOW) && (currentMillis - relay1Millis) >= relay1ON) // check status of relay, checks if its time to switch it off/on 
  {                                                                       
    relay1State = HIGH;
    relay1Millis = currentMillis;
    digitalWrite(relay1, relay1State);

  }
  else if ((relay1State == HIGH) && (currentMillis - relay1Millis) >= relay1OFF) { // check if its time to turn off 
    relay1State = LOW;
    relay1Millis = currentMillis; 
    digitalWrite(relay1, relay1State);
  }

  if ((relay2State == LOW) && (currentMillis - relay2Millis) >= relay2ON)
  {
    relay2State = HIGH;
    // typically would take millis (relay2Millis = currentMillis)
    // but trying to make this value to align with the mist 
    digitalWrite(relay2, relay2State);

  }
  else if ((relay2State == HIGH) && (currentMillis - relay2Millis) >= relay2OFF) {
    relay2State = LOW;
   // same again
    digitalWrite(relay2, relay2State);
  }

  if ((relay3State == LOW) && (currentMillis - relay3Millis) >= relay3ON)
  {
    relay3State = HIGH;
    relay2Millis = currentMillis; // set it here to try to time both based on the last time fan was active 
    relay3Millis = currentMillis;
    digitalWrite(relay3, relay3State);
    

  }
  else if ((relay3State == HIGH) && (currentMillis - relay3Millis) >= relay3OFF) {
    relay3State = LOW;
    relay2Millis = currentMillis;
    relay3Millis = currentMillis;
    digitalWrite(relay3, relay3State);
  }
}

It doesnt work in the way i want it to, either the timings fall out of sync or the fan comes on and then switches to the mister, resulting in it not being active at the same time. I'm sure theres another way of doing it, i just thought about what may work and tried it, and now im here :stuck_out_tongue_closed_eyes:

Any help would be greatly appreciated, i may be missing something obvious.

Neb

Firstly, it would make sense to use decent names like pumpState and pumpRelay; it will make it far easier to understand.

For the problem, there is a dependency between two of your relays. So whichever relay depends on whichever other one needs to have that dependency included in the if/else if.

sterretje:
For the problem, there is a dependency between two of your relays. So whichever relay depends on whichever other one needs to have that dependency included in the if/else if.

Good point about the variable names, and thanks for the answer. I have no idea how to include a dependency, thats the first time i have come across the term, but it sounds like its what i require. Any links/description on what it is and how to use it?

Thanks a lot

It's not programming related, just meaning that something depends on something else. You already use is for testing the millis() stuff like

  if ((relay2State == LOW) && (currentMillis - relay2Millis) >= relay2ON)

where your timing check depends on the state of the relay state.

You can make the above depend on the state of the first relay using

  if ((relay1State == HIGH && relay2State == LOW) && (currentMillis - relay2Millis) >= relay2ON)

Note that this is only for demo, it's more than likely the wrong one that I picked.

Typed this once but the forum is acting up for me today.

When you turn the mister on, turn on the fan and set its state and time variables.

Get rid of the other code that turns the fan on, but retain the bit that turns it off.

I changed the names to make it more clear and structured the code to make it clear what is independent and what is dependent. I changed the long variables to unsigned. I tested this revised code.

const byte PumpRelayPin = 8;
const byte FanRelayPin = 7;
const byte MisterRelayPin = 4;

unsigned long pumpTimestamp;
unsigned long fanTimestamp;
unsigned long misterTimestamp;

unsigned long pumpDelay = 5000UL;
const unsigned long FanDelay = 20000UL;
unsigned long misterDelay = 10000UL;


void setup() {
  pinMode(PumpRelayPin, OUTPUT);
  digitalWrite(PumpRelayPin, HIGH);
  pumpTimestamp = millis();
  pinMode(FanRelayPin, OUTPUT);
  digitalWrite(FanRelayPin, HIGH);
  fanTimestamp = millis();
  pinMode(MisterRelayPin, OUTPUT);
  digitalWrite(MisterRelayPin, HIGH);
  misterTimestamp = millis();
}

void loop() {
  managePump();
  manageMisterAndFan();
}

void managePump() {
  if (millis() - pumpTimestamp >= pumpDelay) {
    int pumpState = digitalRead(PumpRelayPin);
    if (pumpState == LOW) {
      digitalWrite(PumpRelayPin, HIGH);
      pumpDelay = 5000UL;
      pumpTimestamp = millis();
    }
    else {
      digitalWrite(PumpRelayPin, LOW);
      pumpDelay = 300000UL;
      pumpTimestamp = millis();
    }
  }
}

void manageMisterAndFan() {
  if (millis() - misterTimestamp >= misterDelay) {
    int misterState = digitalRead(MisterRelayPin);
    if (misterState == LOW) {
      digitalWrite(MisterRelayPin, HIGH);
      digitalWrite(FanRelayPin, HIGH);
      misterDelay = 10000UL;
      misterTimestamp = millis();
      fanTimestamp = misterTimestamp;
    }
    else {
      digitalWrite(MisterRelayPin, LOW);
      misterDelay = 200000UL;
      misterTimestamp = millis();
    }
  }
  if (millis() - fanTimestamp >= FanDelay) digitalWrite(FanRelayPin, LOW);
}

wildbill:
Typed this once but the forum is acting up for me today.

You're not the only one. It's reported on github.

Perehama:
I changed the names to make it more clear and structured the code to make it clear what is independent and what is dependent.

Thanks a lot, it made a lot of sense reading through that, it cleared it up for me! I appreciate the help, using the code now, adding another pump soon :slight_smile:

wildbill:
Typed this once but the forum is acting up for me today.
When you turn the mister on, turn on the fan and set its state and time variables.
Get rid of the other code that turns the fan on, but retain the bit that turns it off.

I couldn't connect earlier either, and yeah i didn't realise i could control it like that for some reason, thanks