Help with a relay delay

I am working on my first Arduino project and while it generally has been going smoothly I ran into a roadblock I just can't figure out how to solve. Any thoughts or suggestions would be very welcome.

Goal: I would like to turn an exhaust fan on and off in order to keep the humidity and temperature in my shed close to ambient. As designed I am using a Nano-Every to read the temp and humidity from two DHT-11 sensors, one inside and one outside the shed. The existing code then smooths the reading to give a rolling average of the conditions, then finds the delta between the two. If the delta is greater than 10 degrees or 10% RH, it turns on a relay for five minutes.

The issue is that everything is working except the delay on the timer. Yes I can get it to work by just adding a delay, but then because of the way the rolling average is computer it takes a long time for it to finally turn off.

What I am hoping is to find some way to keep the relay on for the five minutes, while the Arduino is still logging the change in humidity and temperature.

 //Global Configuration
      //Sensor
        #include "DHT.h"
         
        #define DHT1PIN 2     //Inside Sensor 1
        #define DHT2PIN 4     //Outside Sensor 2
        
        #define DHT1TYPE DHT11   
        #define DHT2TYPE DHT11   
        
        DHT dht1(DHT1PIN, DHT1TYPE);
        DHT dht2(DHT2PIN, DHT2TYPE);

      //Smoothing
        float TA1 = 10; //nominal start values
        float TA2 = 10;
        float HA1 = 50;
        float HA2 = 50;
        
      //relay
       int relay_pin = 11;

void setup() {
     //Serial
        Serial.begin(9600); 
        Serial.println("DHTxx test!");

     //Sensor
        dht1.begin();
        dht2.begin();
        
      //relay
       pinMode(relay_pin, OUTPUT);
       digitalWrite(relay_pin, HIGH);
}

 
void loop() {
      delay(1000);
    //Sensor
      float h1 = dht1.readHumidity();
      float t1 = dht1.readTemperature();
      float h2 = dht2.readHumidity();
      float t2 = dht2.readTemperature();
     
        
    //Serial print
          if (isnan(t1) || isnan(h1)) {
            Serial.println("Failed to read from DHT #1");
           } else {
             Serial.print("Humidity 1: "); 
             Serial.print(h1);
             Serial.print(" %\t");
             Serial.print("Temperature 1: "); 
             Serial.print(t1);
             Serial.println(" *C");
          }
          if (isnan(t2) || isnan(h2)) {
            Serial.println("Failed to read from DHT #2");
          } else {
            Serial.print("Humidity 2: "); 
            Serial.print(h2);
            Serial.print(" %\t");
            Serial.print("Temperature 2: "); 
            Serial.print(t2);
            Serial.println(" *C");
          }
    
    //Smoothing
      // Sensor 1 inside shed
      // Sensor 2 outside shed
          {
          HA1 = (HA1*.95)+(h1*.05); //Weight of new vs old
          Serial.print("H1 Average:  ");
          Serial.print(HA1);
          Serial.print(" %\t");
          
          TA1 = (TA1*.95)+(t1*.05);
          Serial.print("T1 Average: ");
          Serial.print(TA1);
          Serial.println(" *C");
          
           
          HA2 = (HA2*.95)+(h2*.05);
          Serial.print("H2 Average  ");
          Serial.print(HA2);
          Serial.print(" %\t");
          
          TA2 = (TA2*.95)+(t2*.05);
          Serial.print("T2 Average  ");
          Serial.print(TA2);
          Serial.println(" *C");
          }
          
    
          int Hdelta = (HA1-HA2);
          int Tdelta = (TA1-TA2);
    
          Serial.print("H∆  ");
          Serial.print(Hdelta);
          Serial.println("%\t");
    
          Serial.print("T∆  ");
          Serial.print(Tdelta);
          Serial.println(" *C");
          Serial.println();
    
    //relay control
        {
          if (Hdelta > 10 || Tdelta > 10) {
            digitalWrite(relay_pin, LOW);
            delay(60000);}
          else 
            digitalWrite(relay_pin, HIGH);
          
        }
        }

Non-blocking timing tutorials:
Several things at a time.
Beginner's guide to millis().
Blink without delay().

Don’t use delays is a good rule of thumb. Delays tell your uC to do nothing for a set time. 1 second does not seem much to you but to the uC it is an age. You want to loop through your code as fast as possible to be responsive. The uC can’t check anything while it is stuck in a delay. You want to use millis to create timers and check when the required time has past rather than delays. You have been given a good list of links to research which will get you there.

You need to figure out and program a minimum OFF time, say 15 or 30 minutes. How long does it take for the average to fall back below set point after 5 minutes of fan running?

JCA34F:
You need to figure out and program a minimum OFF time, say 15 or 30 minutes. How long does it take for the average to fall back below set point after 5 minutes of fan running?

Actually what I need is a minimum ON time. I am just trying to keep it from short cycling and burning up the motor. I don't really care if it turns off and then immediately turns back on.

As of now I have no idea how long it will take, I haven't installed the fan yet. I was waiting on getting the controller up and working first.

First thing, you are smoothing against an arbitrary value that is declared at startup, those values should be acquired in setup() before starting loop(). Put your data acquisition code in a function and call it first in setup() then when needed in loop().
Get that done and working, then a millis() minimum on delay for the fan is easy.

As far as I can understand what you are trying to do. I'd approach it something like this..

Granted, I didn't really get how you were doing your math. In this version I just read the raw data into a set of 4 running average "smoothers" and checked for delta H and delta T. Hopefully this can show enough that you can see how I did it. The timing is handled by two timeObj(s), which are basically just egg timers. Set 'em, start 'em, when they go "ding()", their time has expired.

#include "DHT.h"
#include <runningAvg.h>
#include <timeObj.h>

#define RELAY_PIN 11

#define DHT1PIN   2     //Inside Sensor 1
#define DHT2PIN   4     //Outside Sensor 2

#define DHT1TYPE DHT11   
#define DHT2TYPE DHT11   

DHT dht1(DHT1PIN, DHT1TYPE);
DHT dht2(DHT2PIN, DHT2TYPE);

float h1;      // Values for heat and tempature.
float t1;
float h2;
float t2;
float Hdelta;  // The deltas.
float Tdelta;
              
bool        relayState;
timeObj     relayTimer(5*60*1000);  // Its in miliseconds. 1000 ms = a second, 60 seconds = minute 5 minutes..
timeObj     loopTimer(1000);        // I guess you want the loop slowed down?
runningAvg* smoother[4];

void setup(void) {
   
   // Coms up first..
   Serial.begin(9600); 

   // Relay setup and shut off..
   pinMode(RELAY_PIN, OUTPUT);
   digitalWrite(RELAY_PIN, HIGH);
   relayState = false;              // Relay is off.

   // Sensors fired up..
   dht1.begin();
   dht2.begin();
   
   // Set up your running avarage objects.
   for (int i=0;i<4;i++) {
      smoother[i] = new runningAvg(10);  // 10 is the number of samples to average out. Adjust to suit your system.
   }

   // Fire up your loop slowing timer.
   loopTimer.start();
}


// A function that turns the fan on and off.
void switchRelay(bool onOff) {
         
   if (onOff) {                        // If we want the relay on..
      digitalWrite(RELAY_PIN, LOW);    // Fire it up.
      relayTimer.start();              // Start the timer.
   } else {                            // Else, we want it off..
      digitalWrite(RELAY_PIN, HIGH);   // shut it down.
   }
   relayState = onOff;                 // The relay state is now what they asked for.
}


void loop(void) {

   if (loopTimer.ding()) {                               // If the loop timer has expired..
      h1 = smoother[0]->addData(dht1.readHumidity());    // Read huminidy into smoother, save smoothed value.
      t1 = smoother[1]->addData(dht1.readTemperature()); // Read temp into smoother, save smoothed value.
      h2 = smoother[2]->addData(dht2.readHumidity());    // Again
      t2 = smoother[3]->addData(dht2.readTemperature()); // And again..
      Hdelta =  abs(h1 - h2);                            // Calculate delta humidity.
      Tdelta =  abs(t1 - t2);                            // Calculate delta temp.
      
      if (!relayState) {                                 // If the fan's off..
         if (Hdelta > 10 || Tdelta > 10) {               // And we are past our delta..
            switchRelay(true);                           // On with the fan!
         }
      } else if (relayTimer.ding()) {                    // Else, if the fan IS running, and the timer has expired..
         if (Hdelta <= 10 && Tdelta <= 10) {             // And the room has reached ambiant..
            switchRelay(false);                          // Off with the fan!
         }
      }
      loopTimer.start();                                 // Reset your loop timer.
   }
}

You will need to grab LC_baseTools from the library manager to try this.

-jim lee