Humidity sensor controlling pump for x seconds

Hi all,

Been running in circles last few days trying desperately to get this thing to work.

The short story is I need the arduino to check the humidity every 5 minutes and if below a threshold, I need it to run a digital output (to a pump) for say 3 seconds. I then want to recheck after 5 minutes has elapsed to see if the humidity has risen enough or not.

I can get it to work just fine as a constant on/off state (ie, turn on, and if the humidity is higher after 5 minutes turn it off) however that would end up in minor flooding for the intended application.

I cannot use a delay, as the arduino is also running an LCD to show the temp/humidity.

The last lot of code I tried (which obviously doesn't work, also note the short durations are just trying to get it working, prefer to wait 10s than 5 minutes):

unsigned long interval = 10000;
unsigned long previousMillis = 0;



void setup() {
  Serial.begin(9600);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16,2);
  dht.begin();
  pinMode(10, OUTPUT); //output for pump

}

void loop() {
  //humidity pump control section of code follows

unsigned long currentMillis = millis(); //grab current time

if(((currentMillis - previousMillis) >= interval) && (dht.readHumidity() < 80)) {
  digitalWrite(10, HIGH); 
}
else if ((currentMillis - previousMillis) >= (interval - 6000)) {
  digitalWrite(10, LOW);
}


  previousMillis = millis();

I am truly hopeless with this and have tried so many variations of Millis at this point. If you could very clearly point me in the right direction that would be a fantastic help; i'm really struggling with the check every 5 minutes but only run for 3 seconds part.

Regards,
Luke

Worth mentioning something as simple as:

void setup() {
  Serial.begin(9600);
  // set up the LCD's number of columns and rows: 
  lcd.begin(16,2);
  dht.begin();
  pinMode(10, OUTPUT); //output for pump
}



void loop() {
  //humidity pump control section of code follows

if(dht.readHumidity() > 50) {
  digitalWrite(10, HIGH);
  delay(2000);
  digitalWrite(10, LOW);
  delay(30000);
}

Would be perfect except it completely stops my LCD from displaying correctly for the entire duration of the delay (which set here is 30s, but would ideally be at least 2 minutes long).

The program logic needs to be revised completely. You update previousmillis immediately after making the test.

You need separate variables that remember the time at which the pump was turned on and when the measurement was made. Study the "how to do several things at once" example posted elsewhere on the forum.

In timing statements, you should always use unsigned long constants to avoid confusion (e.g. 6000UL).

jremington:
The program logic needs to be revised completely. You update previousmillis immediately after making the test.

You need separate variables that remember the time at which the pump was turned on and when the measurement was made. Study the "how to do several things at once" example posted elsewhere on the forum.

In timing statements, you should always use unsigned long constants to avoid confusion (e.g. 6000UL).

So after going through this (yet again) I think I have come up with something workable. Just needed to walka way for a day and come back to it with a fresh head I think...

#include <Servo.h>
#include "DHT.h" 
#define DHTPIN 2     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);

// LCD
// LCD RS=3, EN=4, DS4=5, DS5=6, DS6=7, DS7=8
#include <LiquidCrystal.h>
LiquidCrystal lcd( 3, 4, 5, 6, 7, 8);

// ----CONSTANTS (won't change)

     // the pin numbers for the LEDs
const int led_A_Pin = 10;
const int led_A_Interval = 15000; // number of millisecs between blinks
const int blinkDuration = 3000; // number of millisecs that Led's are on - all three leds use this

//------- VARIABLES (will change)
           
byte led_A_State = LOW;           //   LOW = off // used to record whether the LEDs are on or off
unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousLed_A_Millis = 0;       // will store last time the LED was updated

//========

void setup() {

 Serial.begin(9600);
 Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running
 
     // set the Led pins as output:
 pinMode(led_A_Pin, OUTPUT);
 lcd.begin(16,2);
 dht.begin();

}

//=======

void loop() {

     // Notice that none of the action happens in loop() apart from reading millis()
     //   it just calls the functions that have the action code

 currentMillis = millis();   // capture the latest value of millis()
                             //   this is equivalent to noting the time from a clock
                             //   use the same time for all LED flashes to keep them synchronized
 

 updateLed_A_State();       // call the functions that do the work
 switchLeds();

 // 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();
  float t = dht.readTemperature();

    // set the cursor to (0,0):
  lcd.setCursor(0, 0);
  // print from 0 to 9:
  
   lcd.print("Temp: ");
   lcd.print(t);
   lcd.print("C");
  // set the cursor to (16,1):
  lcd.setCursor(0,1);
  lcd.print("Humidity: ");
  lcd.print(h);
  lcd.print("%");
    delay(200);

}

//========

void updateLed_A_State() {

 if (led_A_State == LOW) {
         // if the Led is off, we must wait for the interval to expire before turning it on
   if ((currentMillis - previousLed_A_Millis >= led_A_Interval) && (dht.readHumidity() < 70)) {
         // time is up, so change the state to HIGH
      led_A_State = HIGH;
         // and save the time when we made the change
      previousLed_A_Millis += led_A_Interval;
         // NOTE: The previous line could alternatively be
         //              previousOnBoardLedMillis = currentMillis
         //        which is the style used in the BlinkWithoutDelay example sketch
         //        Adding on the interval is a better way to ensure that succesive periods are identical

   }
 }
 else {  // i.e. if onBoardLedState is HIGH
 
         // if the Led is on, we must wait for the duration to expire before turning it off
   if (currentMillis - previousLed_A_Millis >= blinkDuration) {
         // time is up, so change the state to LOW
      led_A_State = LOW;
         // and save the time when we made the change
      previousLed_A_Millis += blinkDuration;
   }
 }
}

//=======





void switchLeds() {
     // this is the code that actually switches the LEDs on and off

 digitalWrite(led_A_Pin, led_A_State);

}

//=======






//=====END

Lets me run a check every 15s and if criteria is met enable the digital output pin (ie the pump) for 3 seconds. Presumably this will translate fine into longer durations? Or will I need to adjust this section to get to the times I need and make them long unsigned or something?

const int led_A_Pin = 10;
const int led_A_Interval = 15000; // number of millisecs between humidity checks
const int blinkDuration = 3000; // number of millisecs that pump is on

FYI: Will need it for every few seconds (so I know blink duration is fine), but the pump interval to be 5 mins (300,000). Will const int topple over for 300,00 or be fine?

Once done will update all the values to something more intuitive than led_A etc.

Using int for time will work up to 32767 milliseconds but causes the compiler to work things out and may be confusing for humans. unsigned long will work for 300000 and longer and causes less confusion.

Updating names NOW will be less confusing.

unsigned long will work for 300000 and longer and causes less confusion.

So simply change:

const int led_A_Interval = 15000; // number of millisecs between humidity checks
const int blinkDuration = 3000; // number of millisecs that pump is on

to...

const unsigned long led_A_Interval = 15000; // number of millisecs between humidity checks
const unsigned long blinkDuration = 3000; // number of millisecs that pump is on

Will do the trick so I can increase duration to 300,000? Currently using in application during test phase so not keen to make adjustment unless it's the correct one.

Appreciate help cheers.

Always use unsigned long variables and constants when working with millis().

jremington wrote:

Always use unsigned long ... constants when working with millis().

unsigned long constants have a suffix of UL, such as 300000UL .

While some compilers may be smart enough to figure this out without the UL, the UL tells the world that this is what you intended.