This is my first time posting so forgive me if I don't have my sketch uploaded correctly. I am an arduino novice by far, just learning as I go, I am also a farmer so I decided I wanted to make a controller for my grain bin fans based on temperature and humidity readings to control a relay which would in turn control the fan. I have succeeded in accomplishing that but I wanted to refine it a bit more and use millis() to tell the ardruino that once the temp/humidity threshold has been reached, to leave the fan on for xx amount of time before it shuts off even if the temp/humidity drops back below the threshold during that time. I think I mostly understand the millis() function but I can't seem to figure out how exactly to implement it in place of delay() in my code. Its the last several lines in those if statements, where it says delay(600UL) thats where I want to utilize millis. If possible anyway. Thank you in advance for any help!
/* turn led on if temp is above certain point
*/
// global constants
unsigned long previousTime = 0;
const unsigned long minRunTime = 1,200,000UL;
// library
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
#define DHTPIN 7
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
//Variables
int chk;
float hum;//Stores humidity
float temp;//stores temp
int relay = 3;
void setup() {
Serial.begin(9600);
lcd.begin(16,2);
dht.begin();
pinMode(3, OUTPUT);
pinMode(2, OUTPUT);
}
void loop() {
unsigned long currentTime = millis();
delay(2000);
//Read humidity and temp
hum = dht.readHumidity();
temp = dht.readTemperature(true);
//Prints Humidity and Temp to serial monitor
Serial.print("humidity:");
Serial.print(hum);
Serial.print("%, Temp:");
Serial.print(temp);
Serial.println("F");
lcd.clear();
lcd.print("HUM: ");
lcd.print(hum);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("TEMP: ");
lcd.print(temp);
lcd.print("F");
delay(10000);
//Turn fan on if temp and humidity is within the threshold
if ((temp) > 30 and (hum) > 20 and (temp) < 90 and (hum) < 50) {
digitalWrite(3, HIGH);
if (relay = HIGH) delay(600UL);
} else {
digitalWrite(3, LOW);
}
}
Did you have a look at the Blink Without Delay sketch? (File->Examples->-02.Digital->BlinkWithoutDelay). It will show you have to use millis() properly.
Then, read the sticky post at the top of the forum and learn now to properly add your code inside code tags.
If you get stuck, post back and please do it properly.
I think I got the code posted correctly now. At least it is on my screen anyway. I have looked at Bwod, but that and every other example I have found is just telling it to do print or read something every xx amount of time. I am reading sensors and then based off the data that is returned from said sensor, I may or may not want it to wait for a certain amount of time. The reason I want to use millis is so I can still have up to date temp and humidity readings even when its in that delay period. Obviously if you use delay it all just stops and waits until that time period is up so I can't get my readings every 10 seconds like I want to during that time.
As a first time poster - you deserve ++karma for making the effort.
Now to the millis() thing.
It seems unintuitive at first glance to a beginner, but you need to get your head around the idea that loop() is running all the time - fast.
You can set, check & do things on separate passes each time around - which appear to be happening 'instantly'... in reality they may occur milliseconds apart - but you and most projects don't care about that.
(Later - you may learn some other, more advanced tricks, or ultimately step up to a more complex platform than the Arduino IDE and 8-bit chips.)
Put your project aside for a few hours, load up and work through the BWoD examples, just blinking LEDs... tweak them and try to understand why they do what they do, and how. It's not so tricky when you spend a few minutes figuring it out.
Thanks for the responses! Maybe I didn't word it correctly or maybe I am just not quite wrapping my mind around those examples, but they aren't what I need. All those examples are just timing based to blink an LED or something of that sort, there isn't any other data being used in those statements. What I need is to have a relay remain on for 20 minutes once its turned on. So do I need an if statement within an if statement to make millis work in this case? I've already got an if statement checking the data from the DHT22 and then what it to remain on for 20 minutes if the temp and humidity is within the threshold even if it drops back below said threshold.
What I need is to have a relay remain on for 20 minutes once its turned on. So do I need an if statement within an if statement to make millis work in this case?
Turn it on. Save the current value of millis(). Check each time through loop whether the current value of millis() minus the start value equals or is greater than the required period. If so then do something like turning it off, otherwise keep going round loop()
If you want other factors to influence whether it turns on then introduce a boolean to the program and turn on the relay only if the boolean is true. If for some reason it must not turn on then set the boolean to false and it won't happen
This is mostly classic BlinkWithoutDelay as exemplified by the example of that name
Farmboy1994:
Thanks for the responses! Maybe I didn't word it correctly or maybe I am just not quite wrapping my mind around those examples, but they aren't what I need. All those examples are just timing based to blink an LED or something of that sort, there isn't any other data being used in those statements. What I need is to have a relay remain on for 20 minutes once its turned on. So do I need an if statement within an if statement to make millis work in this case? I've already got an if statement checking the data from the DHT22 and then what it to remain on for 20 minutes if the temp and humidity is within the threshold even if it drops back below said threshold.
Always test the timer in each iteration of loop(). Write come code and try to get it working, then come back with your sketch and any questions.
//Blink without Delay skeleton
//4 examples demonstrated
//
//LED wiring options
//=============================================
//Depending which way your LEDs are wired, uncomment the next line.
//#define PlusEqualsON
#ifdef PlusEqualsON
//wired so +5V turns LED ON
#define ledON HIGH
#define ledOFF LOW
//=========================
#else
//wired so +5V turns LED OFF
#define ledON LOW
#define ledOFF HIGH
//=========================
#endif
//switch wiring options
//=============================================
//Depending which way your switches are wired, uncomment the next line.
#define PushEqualsLOW
#ifdef PushEqualsLOW
//pushing the switch makes pin LOW
#define Pushed LOW
#define Released HIGH
//=========================
#else
//pushing the switch makes pin HIGH
#define Pushed HIGH
#define Released LOW
//=========================
#endif
//=============================================
unsigned long currentMillis;
unsigned long pin13Millis;
unsigned long pin12Millis;
unsigned long pin11Millis;
unsigned long SwitchMillis;
//if these are not changed in the sketch, they can be const
unsigned long debounceMillis = 100UL; //100ms
unsigned long ledOnTime = 5*1000UL; //5 seconds
byte laststartSwitchState = HIGH;
byte buttonState = HIGH;
byte counter = 0;
//the following are enable/disable flags
//some of these might not be used in this sketch
boolean flag13 = true;
boolean flag12 = true;
boolean flag11 = true;
boolean flag10 = true;
const byte startSwitch = 2; //pushed = LOW
const byte testSwitch = 3; //pushed = LOW
//**********************************************************************
void setup()
{
Serial.begin(9600);
digitalWrite(13,ledOFF);
pinMode(13, OUTPUT);
digitalWrite(12,ledOFF);
pinMode(12, OUTPUT);
digitalWrite(11,ledOFF);
pinMode(11, OUTPUT);
digitalWrite(10,ledOFF);
pinMode(10, OUTPUT);
pinMode(startSwitch, INPUT_PULLUP); //pushed = LOW
pinMode(testSwitch, INPUT_PULLUP); //pushed = LOW
} // >>>>>>>>>>>>>> E N D O F s e t u p ( ) <<<<<<<<<<<<<<<<<
void loop()
{
//save the current time
currentMillis = millis();
//************************************* E x a m p l e 1
//toggle pin 13 every 200mS
//has 200ms or more gone by?
if (currentMillis - pin13Millis >= 200UL)
{
//code here runs every 200ms
//get ready for next iteration
pin13Millis = pin13Millis + 200UL;
//toggle pin 13
digitalWrite(13,!digitalRead(13));
}
//************************************* E x a m p l e 2
//at power up, pin 12 LED goes ON, after 3 seconds goes OFF and stays OFF
//could be used as a powerup reset signal
if (flag12 == true && currentMillis - pin12Millis <= 3000UL)
{
//code here runs for 3 seconds after power up, then stops
digitalWrite(12,ledON);
}
else
{
digitalWrite(12,ledOFF);
//disable further pin 12 control
flag12 = false;
}
//************************************* E x a m p l e 3
//if testSwitch is pushed and released
//pin 11 LED goes ON for 5 seconds, then goes OFF
buttonState = digitalRead(testSwitch);
//are we are allowed to check the switch and is it pressed?
if(flag11 == true && buttonState == Pushed)
{
//enable timing of LED on pin 11
flag11 = false; //false --> timing is enabled
//turn LED ON
digitalWrite(11,ledON);
//record the time LED turned ON
pin11Millis = currentMillis;
}
//are we allowed and is it time to control pin 11
if (flag11 == false && currentMillis - pin11Millis >= ledOnTime)
{
//if enabled, code here runs after ledOnTime ms goes by
digitalWrite(11,ledOFF);
//allow switch press detection again
flag11 = true; //true --> switch monitoring is enabled
}
//************************************* E x a m p l e 4
//is it time to check the switches?
//in particular, pushing startSwitch will turn ON/OFF (toggle) an output pin 10
//is it time to check the switches
if (currentMillis - SwitchMillis >= debounceMillis)
{
//code here runs every debounceMillis ms
//get ready for the next iteration
SwitchMillis += debounceMillis;
//go and check the switches
checkSwitches();
}
//*********************************
//put other non-blocking stuff here
//*********************************
} // >>>>>>>>>>>>>> E N D O F l o o p ( ) <<<<<<<<<<<<<<<<<
//======================================================================
// F U N C T I O N S
//======================================================================
//****************** c h e c k S w i t c h e s ( ) *********************
//switches are checked every debounceValue milli seconds
//no minimum switch press time is validated with this code (i.e. No glitch filter)
void checkSwitches()
{
//re-usable for all the switches
boolean thisState;
//************************************* E x a m p l e Push ON push OFF (toggle)
//check if this switch has changed state
thisState = digitalRead(startSwitch);
if (thisState != laststartSwitchState)
{
//update the switch state
laststartSwitchState = thisState;
//this switch position has changed so do some stuff
//"HIGH condition code"
//switch went from LOW to HIGH
if(thisState == HIGH)
{
//Do some HIGH switch stuff here
}
//"LOW condition code"
//switch went from HIGH to LOW
else
{
//Do some LOW switch stuff here
digitalWrite(10, !digitalRead(10));
//print number of pushes
counter++;
Serial.println(counter);
}
} //END of startSwitch code
//*****************************************
//similar code for other switches goes here
//*****************************************
} //END of checkSwitches()
//**********************************************************************
//======================================================================
// E N D O F C O D E
//======================================================================
/* turn led on if temp is above certain point
*/
// global constants
unsigned long previousDisplayTime; // screen update time
const unsigned long displayDelay = 10000UL; // update screen every 10 seconds
unsigned long previousReadTime; // last sensor read time
const unsigned long readDelay = 2000; // read sensors every 2 seconds
unsigned long fanStartTime; // time fan turned on
const unsigned long minRunTime = 1000UL * 60 * 2; // 20 minute
bool fanRunning = false;
// library
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
#define DHTPIN 7
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
//Variables
float hum;//Stores humidity
float temp;//stores temp
const int relayPin = 3;
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
dht.begin();
pinMode(relayPin, OUTPUT);
pinMode(2, OUTPUT);
}
void loop() {
unsigned long currentTime = millis();
// check if it is time to read sensors
if ( currentTime - previousReadTime >= readDelay ) {
previousReadTime = currentTime;
//Read humidity and temp
hum = dht.readHumidity();
temp = dht.readTemperature(true);
//Prints Humidity and Temp to serial monitor
Serial.print("humidity:");
Serial.print(hum);
Serial.print("%, Temp:");
Serial.print(temp);
Serial.println("F");
}
// check if it is time to update lcd
if ( currentTime = previousDisplayTime >= displayDelay ) {
previousDisplayTime = currentTime;
lcd.clear();
lcd.print("HUM: ");
lcd.print(hum);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("TEMP: ");
lcd.print(temp);
lcd.print("F");
}
//check fan status
if ( fanRunning == true ) {
// fan already running so test how long it has been running and turn off if needed
if ( currentTime - fanStartTime >= minRunTime ) {
// turn it off
fanRunning = false;
digitalWrite(relayPin, LOW);
}
}
else {
// fan is not running so test if we need to turn it on
if ((temp) > 30 and (hum) > 20 and (temp) < 90 and (hum) < 50) {
digitalWrite(relayPin, HIGH);
fanStartTime = currenTime;
fanRunning = true;
}
}
}