Using Millis instead of delays

i am building a fully automated terrarium, The sketch will be added to later but the main meat and potatoes is the heating and cooling. I am wondering how to use the Millis function to keep my sensors reading but not have my heater turn on and off rapidly when it get right at the threshold. There are 2 fans in place of the real fan and heater for testing purposes. The large fan is the (Fan), small fan is the (Heater).

This is my first real build and i have only had my arduino a week so please, newbie terms here would be helpful.

/*This is my automated Eviroment Sketch
 * It has a heater & Fan attached to a 2 relay board Powered by the 5V on the Arduino (for now)
 * Eventually there will be a Ultrasonic Atomizer to adjust the humidity Up
 * Along with a 1602 LCD display connected via I2C
 * The DHT21 was used to get the values
  */
#include "DHT.h" //The origonal File found in the DHT Sensors Library

#define DHTPIN 2 // DHT connected to Pin 2

#define DHTTYPE DHT21 

DHT dht(DHTPIN, DHTTYPE);

// These constants won't change:
const int heaterPin = 10;       // pin that the Heater is attached to
const int fanPin = 12;          // Pin that Fan is attached to

void setup() {
  // initialize the Heater & Fan pins as an output:
  pinMode(heaterPin, OUTPUT);
  pinMode(fanPin, OUTPUT);
  // initialize serial communications:
  Serial.begin(9600);
  dht.begin();
  delay(5000);  // to allow relays to cycle, or they stick ON
}

void loop() {

  // Wait a few seconds between measurements with the DHT
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);
  /* DELETED CODE, Removed Celcius From Tempature Serial Print
   *  Removed Heat index from Serial Print
   */
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: ");
  Serial.print(f);
  Serial.print(" *F\t");
  Serial.println();
  
  // if the Tempature value (f) is High enough, turn on the Fan :
  if (f > 85) {
    digitalWrite(fanPin, LOW);//Backwards to Energize the Relay
    delay(30000);
  }
  else {
    digitalWrite(fanPin, HIGH); //Backwards to De-energize the Relay
  }
    // if the Tempature value (f) is Low enough, turn on the Heater :
  if (f < 64) {
    digitalWrite(heaterPin, LOW); //Backwards to Energize the Relay
    delay(15000);   
  }
  else {
    digitalWrite(heaterPin, HIGH); //Backwards to De-energize the Relay
  }
}

A+ for detail on your post!

Although, use code tags for code, not quote tags.

When you get to the threshold and it changes states, then you have 2 choices.
1)Create a minimum delay before allowing it to change stages again. So if it changes states < 1 minute ago, it cant turn back off or on again.
2)Create a difference threshold so once it clicks on at lets say 80F, it must hit 75F before it can turn back off. So a difference threshold of 5F.

And instead of using delays, use millis() for timing. You can find a great example of how to do this in the BlinkWithoutDelay example

Thanks, how would I add a minimum delay, or create a threshold difference?

I like the threshold difference because it inherently allows me to keep receiving values from the DHT while it is adjusting the environment.

Google "hysteresis"

So, for hysteresis, you need to add information to your “if” statements about the current state of the fan or heater. The current state affects your threshold value (i.e. the threshold is one value on the way up, and a different value on the way down).

So, you need to add a boolean to store the current state of the fan, and one for the heater.

And in your case so far, delay() seems to be fine. Using millis() makes the code more complex, and is only necessary when you want to do more than one thing at a time, or you don’t want to stop the whole program while waiting (although I can see no point to the delay at all in your sketch anymore. Just take the delays out entirely now you have the threshold hysteresis).

Something like this should work (untested) or at least, demonstrate the idea.

boolean isFanOn = false;
boolean isHeaterOn = false;

void loop ()
{
  ...
  // if the Temperature value (f) is High enough, turn on the Fan :
  if (isFanOn == false) {
    if (f > 85) {
      digitalWrite(fanPin, LOW); // Turn fan on. Backwards to Energize the Relay
      isFanOn = true; // store fan state
      //delay(30000);
    }
  } else if (f < 80) {
    digitalWrite(fanPin, HIGH); // Turn fan off. Backwards to De-energize the Relay
    isFanOn = false; // store fan state
  }

  // if the Temperature value (f) is Low enough, turn on the Heater :
  if (isHeaterOn == false) {
    if (f < 64) {
      digitalWrite(heaterPin, LOW); // Turn heater on. Backwards to Energize the Relay
      isHeaterOn = true; // store heater state
      //delay(15000);
      }
  } else if (f > 70) {
    digitalWrite(heaterPin, HIGH); // Turn heater off. Backwards to De-energize the Relay
    isHeaterOn = false; // store heater state
  }
  ...
}

A pretty standard use of hysteresis is in things like home central heating. Say you have your set point (desired temperature) at 20 °C, the heater will actually overshoot to (say) 20.5 °C, and then turn off. Then it doesn't turn on again until it falls below 19.5 °C. That way it isn't "twitching" and turning on and off every few seconds, because of slight errors in the temperature reading.

Also, what I think my heater does, is pause every now and then. Say for example it is a cold morning, and it starts out at 10 °C. I heats up until about 18 °C and then switches off. I think it is waiting to see if the heat already in the system carries it up to 20 °C. If, after 5 or so minutes it is still too low, it turns on again.

The demo several things at a time illustrates how to use millis() to manage timing. It is an extended demo of the BWoD technique.

...R