Bathroom fan control

This is my implementation of a Arduino Pro Mini as a bathroom fan control unit. It senses humidity and IR to turn on and off the fan with a relay shield. Everything packed up in a IP67 case. It works verry well. However; i'm not sure what is going to happen with my dependency on millis when it rolls over.


[/url]

#include <dht.h>

#define dht_dpin A0 //no ; here. Set equal to channel sensor is on
#define RELAY1 3     
#define HUMIDITYTREASHOLD 55     


float Counter;
long previousMillis = 0;        // will store last time LED was updated

const int ledPin =  13;      // the number of the LED pin
int ledState = LOW;             // ledState used to set the LED
long previousMillisLed = 0;        // will store last time LED was updated
long interval = 300;   

dht DHT;

void setup(){
  pinMode(ledPin, OUTPUT);
  pinMode(PIR_Sensor_Pin, INPUT);     // declare sensor as input
  pinMode(RELAY1, OUTPUT);  
  
  Serial.begin(9600);
    
  digitalWrite(ledPin, HIGH);
  delay(200);
    digitalWrite(ledPin, LOW);
  delay(200);
    digitalWrite(ledPin, HIGH);
  delay(200);
    digitalWrite(ledPin, LOW);
  delay(200);
    digitalWrite(ledPin, HIGH);
  delay(200);
    digitalWrite(ledPin, LOW);
  delay(200);
  
  digitalWrite(RELAY1,HIGH);          // Turns Relay Off
  delay(1000);
    digitalWrite(RELAY1,LOW);          // Turns Relay Off
  delay(1000);
    digitalWrite(RELAY1,HIGH);          // Turns Relay Off
  delay(1000);
    digitalWrite(RELAY1,LOW);          // Turns Relay Off
  delay(1000);
    digitalWrite(RELAY1,HIGH);          // Turns Relay Off
  delay(1000);
  
  Serial.println("Start loggingn\n");
}

void loop(){

  if(millis() - previousMillis > 1000) {
    previousMillis = millis(); 
    DHT.read11(dht_dpin);
    Serial.print("Current humidity = ");
    Serial.print(DHT.humidity);
    Serial.print("% ");
    Serial.println("temperature = ");
    Serial.print(DHT.temperature);
    Serial.println("C ");
    Serial.print("Counter = ");
    Serial.println(Counter);
    Serial.print("PIR = ");
    Serial.println(analogRead(A1));    
    Serial.print("Timer = ");
    Serial.println((millis()-Counter)); 
  }

 
  if ((analogRead(A1)) > 500){
  Counter = millis();
  }

  if ((DHT.humidity >= HUMIDITYTREASHOLD) || ((analogRead(A1)) > 500)){
    digitalWrite(RELAY1, LOW);  // turn Fan ON
  }

  if ((DHT.humidity < (HUMIDITYTREASHOLD - 3)) && ((analogRead(A1)) < 200) && ((millis()-Counter) >= 300000)) {
    digitalWrite(RELAY1, HIGH);  // turn Fan OFF
  }


  if(millis() - previousMillisLed > interval) {
    // save the last time you blinked the LED 
    previousMillisLed = millis();   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }

}

"timer" variables should be
unsigned long previousMillis = 0;        // will store last time LED was updatedThen the magic works - there is no problem with "overflow" - you have written the code right

if(millis() - previousMillisLed > interval) {

If you want to understand how unsigned long solves the rollover problem, try the sketch from this: Arduino Playground - TimingRollover

The thing with millis(), long or not long, rollover problem is that after 52days continously, it will roll over.
That will render your sketch useless for 52days.

The way to deal with it is that your millis can can never be less than your previous stored millis.

If that happens you just make them equal.

Simple.

Did you have a look at my previous post ?
When a unsigned long has a rollover (for example millis() itself) and the previous value did not yet rollover, they still can be substracted and that still will be a positive number, even if the first one is a very low value (because it did a rollover).

Thanks for your input. I will have a look at my code again. Is there any way of "speeding up" millis to test the rollover? Like starting of millis at a really high value that's just before the point of it rolling over.

If you read Reply #2 and follow that link and run the example at the bottom, you see a real test.

I think it is possible to change millis(), it's just a variable. But it will be hard to test if millis() rollover has influence on the sketch. It is better to check the sketch source code and check that everything is "unsigned long" and that always the newer time is substracted with the older time (and not the other way around).

nice idea and implementation. Where do you get 5v from?

janost:
The thing with millis(), long or not long, rollover problem is that after 52days continously, it will roll over.
That will render your sketch useless for 52days.

The way to deal with it is that your millis can can never be less than your previous stored millis.

If that happens you just make them equal.

Rubbish. :stuck_out_tongue_closed_eyes:

If you use unsigned variables and do the subtraction the "rollover" problem does NOT EXIST.

Here is a post where I have a longer explanation. -> micros() wrapping problem - #12 by 3dprinter - Programming Questions - Arduino Forum

And back to the posters next question (inspired by janost's FUD)

Tobbera:
Is there any way of "speeding up" millis to test the rollover?

You can use unsigned integer for all "timer variables". Use word(millis() ) to get current value. Now you get the rollover every 65.536 seconds. So you test program should have timers at 10 seconds duration or so. (Otherwise you may fall into the trap and confusion of timers "auto retriggering" as described in my longer explanation above)

dtokez:
nice idea and implementation. Where do you get 5v from?

A 230 volt USB wall charger that I ripped apart. But be careful, I made a misstake and I got electricuted, then the fuse in the switchboard went. Not a nice experience.

Tobbera:
Is there any way of "speeding up" millis to test the rollover?

Yes. Use unsigned short instead of unsigned long. You will have to consistently cast the value returned from millis.

Or, use this function instead of millis. The wrap occurs five seconds after your board is reset...

unsigned long MyMillis( void )
{
  const unsigned short Offset = (unsigned long)(-1) - 5000ul;

  return( millis() + Offset );
}

Thanks, I will boomark this for future millis-rollover-tolerance-testing. =)