interval in loop, countdown timer in function using millis

I have built an inline humidifier and now it needs to be controlled :slight_smile:
The humidifier has a HDC1080 Rh sensor built in to measure the humidity and a levelswitch to protect against flooding in case the drain blockes.
I'm having difficulties to program the timing part while trying to avoid using delays and keeping the code compact.
Here's what is suppose to happen:

Every 60 seconds function bevochtigerAan is triggered. That function has to meet three conditions to execute.
-check Rh sensor value against a threshold value,
-check levelswitch to see if systeem is not flooding.
-if no more than 2 seconds have passed (keep waterrelay ON for 2 seconds)
If any is/are false, exit function, go back to mainloop and wait another 60 sec's before starting again.

So, I need an interval in the main loop which triggers a function. Inside the function there's a timer.
Somewhere down the line I get lost...

#include <Wire.h>
#include "ClosedCube_HDC1080.h"
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 4);
ClosedCube_HDC1080 hdc1080;

byte tresholdRv = 81;
const int relais01 = 53;
const int levelSensorRh = 47;
int bevochtigerLevelRh;
float readHumidity;
float readTemperature;
unsigned long intervalRh = 60000; // interval
unsigned long durationRh = 2000; // duration water on
unsigned long previousMillisRh = 0;


void setup() {
  pinMode(relais01, OUTPUT);
  digitalWrite(relais01, HIGH);
  pinMode (levelSensorRh, INPUT_PULLUP);
  lcd.init();
  lcd.backlight();
  hdc1080.begin(0x40);

  lcd.setCursor(0, 2);
  lcd.print("Treshold ");
  lcd.print(tresholdRv);
  lcd.print("%");
}

void loop() {
  unsigned long currentMillisRh = millis(); // grab current time
  if ((unsigned long)(currentMillisRh - previousMillisRh) >= intervalRh) { //have 60 seconds passed?
    bevochtigerAan;
  }

  lcd.setCursor(0, 0);
  lcd.print("T=");
  lcd.setCursor(3, 0);
  lcd.print(readTemperature);
  lcd.setCursor(7, 0);
  lcd.print((char)223);
  lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print("Rv=");
  lcd.setCursor(3, 1);
  lcd.print(readHumidity);
  lcd.print("%");
}

void bevochtigerAan() {
    readHumidity = hdc1080.readHumidity();
    bevochtigerLevelRh = digitalRead(levelSensorRh);
    unsigned long currentMillisRh = millis();
  if ((readHumidity < tresholdRv) && (bevochtigerLevelRh == LOW) && (currentMillisRh - previousMillisRh <= durationRh)){ //check three conditions
    digitalWrite(relais01, LOW); //switch ON relay
  lcd.setCursor(0, 3);
  lcd.print("water AAN");
  }
  else {
    digitalWrite(relais01, HIGH); //switch OFF relay
  lcd.setCursor(0, 3);
  lcd.print("water UIT");
  previousMillisRh = millis();
  }
}

Hi RogMoe,

it would help a lot of you describe what behavoiur you are observating when you run this code-version

best regards Stefan

So, I need an interval in the main loop which triggers a function.

Are you familiar with the using millis for timing tutorial? Don't put the timer in loop, put it at the top of the function so it's the first thing that's checked. So, in loop your function is called, then the function checks to see if the time has elapsed and returns if not, or does its thing if it's time. Look in my tutorial using Nextion displays with Arduino, there's some code in there that updates a clock every second. Use that as a template for getting a longer time. I'm using a mobile phone to post this, otherwise I'd post some sample code here.

One issue is this in loop:

bevochtigerAan;

That doesn't call your function, should be:

bevochtigerAan();

If your code does not work add debug-output to analyse what is going on

here is a version that does a lot of debug-output to the serial monitor

I commented out the LCD, humidity sensor stuff to make it run without the additional hardware

The serial output has a system a numbe for exact identifying which line of code the name of the function it is in

/*
#include <Wire.h>
#include "ClosedCube_HDC1080.h"
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 4);
ClosedCube_HDC1080 hdc1080;
*/

byte tresholdRv = 81;
const int relais01 = 53;
const int levelSensorRh = 47;
int bevochtigerLevelRh;
float readHumidity;
float readTemperature;
unsigned long intervalRh = 10000; // interval original 60000
unsigned long durationRh = 2000; // duration water on
unsigned long previousMillisRh = 0;


void setup() {
  Serial.begin(115200);
  Serial.println("Setup Start");
  pinMode(relais01, OUTPUT);
  digitalWrite(relais01, HIGH);
  pinMode (levelSensorRh, INPUT_PULLUP);
/*
  lcd.init();
  lcd.backlight();
  hdc1080.begin(0x40);

  lcd.setCursor(0, 2);
  lcd.print("Treshold ");
  lcd.print(tresholdRv);
  lcd.print("%");
*/  
}

void loop() {
  delay(500); // slow down serial output
  unsigned long currentMillisRh = millis(); // grab current time
  Serial.print("1 loop currentMillisRh = millis(); ");    
  Serial.println(currentMillisRh);
  
  if ((unsigned long)(currentMillisRh - previousMillisRh) >= intervalRh) { //have 60 seconds passed?
    Serial.print(currentMillisRh);
    Serial.print( " - ");
    Serial.print(previousMillisRh);
    Serial.print( " >= ");
    Serial.println(intervalRh);
    /*
    previousMillisRh = currentMillisRh;
    Serial.print( "2 loop updateting previousMillisRh=");
    Serial.println(previousMillisRh);
    */ 
    Serial.println(" 3 loop right before entering bevochtigerAan;");    
    //bevochtigerAan; // !!! ALWAYS add parenthesis "()" behind the functions name!!!
    bevochtigerAan();
    Serial.print("4 loop below bevochtigerAan; currentMillisRh:=");    
    Serial.println(currentMillisRh);
  }
  /*
  lcd.setCursor(0, 0);
  lcd.print("T=");
  lcd.setCursor(3, 0);
  lcd.print(readTemperature);
  lcd.setCursor(7, 0);
  lcd.print((char)223);
  lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print("Rv=");
  lcd.setCursor(3, 1);
  lcd.print(readHumidity);
  lcd.print("%");
  */  
}

void bevochtigerAan() {
    Serial.println("1 bevoch() entered");    

    readHumidity = 60;//hdc1080.readHumidity();
    bevochtigerLevelRh = LOW;//digitalRead(levelSensorRh);
    unsigned long currentMillisRh = millis();
    Serial.print("currentMillisRh = millis()=  ");    
    Serial.print(currentMillisRh);
    
    Serial.print("  readHumidity=");    
    Serial.print(readHumidity);
    Serial.print("  tresholdRv=");     
    Serial.print(tresholdRv);     
    
    if (bevochtigerLevelRh == HIGH) {
      Serial.print("  2 bevoch() bevochtigerLevelRh: HIGH");     
    }
    else {
      Serial.println("  2 bevoch() bevochtigerLevelRh: LOW");     
    }
    
    Serial.println("3 bevoch()  (currentMillisRh - previousMillisRh ");     
    Serial.print  ("4 bevoch()   ");     
    Serial.print(currentMillisRh);
    Serial.print(" - "); 
    Serial.println(previousMillisRh);     
    Serial.print ("5 bevoch() result=");  
    Serial.println(currentMillisRh - previousMillisRh);     

    if ( (currentMillisRh - previousMillisRh)  <= (durationRh)  ) { 
      digitalWrite(relais01, LOW); //switch ON relay
      Serial.print("6 bevoch() if is TRUE switch relay ON");    
      /*    
      lcd.setCursor(0, 3);
      lcd.print("water AAN");
      */  
    }
    else {
      Serial.println("7 bevoch() if is false switch relay OFF ");    
      digitalWrite(relais01, HIGH); //switch OFF relay
      /*
      lcd.setCursor(0, 3);
      lcd.print("water UIT");
      */
      previousMillisRh = millis();
      Serial.print(" 8 bevoch()previousMillisRh = millis();");    
      Serial.print(" 8 bevoch() previousMillisRh=");    
      Serial.println(previousMillisRh);
    }
    Serial.println("9 bevoch() leaving bevochtigerAan()");
    Serial.println();
}

If you do a thoroughly analyse of the serial output you will find the logical error
To make it work with your hardware just remove the blockcommenting and the delay(500)
and set time back to 60000

best regards Stefan