Problem activating and deactivating a fan using millis function

Hi, I’m trying to do a project with a fan and a DHT22 sensor. I want to activate the fan when the temperature or the humidity overpasses a limit, and to deactivate it when the temperature or the humidity are normal again, but only after 20 seconds of being activated. Here is my code:

#include <DHT.h>;
#define DHTPIN 7
#define DHTTYPE DHT22

const int relefanPin = 8;
unsigned long interval = 20000;
unsigned long startMillis;  
unsigned long currentMillis;

DHT dht(DHTPIN, DHTTYPE);

float hum;  
float temp; 

void setup() {
  Serial.begin(9600);
  dht.begin();
  pinMode(relefanPin, OUTPUT);
  digitalWrite(relefanPin, LOW);
}

void loop() {
  currentMillis = millis();
  hum = dht.readHumidity();
  temp = dht.readTemperature();
  
  if ((temp >= 25) || (hum >= 80))
  {
    digitalWrite(relefanPin, HIGH);
    startMillis = millis();
  }
  else if ((currentMillis - startMillis) <= interval);
  {
    digitalWrite(relefanPin, LOW);
  }

  delay(2000);
}

Thanks

else if ((currentMillis - startMillis) <= interval);

Should be

else if ((currentMillis - startMillis) >= interval);

It doesn’t work either

When you say it doesn’t work, what isn’t happening? Is the fan staying on or off?

BTW, your setting currentMillis to millis() at the start of each loop is redundant, you can simply test millis().

evanmars is correct.

Also,

The code says to turn off the fan 20 seconds after both the temp and humidity are back within desired limits, not as you say “after 20 seconds of being activated”. To set the time relative to first activation, you need to save the millis of the first time it is true and goes through the

if ((temp >= 25) || (hum >= 80))
{
digitalWrite(relefanPin, HIGH);
startMillis = millis(); // <= this needs to be the “activation time”
}

I think Dale, that the logical suggestion of the translation or OPs problem, is that the timer should initiate it's 20 second countdown once the readings have returned to normal, thereby shutting the fan off after this condition is met. That being the case, the code as is is valid as startMillis would cease being updated once the test fails.

You are correct in stating that evanmars' post should be followed in changing the else if test to >=, this is why I've asked for clarification on which state is persisting. With the change, the code should work. Why it doesn't may not be a problem with the code but the sensor or the sensor readings. Difficult to tell without knowing what those readings are.

I’ve done what you have suggested me and now the fan activates when the temperature is over the limit but not when the humidity is. Also the condition with the millis is not working because the fan reactivates before the 20 seconds. Here is what the code looks like now:

#include <DHT.h>;
#define DHTPIN 7
#define DHTTYPE DHT22

const int relefanPin = 8;
unsigned long interval = 20000;
unsigned long startMillis;  
unsigned long currentMillis;

DHT dht(DHTPIN, DHTTYPE);

float hum;  
float temp; 

void setup()
{
  Serial.begin(9600);
  dht.begin();
  pinMode(relefanPin, OUTPUT);
  digitalWrite(relefanPin, LOW);
}

void loop()
{  
  hum = dht.readHumidity();
  temp = dht.readTemperature();
    
  if ((temp >= 31) || (hum >= 80) && (millis() - startMillis >= interval))
  {
    digitalWrite(relefanPin, HIGH);
  }
  else
  {
    digitalWrite(relefanPin, LOW);
    startMillis = millis();
  }
}
unsigned long startMillis;

This variable is obviously intended to hold the time that some event occurred. There is NO clue what the event is, though. You REALLY need a better name.

unsigned long currentMillis;

This should NOT be a global variable.

float hum; 
float temp;

There is no reason for these to be global, either.

  if ((temp >= 31) || (hum >= 80) && (millis() - startMillis >= interval))

Using parentheses is a good idea, since your concept of the operator precedence may not be the same as the compilers. But, it still isn't clear what you are trying to do here.

if((too hot or too humid) and (it's time to do something)) ? or if((too hot) or (too humid and it's time to do something))?

Which one did you mean? Which one is the compiler seeing? Where should you add more parentheses so that the compiler does what you meant?

Which name do you suggest me to put? What do you mean when you say that the variable shouldn’t be global, do I have to write it inside the void loop? What I meant was if (too hot or too humid) and (time to do something). But what I think it’s wrong is the syntax of the millis and startMillis, because the fan activates but not when it should.

What I meant was if (too hot or too humid) and (time to do something).

Don't tell me. Tell the compiler, by putting the parentheses in the proper places.

  if ((temp >= 31 || hum >= 80) && (millis() - startMillis >= interval))

Even better, don't use a compound if statement.

  if (temp >= 31 || hum >= 80)
  {
     // It's too hot or too humid
     if (millis() - startMillis >= interval)
     {
        // It's time to do something
     }
  }

By writing the code this way, you can see that you are not going to be able to run the fan for 20 seconds after the temperature and humidity drops to acceptable levels.

You need to set the time it got too hot or too humid, when you turn the fan on (or when you decide that the fan needs to be on).

That last statement should give you a clue what the event is that you are recording the time of, which should suggest a better name than startMillis. Perhaps whenItGotTooHotOrHumid.

Long names ARE good, if that it what it takes to convey meaning. Notice that millis does NOT have to be part of the name. Whether the value is from millis(), micros(), or an RTC is irrelevant.

Actually, you need to record when it is no longer too hot and/or too humid, so you know when to turn the fan off.

To determine if it is time to turn the fan off, it doesn't matter if the fan is on, or not.

if(noLongerTooHotOrHumid > 0 && millis() - noLongerTooHotOrHumid >= coolDownTime)
{
   // The fan no longer needs to be on. Turn it off.

   noLongerTooHotOrHumid = 0;
}

I don’t understand what you are telling me in the last part. I don’t know if you have understood me correctly but what I want the fan to do is wait 20 seconds after being deactivated even if the temperature is over the limit. This is necessary because without that the fan is going to be constantly turning on and off in some cases in which the temperature is going over and under the limit all the time. Sorry if you had understood me correctly but I didn’t totally understand what you told me in the last post.

Your code doesn't work decause you have a if that turns on (and else that turns off) that controll like this: A=temoeratur >limit B=humidity >limit C=timer millis passed The if controlls (a OR b AND c). In Arduino this is like if (A) I work if (NOT a but b AND c) I work the same

What you want is a if (a AND c) I work if (b AND c) i work

The translation can be OR if (a AND c OR b AND c)

OR if ((a OR b) AND c)

Do you understand?

Okay thanks I’ll try that