Timed relay actuation

I'm trying to run a heater coil, a blower and a motor at certain intervals of time using relays.

The heater and the blower are just turned on and off at set intervals.

The motor however, uses two relays, one for forward and one for reverse, I need help to make sure the reverse relay isn't turning on when the forward is running and vice versa.

Currently, the code actuates both motor relays at once which would fry the motor coils.

int blowerPin =  13;
int blowerState = LOW;
unsigned long blowerMillis = 0;
long blowerOnTime = 30000;           // milliseconds of on-time
long blowerOffTime = 1000;          // milliseconds of off-time

int heaterPin =  12;
int heaterState = LOW;
unsigned long heaterMillis = 0;
long heaterOnTime = 30000;           // milliseconds of on-time
long heaterOffTime = 1000;          // milliseconds of off-time

int motorPinFWD =  11;
int motorStateFWD = LOW;
unsigned long motorMillisFWD = 0;
long motorOnTimeFWD = 30000;           // milliseconds of on-time
long motorOffTimeFWD = 30000;          // milliseconds of off-time


int motorPinREV =  10;
int motorStateREV = LOW;
unsigned long motorMillisREV = 0;
long motorOnTimeREV = 30000;           // milliseconds of on-time
long motorOffTimeREV = 30000;          // milliseconds of off-time


void setup()
{
  pinMode(blowerPin, OUTPUT);
  pinMode(heaterPin, OUTPUT);
  pinMode(motorPinFWD, OUTPUT);
  pinMode(motorPinREV, OUTPUT);
}

void loop()
{
  unsigned long currentMillis = millis();

  if ((blowerState == HIGH) && (currentMillis - blowerMillis >= blowerOnTime))
  {
    blowerState = LOW;
    blowerMillis = currentMillis;
    digitalWrite(blowerPin, blowerState);
  }
  else if ((blowerState == LOW) && (currentMillis - blowerMillis >= blowerOffTime))
  {
    blowerState = HIGH;
    blowerMillis = currentMillis;
    digitalWrite(blowerPin, blowerState);
  }

  if ((heaterState == HIGH) && (currentMillis - heaterMillis >= heaterOnTime))
  {
    heaterState = LOW;
    heaterMillis = currentMillis;
    digitalWrite(heaterPin, heaterState);
  }
  else if ((heaterState == LOW) && (currentMillis - heaterMillis >= heaterOffTime))
  {
    heaterState = HIGH;
    heaterMillis = currentMillis;
    digitalWrite(heaterPin, heaterState);
  }

  if ((motorStateFWD == HIGH) && (currentMillis - motorMillisFWD >= motorOnTimeFWD))
  {
    motorStateFWD = LOW;
    motorMillisFWD = currentMillis;
    digitalWrite(motorPinFWD, motorStateFWD);
  }
  else if ((motorStateFWD == LOW) && (currentMillis - motorMillisFWD >= motorOffTimeFWD))
  {
    motorStateFWD = HIGH;
    motorMillisFWD = currentMillis;
    digitalWrite(motorPinFWD, motorStateFWD);
  }

  if ((motorStateREV == HIGH) && (currentMillis - motorMillisREV >= motorOnTimeREV))
  {
    motorStateREV = LOW;
    motorMillisREV = currentMillis;
    digitalWrite(motorPinREV, motorStateREV);
  }
  else if ((motorStateREV == LOW) && (currentMillis - motorMillisREV >= motorOffTimeREV))
  {
    motorStateREV = HIGH;
    motorMillisREV = currentMillis;
    digitalWrite(motorPinREV, motorStateREV);
  }
}

(deleted)

I'm thinking something like:

if ((motorStateFWD == HIGH  && motorStateREV == !HIGH) && (currentMillis - motorMillisFWD >= motorOnTimeFWD))
  {
    motorStateFWD = LOW;
    motorMillisFWD = currentMillis;
    digitalWrite(motorPinFWD, motorStateFWD);

Using the OFF state of the opposite coil, aka 'interlocking', will prevent the FWD coil code from executing if REV is also currently active.

There are also available reversing contactors for this purpose which have a mechanical interlock.

Right now you seem to be treating the FORWARD and REVERSE as two separate timers:

int motorPinFWD =  11;
int motorStateFWD = LOW;
unsigned long motorMillisFWD = 0;
long motorOnTimeFWD = 30000;           // milliseconds of on-time
long motorOffTimeFWD = 30000;          // milliseconds of off-time

int motorPinREV =  10;
int motorStateREV = LOW;
unsigned long motorMillisREV = 0;
long motorOnTimeREV = 30000;           // milliseconds of on-time
long motorOffTimeREV = 30000;          // milliseconds of off-time

It's like you are blinking the FORWARD on and off every 30 seconds and blinking the REVERSE on and off every 30 seconds. Did you intend to alternate between forward and reverse every 30 seconds? Or maybe FORWARD, OFF, REVERSE, OFF each 30 seconds?

I'm going to guess alternating forward and reverse:

  if (currentMillis - motorMillisFWD >= motorOnTimeFWD)
  {
    motorMillisFWD = currentMillis;
    // Time for  change!
    if (motorStateFWD) { // Motor is in forward
      // Switching to REVERSE
        digitalWrite(motorPinFWD, HIGH);   // HIGH before LOW to prevent a short circuit
        digitalWrite(motorPinREV, LOW);
        motorStateFWD = false;
    } else { // Motor is in reverse
      // Switching to FORWARD
        digitalWrite(motorPinREV, HIGH);  // HIGH before LOW to prevent a short circuit
        digitalWrite(motorPinFWD LOW);
        motorStateFWD = true;
    }
 }  // end timer

WARNING: Put an external pull-up resistor on the motor relay output pins so they power up DEACTIVATED. The processor resets to all pins input so the pins will be floating. Having both float LOW will turn both relays on and cause a short circuit.

WARNING: Write HIGH to the motor relay pins BEFORE setting them to OUTPUT. Having both drive LOW will turn both relays on and cause a short circuit.

Hi,

Anjanbabu:
I'm trying to run a heater coil, a blower and a motor at certain intervals of time using relays.

The heater and the blower are just turned on and off at set intervals.

The motor however, uses two relays, one for forward and one for reverse, I need help to make sure the reverse relay isn't turning on when the forward is running and vice versa.

Currently, the code actuates both motor relays at once which would fry the motor coils.

Why not have one relay to turn the motor ON/OFF, the other FOR/REV.
That way you will never have FOR and REV on at the same time.
You must need an OFF state to let the motor come to a stop before changing direction.
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Thanks.. Tom.. :slight_smile:

Wouldn't the safest, proper way to handle this be electrically, using a relay such as dougp suggested or a contactor/relay with auxiliary contacts or a contactor/relay with one more set of contacts than are needed to energize the motor? The contactor/relay would need to be double throw or have normally closed aux contacts. - Scotty

scottyjr:
Wouldn't the safest, proper way to handle this be electrically, using a relay such as dougp suggested or a contactor/relay with auxiliary contacts or a contactor/relay with one more set of contacts than are needed to energize the motor? The contactor/relay would need to be double throw or have normally closed aux contacts. - Scotty

The type in the link I posted also has coil interlocking capability and auxiliary contacts for sensing by the controlling circuit. Reversing contactors

I'm going to guess alternating forward and reverse:

  if (currentMillis - motorMillisFWD >= motorOnTimeFWD)

{
    motorMillisFWD = currentMillis;
    // Time for  change!
    if (motorStateFWD) { // Motor is in forward
      // Switching to REVERSE
        digitalWrite(motorPinFWD, HIGH);  // HIGH before LOW to prevent a short circuit
        digitalWrite(motorPinREV, LOW);
        motorStateFWD = false;
    } else { // Motor is in reverse
      // Switching to FORWARD
        digitalWrite(motorPinREV, HIGH);  // HIGH before LOW to prevent a short circuit
        digitalWrite(motorPinFWD LOW);
        motorStateFWD = true;
    }
}  // end timer




WARNING: Put an external pull-up resistor on the motor relay output pins so they power up DEACTIVATED. The processor resets to all pins input so the pins will be floating. Having both float LOW will turn both relays on and cause a short circuit.

WARNING: Write HIGH to the motor relay pins BEFORE setting them to OUTPUT. Having both drive LOW will turn both relays on and cause a short circuit.

Yup, I need to alternate between CW and CCW. I could get it to alternate using the code you wrote me, thanks a lot for that. But there is a small problem, when the CW cycle ends, the code turns off the CW relay and INSTANTLY turns on the CCW relay. I need a 5 seconds delay to make sure the motor inertia is nulled or the gearbox will grind itself out.

You neither mentioned that requirement nor had anything like that in your attempted sketch.

To do what you want you will need to keep more state information. I recommend a byte variable to contain a value of 0, 1, 2, or 3. You will also need an unsigned long variable in which to keep the time interval since it is sometimes 30 seconds and sometimes 5 seconds.

Start with state = 0, interval = 30000. Start the motor forward and record the start time.

In the loop(), check to see if the interval is done. If so, based on the current state, move to the next state.

If the state is 0, change it to 1, stop the motor, set the interval to 5000, and record the start time.
else
If the state is 1, change it to 2, start the motor in reverse, set the interval to 30000, and record the start time.
else
If the state is 2, change it to 3, stop the motor, set the interval to 5000, and record the start time.
else
If the state is 3, change it to 0, start the motor forward, set the interval to 30000, and record the start time.

The cycle then repeats.

Instead of the if/else chain you can use the switch/case statement.