Code to control 2 fans with timers

I am trying to write a code that will turn on one fan1 for an hour and then turn it off. Then at the same time fan1 is turning off fan 2 comes on for an hour. I want to have fan1 and fan2 do that when the temperature goes above 85 degrees F. Once it is below 85 degrees the fans stay off.

Each fan is connected to a relay and they are 12v dc.
relayFan1 = 28
relayFan2 = 30

Thanks for the help in advance.

The Code I have been working with will be on the following 3 posts.

CODE PART 1

/*
 *** A SPECIAL THANKS TO THE FOLLOWING WHO HAVE WROTE A CODE THAT HAS BENEFITTED MY PROGRAM ***
 * -  DAVID NAVES (http://davenaves.com) MAJOR CONTRIBUTOR

* //D
*/



//libraries
#include <DHT.h>                              // load library for temperature and humidity
#include <LiquidCrystal_I2C.h>                // load library for 4x20 I2C lcd display
#include <Wire.h>                             // load library for 4x20 I2C lcd display
#include <OneWire.h>                          // load the onewire library for thermometer
// #include <Servo.h>                            // load the servo library



// print debug messages or not to serial
const boolean SerialDisplay = true;



// pins assignments
const int photocellPin = A0;                   // photocell connected to analog 0
const int relayFan1 = 28;                      // heat lamp relay set to digital pin 28
const int relayFan2 = 30;                       // exhaust fan relay set to digital pin 30
const int enableCoopDoorMotorB = 2;            // enable motor b - pin 2
const int directionCloseCoopDoorMotorB = 31;   // direction close motor b - pin 31
const int directionOpenCoopDoorMotorB = 32;    // direction open motor b - pin 32
const int bottomSwitchPin = 33;                // bottom switch is connected to pin 33
const int topSwitchPin = 34;                   // top switch is connected to pin 34
const int coopDoorOpenLed = 35;                // led set to digital pin 35
const int coopDoorClosedLed = 36;              // led set to digital pin 36
// const int relayElectricFence = **;          // heat lamp relay set to digital pin 43
const int relayInteriorLight = 37;             // interior lights relay set to digital pin 37
const int enableCoopWindowMotorL = 3;          // enable left window motor - pin 3
const int directionCloseCoopWindowMotorL = 38; // direction close motor  - pin 38
const int directionOpenCoopWindowMotorL = 39;  // direction open motor  - pin 39
const int enableCoopWindowMotorR = 4;          // enable left window motor - pin 4
const int directionCloseCoopWindowMotorR = 40; // direction close motor  - pin 40
const int directionOpenCoopWindowMotorR = 41;  // direction open motor  - pin 41



// temp and humidity assignments
#define DHTPIN1 22  
#define DHTTYPE1 DHT11 
DHT ControlBox(DHTPIN1, DHTTYPE1);

#define DHTPIN1 24  
#define DHTTYPE1 DHT11 
DHT Coop(DHTPIN1, DHTTYPE1);

#define DHTPIN1 26  
#define DHTTYPE1 DHT11 
DHT Run(DHTPIN1, DHTTYPE1);



// variables



// temp and humidity readings
  float Humidity2 = Coop.readHumidity();              // checks humidity level
  float Temp2 = Coop.readTemperature();               // create temperature variable
  float CoopTemp = (1.8 * Temp2 + 32);                // convert celcius to fahrenheit


  
// photocell
int photocellReading;                            // analog reading of the photocel
int photocellReadingLevel;                       // photocel reading levels (dark, twilight, light)


// reed switches top and bottom of coop door

// top switch
int topSwitchPinVal;                   // top switch var for reading the pin status
int topSwitchPinVal2;                  // top switch var for reading the pin delay/debounce status
int topSwitchState;                    // top switch var for to hold the switch state

// bottom switch
int bottomSwitchPinVal;                // bottom switch var for reading the pin status
int bottomSwitchPinVal2;               // bottom switch var for reading the pin delay/debounce status
int bottomSwitchState;                 // bottom switch var for to hold the switch state



// SimpleTimer objects
// SimpleTimer coopPhotoCellTimer;



// photocell reading delay
unsigned long lastPhotocellReadingTime = 0;
unsigned long photocellReadingDelay = 600000;   // 10 minutes



// debounce delay
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 100;



// temperature check delay    ***KEEP***
unsigned long lastTempCheckTime = 0;
unsigned long TempCheckDelay = 600000;           // 10 minutes



// interior lights twighlight delay
unsigned long lastTwilightTime = 0;
unsigned long TwilightDelay = 300000;            // 5 minutes



// coop door led error (blinks)
unsigned long lastCoopDoorLedErrorTime = 0;     // millis() returns an unsigned long.
unsigned long coopDoorLedErrorDelay = 500;      // the time we need to wait



// chicken cam servo
// Servo chickenCamServo;              //  servo object to control chickenCam
// int chickenCamServoPos = 0;         // chickenCamServoPosition var



// lcd
LiquidCrystal_I2C lcd(0x27,20,4); 



// ************************************** the setup **************************************

void setup(void) {

  Serial.begin(9600); // initialize serial port hardware

    lcd.init(); 
    lcd.backlight();
    lcd.setCursor(6, 0);
    lcd.print("THE COOP");

 ControlBox.begin();
 Coop.begin();
 Run.begin();


  // welcome message
  if (SerialDisplay) {
    Serial.println(" Processes running:");
    Serial.println(" Timer doReadPhotoCell every 10 minutes - light levels: open or close door");
  }
  // coop hvac

  pinMode(relayFan1, OUTPUT);   //set heat lamp relay output
  pinMode(relayFan2, OUTPUT);    //set exhaust fan relay output

  // coop door

  // coop door motor
  pinMode (enableCoopDoorMotorB, OUTPUT);           // enable motor pin = output
  pinMode (directionCloseCoopDoorMotorB, OUTPUT);   // motor close direction pin = output
  pinMode (directionOpenCoopDoorMotorB, OUTPUT);    // motor open direction pin = output

  // coop door leds
  pinMode (coopDoorOpenLed, OUTPUT);                // enable coopDoorOpenLed = output
  pinMode (coopDoorClosedLed, OUTPUT);              // enable coopDoorClosedLed = output
  digitalWrite(coopDoorClosedLed, LOW);

  // coop door switches
  // bottom switch
  pinMode(bottomSwitchPin, INPUT);                  // set bottom switch pin as input
  digitalWrite(bottomSwitchPin, HIGH);              // activate bottom switch resistor

  // top switch
  pinMode(topSwitchPin, INPUT);                     // set top switch pin as input
  digitalWrite(topSwitchPin, HIGH);                 // activate top switch resistor

  // interior lights relay
  pinMode(relayInteriorLight, OUTPUT);
  digitalWrite(relayInteriorLight, HIGH);

  // electric fence relay
  // pinMode(relayElectricFence, OUTPUT);                   // set electric fence relay as output

  // timed actions setup
  // coopPhotoCellTimer.setInterval(600000, readPhotoCell);   // read the photocell every 10 minutes



  // servo for interior chicken web cam
  //  chickenCamServo.attach(11);                          // chickenCamServo on pin 11



}

CODE PART 2

// ************************************** functions **************************************



// if hot, turn on cooling fans

void doCoopHVACCool() {

  float Humidity2 = Coop.readHumidity();              // checks humidity level
  float Temp2 = Coop.readTemperature();               // create temperature variable
  float CoopTemp = (1.8 * Temp2 + 32);                // convert celcius to fahrenheit


  if ((unsigned long)(millis() - lastTempCheckTime) > TempCheckDelay) {    // check temperature every 10 minutes
    lastTempCheckTime = millis();

    if (CoopTemp >= 85) {                                      // if temp rises above 85F turn on cooling fan(s) relay
      digitalWrite(relayFan1, HIGH);
    }

    else if (CoopTemp < 85) {
      digitalWrite(relayFan1, LOW);
    }
    if (SerialDisplay) {
      Serial.print(" Coop Temperature:");             // print out coop temperature
      Serial.println(CoopTemp);                          // print out the temperature
      Serial.println(" Coop Fan is on");           // print out Coop Exhaust is on
    }
  }
}



// operate the coop door

// photocel to read levels of exterior light

void doReadPhotoCell() { // function to be called repeatedly - per coopPhotoCellTimer set in setup

  photocellReading = analogRead(photocellPin);

  if ((unsigned long)(millis() - lastPhotocellReadingTime) >= photocellReadingDelay) {
    lastPhotocellReadingTime = millis();

    //  set photocel threshholds
    if (photocellReading >= 0 && photocellReading <= 3) {
      photocellReadingLevel = '1';

      if (SerialDisplay) {
        Serial.println(" Photocel Reading Level:");
        Serial.println(" - Dark");
      }
    }
    else if (photocellReading  >= 4 && photocellReading <= 120) {
      photocellReadingLevel = '2';
      if (SerialDisplay) {
        Serial.println(" Photocel Reading Level:");
        Serial.println(" - Twilight");
      }
    }
    else if (photocellReading  >= 125 ) {
      photocellReadingLevel = '3';
      if (SerialDisplay) {
        Serial.println(" Photocel Reading Level:");
        Serial.println(" - Light");
      }
    }
    if (SerialDisplay) {
      Serial.println(" Photocel Analog Reading = ");
      Serial.println(photocellReading);
    }
  }
}

//debounce bottom reed switch

void debounceBottomReedSwitch() {

  //debounce bottom reed switch
  bottomSwitchPinVal = digitalRead(bottomSwitchPin);       // read input value and store it in val

  if ((unsigned long)(millis() - lastDebounceTime) > debounceDelay) {    // delay 10ms for consistent readings

    bottomSwitchPinVal2 = digitalRead(bottomSwitchPin);    // read input value again to check or bounce

    if (bottomSwitchPinVal == bottomSwitchPinVal2) {       // make sure we have 2 consistant readings
      if (bottomSwitchPinVal != bottomSwitchState) {       // the switch state has changed!
        bottomSwitchState = bottomSwitchPinVal;
      }
      if (SerialDisplay) {
        Serial.print (" Bottom Switch Value: ");           // display "Bottom Switch Value:"
        Serial.println(digitalRead(bottomSwitchPin));      // display current value of bottom switch;
      }
    }
  }
}



// debounce top reed switch
void debounceTopReedSwitch() {

  topSwitchPinVal = digitalRead(topSwitchPin);             // read input value and store it in val

  if ((unsigned long)(millis() - lastDebounceTime) > debounceDelay) {     // delay 10ms for consistent readings

    topSwitchPinVal2 = digitalRead(topSwitchPin);          // read input value again to check or bounce

    if (topSwitchPinVal == topSwitchPinVal2) {             // make sure we have 2 consistant readings
      if (topSwitchPinVal != topSwitchState) {             // the button state has changed!
        topSwitchState = topSwitchPinVal;
      }
      if (SerialDisplay) {
        Serial.print (" Top Switch Value: ");              // display "Bottom Switch Value:"
        Serial.println(digitalRead(topSwitchPin));         // display current value of bottom switch;
      }
    }
  }
}


// stop the coop door motor
void stopCoopDoorMotorB() {
  digitalWrite (directionCloseCoopDoorMotorB, LOW);      // turn off motor close direction
  digitalWrite (directionOpenCoopDoorMotorB, LOW);       // turn on motor open direction
  analogWrite (enableCoopDoorMotorB, 0);                 // enable motor, 0 speed
}



// close the coop door motor (motor dir close = clockwise)
void closeCoopDoorMotorB() {
  digitalWrite (directionCloseCoopDoorMotorB, HIGH);     // turn on motor close direction
  digitalWrite (directionOpenCoopDoorMotorB, LOW);       // turn off motor open direction
  analogWrite (enableCoopDoorMotorB, 255);               // enable motor, full speed
  if (bottomSwitchPinVal == 0) {                         // if bottom reed switch circuit is closed
    stopCoopDoorMotorB();
    if (SerialDisplay) {
      Serial.println(" Coop Door Closed - no danger");
    }
  }
}



// open the coop door (motor dir open = counter-clockwise)
void openCoopDoorMotorB() {
  digitalWrite(directionCloseCoopDoorMotorB, LOW);       // turn off motor close direction
  digitalWrite(directionOpenCoopDoorMotorB, HIGH);       // turn on motor open direction
  analogWrite(enableCoopDoorMotorB, 255);                // enable motor, full speed
  if (topSwitchPinVal == 0) {                            // if top reed switch circuit is closed
    stopCoopDoorMotorB();
    if (SerialDisplay) {
      Serial.println(" Coop Door open - danger!");
    }
  }
}



// coop door led error (blinks red)

void docoopDoorLedError() {
  if ((unsigned long)(millis() - lastCoopDoorLedErrorTime) >= coopDoorLedErrorDelay) {
    lastCoopDoorLedErrorTime = millis();
    digitalWrite(coopDoorClosedLed, !digitalRead(coopDoorClosedLed));  // toggle the led on and off
  }
}


//  coop door status: red if open, green if closed, blinking red if stuck

void doCoopDoorLed() {
  if (bottomSwitchPinVal == 0) {                         // if bottom reed switch circuit is closed
    digitalWrite (coopDoorClosedLed, HIGH);              // turns on coopDoorClosedLed (green)
    digitalWrite (coopDoorOpenLed, LOW);                 // turns off coopDoorOpenLed (red)
  }
  else if (topSwitchPinVal == 0) {                       // if top reed switch circuit is closed
    digitalWrite (coopDoorClosedLed, LOW);               // turns off coopDoorClosedLed (green)
    digitalWrite (coopDoorOpenLed, HIGH);                // turns on coopDoorOpenLed (red)
  }
  else if (topSwitchPinVal != 0) {
    if (bottomSwitchPinVal != 0) {                       // if bottom and top reed switch circuits are open
      docoopDoorLedError();                              // blink the coopDoorOpenLed
    }
  }
  else {
    digitalWrite (coopDoorClosedLed, LOW);               // turns off coopDoorClosedLed (green)
    digitalWrite (coopDoorOpenLed, LOW);                 // turns off coopDoorOpenLed (red)
  }
}



//  turn on interior lights at dusk and turn off after door shuts

void doCoopInteriorLightDusk() {

  if ((unsigned long)(millis() - lastTwilightTime) > TwilightDelay) {     // delay 5 mins

    lastTwilightTime = millis();


    doReadPhotoCell();
    bottomSwitchPinVal = digitalRead(bottomSwitchPin);
    if (bottomSwitchPinVal == 1) {                          // if bottom reed switch circuit is open (door is open)
      if (photocellReading  >= 4) {                         // if it's twilight
        if (photocellReading <= 120) {
          digitalWrite (relayInteriorLight, LOW);          // turn on interior light relay
          if (SerialDisplay) {
            Serial.println(" Interior Light: On");
          }
        }
      }
    }
    else if (bottomSwitchPinVal == 0) {                    // if bottom reed switch circuit is closed (door is closed)
      digitalWrite (relayInteriorLight, HIGH);              // turn on interior light relay
      if (SerialDisplay) {
        Serial.println(" Interior Light: Off");
      }
    }
  }
}




}

CODE PART 3

// do the coop door
void doCoopDoor() {
  if (photocellReadingLevel  == '1') {              // if it's dark
    if (photocellReadingLevel != '2') {             // if it's not twilight
      if (photocellReadingLevel != '3') {           // if it's not light
        debounceTopReedSwitch();                    // read and debounce the switches
        debounceBottomReedSwitch();
        closeCoopDoorMotorB();                      // close the door
      }
    }
  }
  if (photocellReadingLevel  == '3') {              // if it's light
    if (photocellReadingLevel != '2') {             // if it's not twilight
      if (photocellReadingLevel != '1') {           // if it's not dark
        debounceTopReedSwitch();                    // read and debounce the switches
        debounceBottomReedSwitch();
        openCoopDoorMotorB();                       // Open the door
      }
    }
  }
}

// chickenCamServo
/*
void doChickenCamServo() {
 for (chickenCamServoPos = 0; chickenCamServoPos < 75; chickenCamServoPos += 1) {   // turns servo 0 to 75 degrees; 1 degree at a time
 chickenCamServo.write(chickenCamServoPos);                                     // read chickenCamServoPosition variable chickenCamServoPos
 }

 for(chickenCamServoPos = 75; chickenCamServoPos>=1; chickenCamServoPos-= 1){      // return from 75 degrees to 0 degrees; 1 degree at a time
 chickenCamServo.write(chickenCamServoPos);                                    // read chickenCamServoPosition variable chickenCamServoPos
 }
 }

 */

//  lcd
void doLcdMsg() {

  float Humidity1 = ControlBox.readHumidity();        // reads humidity level
  float Temp1 = ControlBox.readTemperature();         // reads temperature variable
  float ControlBoxTemp = (1.8 * Temp2 + 32);          // convert celcius to fahrenheit

  float Humidity2 = Coop.readHumidity();              // reads humidity level
  float Temp2 = Coop.readTemperature();               // reads temperature variable
  float CoopTemp = (1.8 * Temp2 + 32);                // convert celcius to fahrenheit

  float Humidity3 = Run.readHumidity();              // reads humidity level
  float Temp3 = Run.readTemperature();               // reads temperature variable
  float RunTemp = (1.8 * Temp2 + 32);                // convert celcius to fahrenheit

//  pinMode(backLight, OUTPUT);            // backlight pin set as output
//  digitalWrite(backLight, HIGH);         // backlight on
//  lcd.begin(16, 2);                      // columns, rows
//  lcd.clear();                           // start with blank screen
//  lcd.setCursor(0, 0);                   // set cursor to column 0, row 0
//  lcd.print("Coop Temp:");               // show "Temp"
//  lcd.print (tempF) ;                    // show temperature of interior coop
//  lcd.print("F");                        // show "F"
//  lcd.setCursor(0, 1);                   // set cursor to column 0, row 1
//  lcd.print("Coop Door:");               // show "Coop Door"

//  if (bottomSwitchPinVal == 0) {         // if coop door bottom switch is closed
//    lcd.print("Closed");                 // display "Closed"
//  }
//  else if (topSwitchPinVal == 0) {     // if coop door bottom switch is open
//    lcd.print("Open");  // display "Open"
//  }
}



// ************************************** the loop **************************************

void loop() {

  doReadPhotoCell();
  doCoopHVACCool();
  //doCoopHVACHeat();
  doCoopDoor();
  // doChickenCamServo();
  doCoopDoorLed();
  doCoopInteriorLightDusk();
  doLcdMsg();

}

I haven't looked through the code completely yet, but that seems like an excessive amount of code for something as easy as a 1 hour timer and to read a temperature sensor.

Added: Read more, I see it is for an automated chicken coop, but it still seems a bit much.

1 Like

What board is that running on?

I think this is pretty straightforward - have a global variable that stores which fan should be used. Then, when your code turns off a fan, have it twiddle the variable.

As an aside, you can save lots of SRAM by wrapping those static strings you're printing with Serial.println() in the F() macro. Without doing that, the string literal wastes space in SRAM, even though it's never going to change and could be in flash.

I am using a mega 2560 R3. I am new at coding and still learning.

I am not sure how to code a global variable but I guess google will be my best friend.

Question:
If it is still hot, why turn of a fan?
Are you trying to save battery power or what?

The fans I am using for the coop are 12vdc fans. With these fans it is recommended to shut the fan off ever 4 hours for an hour so that the motor does not burn up. So to avoid that I have 2 fans that I want to run for an hour and off an hour so that at least one with always be on.

Ok, now I understand why 2 fans.

Maybe, each hour (60 minutes),switch a variable (fanNumber) from 1 to 2.
You have each fan on a different DIO.

Is this a typo? ""pinMode(relayFan1, OUTPUT); //set heat lamp relay output

What arduino are you using (I may have missed that if you already said)?

I am not sure how to do that but seems like that would work if I am understanding it.

Its suppose to be:
pinMode(relayFan1, OUTPUT); //set ceiling fan1 relay output

Arduino Mega 2560 R3

Any help here?
I am still having problems with the generic multitasking concept, so can anyone help with this?
"each hour (60 minutes),switch a variable (fanNumber) from 1 to 2. and then back".

Simple 60 minute timer controlling two fans.

const byte Fan_1 = 1;
const byte Fan_2 = 2;

void setup() {
  // put your setup code here, to run once:
  pinMode(Fan_1, OUTPUT);
  pinMode(Fan_2, OUTPUT);
}

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

  if (millis() - prevTime >= (3600UL * 1000UL))
  {
    static byte Fan = LOW;
    //Toggle the fans
    Fan = !Fan; // 1 = Fan_1, 0 = Fan_2

    // Turn on corresponding fan
    digitalWrite(Fan_1, Fan);
    digitalWrite(Fan_2, !Fan);
    
    //update prevTime
    prevTime += (3600UL * 1000UL);
  }
}

Doesn't check for roll over, but that can be added if needed.

Close, but no cigar..
"
```
*  static unsigned long prevTime = millis();

if (millis() - prevTime >= (60 * 1000UL))
  {*
```
"

Sorry, I Can't see that working.
It may work tho if you move
static unsigned long prevTime = millis();
out of loop() and put it in setup()

Ah I see I made it a minute timer instead of a hour timer. Fixed

  static unsigned long prevTime = millis();

Should this line of code, be moved?

No, it's static. It will assign prevTime the value of millis() only once then ignore it afterwards.

static unsigned long prevTime = millis();
out of loop() and put it in setup()

No because then prevTime is only visible inside setup(), so will its lifespan.

Wait? Am I helping you or TXMEDIC?

I think I follow. I will need to add it to the code and find out. I really do appreciate your time with this.

how does it switch back and forth between the 2 fans?

By the variable "Fan" if it is 1 or HIGH, then Fan_1 is on and Fan_2 is off. If Fan is 0 or LOW, then fan 2 is on and fan 1 is off.