Humidity controlled fan routine

Hello there,

I am currently trying to build some sort of weather-station with a simple dual relay module attached to it
in order to toggle a fan and a mister independently.

I also managed to add a small 1.8-inch TFT display which shows the current readings from a DHT11 sensor.
The number in red shows the runtime of the Arduino Nano (in millis), mostly for debugging.

Here is what I want it to do: IF the humidity reading exceeds a value of 75%
THEN run the fan for 10 Minutes (close circuit on relay 1)

Note: It is likely that the humidity drops below the 75% threshold very shortly after the fan has been activated.

That is why I need it to run for a set amount of time. It didn't take long to understand that the delay (); - function wasn't the right choice here since I want to monitor the sensor values during ventilation- or misting times as well. I have spent quite some time reading up on the millis(); - function and how to set up a timer-counter but i have trouble understanding on how to implement this into the control logic - part of my code.

#include <SPI.h>
#include "Ucglib.h"
#include <dht.h>

dht DHT;

#define DHT11_PIN 4                                                           // defines Signal Pin for the Sensor on the Nano

Ucglib_ST7735_18x128x160_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8);      // Correct Driver for ST7735 Display + Pin-Layout on the Nano

const int relayPin = 3;                                                       // defines Signal Pin for the Relay

unsigned long previoustime_1 = 1001;                                            // initial value for timestamp is 0; this should get updated during the loop, I guess ... 
const unsigned long fantime = 10000;                                         // constant value for a variable called "fantime" = 10000ms or 10 seconds 


void setup(void)              ///////////////////////////////////SETUP//////////////////////////////////////////////
{
  delay(1000);
  
//Relay Setup

  pinMode(relayPin, OUTPUT);                                                  // sets the mode of the pin to output
  
   
//Display Setup                                                              // rotates the Display into "portrait-mode" and clears it once at the beginning

  ucg.begin(UCG_FONT_MODE_TRANSPARENT);         
  ucg.setRotate180();           
  ucg.undoClipRange();                       
  ucg.clearScreen();                       
                     

//Outer Frame                                                                // this draws all static graphics (Labels, Borders, etc,)

  //ucg.setColor(0, 111, 255);            //draw orange (alternative color) 
  ucg.setColor(255, 255, 255);           //draw white
  ucg.drawLine(0, 0, 125, 0);           //top line     
  ucg.drawLine(0, 18, 125, 18);        //second top line 
  ucg.drawLine(0, 0, 0, 160);         //left colum
  ucg.drawLine(125, 0, 125, 160);    //right colum
  ucg.drawLine(0, 158, 125, 158);   //bottom line
    

//Inner Frame

  ucg.drawLine(65, 18, 65, 65);          // middle colum
  ucg.drawLine(0, 65, 125, 65);         // upper divider
  ucg.drawLine(0, 100, 125, 100);      //lower divider


//Static Text 

  ucg.setFont(ucg_font_profont15_8f); // Device Name & Version
  ucg.setColor(255, 255, 255);
  ucg.setPrintPos(11,13  );
  ucg.print("Greenhouse V0.1");

//Static Text Climate controlers (circut on relay 1(fan) & circut on relay 2(mister) 

  ucg.setFontMode(UCG_FONT_MODE_SOLID);
  ucg.setFont(ucg_font_profont15_8f);
  ucg.setPrintPos(11, 80);
  ucg.print("Fan");
  ucg.setPrintPos(11, 95);
  ucg.print("Mister");
  
}

void loop(void)                             //////////////////LOOP/////////////////////////////////////////////
{

//Runtime on display (for debugging) 
  unsigned long currenttime = millis();
  ucg.setFont(ucg_font_inb16_mf);
  ucg.setPrintPos(10, 135);
  ucg.setColor(0,0, 255);          // draw red
  ucg.print(currenttime);

 
//Sensor check value pin
    int chk = DHT.read11(DHT11_PIN);           // DHT11 Sensor can now be read

//Control Logic
 
 
  if(DHT.humidity  > 75)
    {
      
       digitalWrite(relayPin, LOW);            // ??????????? How do I time this correctly???????????
           
    }
  else
      digitalWrite(relayPin, HIGH);

I have defined a variable to keep track of the time (elapsed millis) and a constant value for the fan runtime (set to 10 sec for debugging).

How do I implement this correctly? Do I need to build it via an While-statement inside of an If-statement?

I cannot wrap my head around this for some reason. Please, someone help me understand :o

Take a look at this tutorial and it should be clear how to use millis() so that you can do something else while waiting for a time to elapse;

Create a Boolean to keep track of whether the fan is running.

In your loop function, if the fan is off, see if the humidity is too high. If so, note the time using millis and set the Boolean variable to indicate that the fan is on (and set the relay so it is).

Similarly, if the fan is running, use millis to see how long it is since you turned on the fan. If it exceeds your interval, turn it off and change your Boolean to indicate that.

Alright,

I have read the "Blinking without Delay()" thing again and I think I have set these Boolean thingies to check whether the fan is running or not.

However, it's still not working. Sometimes I can get the fan to turn on on threshold but then it starts going on and off, which means i am calculating the time to turn off wrong, or nothing at all happens when the threshold is reached.

I have the feeling i know what to do but i don't know how correctly formulate it. :frowning:

//Control Logic
 
 
  if(digitalRead(relayPin) == HIGH && DHT.humidity >=50)           // if fan is not running AND humidity is over 50 THEN turn fan on
    {
      
          digitalWrite(relayPin, LOW);
          unsigned long wettime = millis();
          wettime = previoustime_1;                                // initial time stamp value 0 gets overwritten with current time here
        
        
    }

  if(digitalRead(relayPin) == LOW)                                 // if fan is on 
      {
        if((previoustime_1 - currenttime) > 10000)                 // calculate the timespan between fan-on and current time; compare that to fix value of 10 sec
        {
            digitalWrite(relayPin, HIGH);
            
        }
        else digitalWrite(relayPin, LOW);                          // if timespan lesser than 10 sec keep running 
      }

Where is 'previoustime_1' updated? It's getting confusing with changes and snippets. Please just repost the entire current sketch.

Sorry about that.
Here is the entire code so far:

previoutime_1 gets the value of 0 at the beginning

#include <SPI.h>
#include "Ucglib.h"
#include <dht.h>

dht DHT;

#define DHT11_PIN 4                                                           // defines Signal Pin for the Sensor on the Nano

Ucglib_ST7735_18x128x160_HWSPI ucg(/*cd=*/ 9, /*cs=*/ 10, /*reset=*/ 8);      // Correct Driver for ST7735 Display + Pin-Layout on the Nano

const int relayPin = 3;                                                       // defines Signal Pin for the Relay

unsigned long previoustime_1 = 0;                                            // initial value for timestamp is 0; this should get updated during the loop, I guess ... 
const unsigned long fantime = 10000;                                         // constant value for a variable called "fantime" = 10000ms or 10 seconds 


void setup(void)              ////////////////////////////////////////////////////////////////////////////////////SETUP//////////////////////////////////////////////
{
  delay(1000);
  
//Relay Setup

  pinMode(relayPin, OUTPUT);                                                  // sets the mode of the pin to output
  
   
//Display Setup                                                              // rotates the Display into "portrait-mode" and clears it once at the beginning

  ucg.begin(UCG_FONT_MODE_TRANSPARENT);         
  ucg.setRotate180();           
  ucg.undoClipRange();                       
  ucg.clearScreen();                       
                     

//Outer Frame                                                                // this draws all static graphics (Labels, Borders, etc,)

  //ucg.setColor(0, 111, 255);            //draw orange (alternative color) 
  ucg.setColor(255, 255, 255);           //draw white
  ucg.drawLine(0, 0, 125, 0);           //top line     
  ucg.drawLine(0, 18, 125, 18);        //second top line 
  ucg.drawLine(0, 0, 0, 160);         //left colum
  ucg.drawLine(125, 0, 125, 160);    //right colum
  ucg.drawLine(0, 158, 125, 158);   //bottom line
    

//Inner Frame

  ucg.drawLine(65, 18, 65, 65);          // middle colum
  ucg.drawLine(0, 65, 125, 65);         // upper divider
  ucg.drawLine(0, 100, 125, 100);      //lower divider


//Static Text 

  ucg.setFont(ucg_font_profont15_8f); // Device Name & Version
  ucg.setColor(255, 255, 255);
  ucg.setPrintPos(11,13  );
  ucg.print("Greenhouse V0.1");

//Static Text Climate controlers (circut on relay 1(fan) & circut on relay 2(mister) 

  ucg.setFontMode(UCG_FONT_MODE_SOLID);
  ucg.setFont(ucg_font_profont15_8f);
  ucg.setPrintPos(11, 80);
  ucg.print("Fan");
  ucg.setPrintPos(11, 95);
  ucg.print("Mister");
  
}

void loop(void)           ///////////////////////////////////////////////////////LOOP/////////////////////////////////////////////
{

//Runtime on display (for debugging) 
  unsigned long currenttime = millis();
  ucg.setFont(ucg_font_inb16_mf);
  ucg.setPrintPos(10, 135);
  ucg.setColor(0,0, 255);          // draw red
  ucg.print(currenttime);

 
//Sensor check value pin
    int chk = DHT.read11(DHT11_PIN);           // DHT11 Sensor can now be read

//Control Logic
 
 
  if(digitalRead(relayPin) == HIGH && DHT.humidity >=50)           // if fan is not running AND humidity is over 50 THEN turn fan on
    {
      
          digitalWrite(relayPin, LOW);
          unsigned long wettime = millis();
          wettime = previoustime_1;                                // initial time stamp value 0 gets overwritten with current time here
        
        
    }

  if(digitalRead(relayPin) == LOW)                                 // if fan is on 
      {
        if((previoustime_1 - currenttime) > 10000)                 // calculate the timespan between fan-on and current time; compare that to fix value of 10 sec
        {
            digitalWrite(relayPin, HIGH);
            
        }
        else digitalWrite(relayPin, LOW);                          // if timespan lesser than 10 sec keep running 
      }
    
      
      
      ucg.setFontMode(UCG_FONT_MODE_SOLID);
      ucg.setFont(ucg_font_7x14B_mf);
      ucg.setPrintPos(75, 80);
      ucg.setColor(0, 225, 255);          // draw yellow 
      ucg.print("idle");

      ucg.setFontMode(UCG_FONT_MODE_SOLID);
      ucg.setFont(ucg_font_7x14B_mf);
      ucg.setPrintPos(75, 95);
      ucg.setColor(0, 225, 255);          // draw yellow 
      ucg.print("idle");
     
                                          
//Sensor Values

  ucg.setFontMode(UCG_FONT_MODE_SOLID);     //Values
  ucg.setFont(ucg_font_inb16_mf);
  ucg.setColor(0,255, 208);
  ucg.setPrintPos(15, 48);
  ucg.print(DHT.temperature, 0);
  delay(100);
  ucg.print("");
  
  //ucg.setPrintPos(48, 48);                // Grad Symbol
  //ucg.print((char)223);
  
  ucg.setPrintPos(50, 48);                  // Units 
  ucg.print("C");
  ucg.setPrintPos(80, 48);
  ucg.setColor(221,255, 0);
  ucg.print(DHT.humidity, 0);
  delay(100);
  ucg.print("");
  ucg.setPrintPos(110, 48);
  ucg.print("%");

cpt_underpants:
previoutime_1 gets the value of 0 at the beginning

At the beginning of what? The program? Don't you need to handle it in loop()?

Ihave not worked through your code but the line below in the Contol Logic section looks suspicious, should the assignement be the other way round;

wettime = previoustime_1;                                // initial time stamp value 0 gets overwritten with 
current time here

If your code is not doing what you expect smatter it with print statements to see where the flow is going and what values variables are taking.

In addition to aarg's point, this is flawed:

    if ((previoustime_1 - currenttime) > 10000)                // calculate the timespan between fan-on and current time; compare that to fix value of 10 sec

Even if previous time_1 was ever set to anything, the subtraction is the wrong way round. As it is, you're subtracting the time now from zero.