implementing and understanding "millis" help

Hello people, I hope you are all well.
I am new to Arduino and electronics/coding in general and i am learning as i go. So any thoughts, suggestions, tips, etc outside of my question would go a long way to helping me improve and i thank you in advance!

I am attempting to build a temperature controlled environment using peltier plates controlled by an uno. In the near future, I would like to add a push button that switches a screen on for 3 seconds. I would like to delay my code for temperature monitoring/changing the state of the peltier plates( i.e peltier plate HIGH or LOW), however i became aware that using the “delay” function pauses the whole loop and would cause problems for monitoring the push button state. Which is where i found “millis”. I just cant get my head around it. Here is my current code with the bare bones of the millis function. If you could point me in the right direction on how to implement millis or another, better way of delaying a section of the loop that would be fantastic.

/* An Arduino controlled ciruit that maintains a tempreture range, either by heating the environment or cooling the environment using peltier plates, which are 
represented by a red LED and a blue LED as circuits.io doesn't have peltier plates in the components list. It will also use a fan to maximise the environment control*/

//Assign pins their names
//these integers will remain the same i.e constant
const int fan = 3;    //pin3 has a fan attached to it
const int cold = 4;   //pin 4 has a peltier that cools attached to it
const int hot = 5;    //pin 5 has a peltier that heats attached to it
const int therm = A1; //analog pin A1 has a thermometer attached to it 
const long interval = 120000 //pause for 2 minutes /*using long as an integer cannot store the 
                               value of time as it will get too large*/
//these integers will change
int thermValue = 0; //integer to store the thermometer value

unsigned long previousMillis = 0;

void setup() {
  pinMode(fan, OUTPUT);    //set fan pin to output
  pinMode(cold, OUTPUT);   //set cold pin to output
  pinMode(hot, OUTPUT);    //set hot pin to output
  Serial.begin(9600);     //start serial connection
} //close setup

void loop(){
  int thermValue = analogRead(therm); //read the value of the thermometer at pin A1
 
  //display the thermometer value in serial view as a celsius value
  float mv = (thermValue/1024.0)*5000;
  float cel = mv/10;
  
  Serial.print("TEMPRETURE =");     
  Serial.print(cel);
  Serial.print("*C");
  Serial.println();
 
  //if the tempreture reported by the thermometer in celsius goes above 20 turn on the cooling peltier else remain off
  if (cel > 20)
  {
    digitalWrite(cold, HIGH);
  } //close if statement
  else
  {
    digitalWrite(cold, LOW);
  }//close else statement
  
  //if the tempreture reported by the thermometer in celsius goes below 15 turn on the fan else remain off
  if (cel < 15)
  {
    digitalWrite(hot, HIGH);
  } //close else statement
  
  else
  {
    digitalWrite(hot, LOW);
  } //close the else statement
  
  //if the tempreture reported by the thermometer in celsius goes above 25 turn the fan on else remain off
  if (cel > 25)
  {
    digitalWrite(fan, HIGH);
  } //close the if statement
  
    else
  {
    digitalWrite(fan, LOW);
  } //close the else statement
  
    //if the tempreture reported by the thermometer goes below 10 turn the fan on else remain off
    if (cel < 10)
    {
      digitalWrite(fan, HIGH);
    } //close the if statement
  
    else
    {
      digitalWrite(fan, LOW);
    } //close the else statement
    
  /*commented out the delay as it pauses the whole code. I want to add an 
  lcd screen with a button that switches on the lcd for a certain ammount 
  of time and delay would casue problems with monitoring the button state*\
  //delay(10000); //delay 10 seconds to stop the constant switching of peltier plates at seesaw tempretres.
  
  } //close loop

Thank you very much!! And i do appreciate any help.

Something like this, I think:

unsigned long previousMillis = 0;
bool delayActive = 0;

void loop()
{
--stuff--

if (delayActive == 0) {
    --existing peltier if statements --
    delayActive = 1;
    }

if (millis() - previousMillis > 10000) {
    delayActive = 0;
    previousMillis = millis()
    }   
}

BTW

Google: hysteresis electronics

Or click here.

Hey LarryD and evanmars, thanks for the quick reply and apologies for my slow one.
I will have a read and give that code a go later today and let you know the outcome.

Thanks again.

Try these mods, should give you a 5 second display update and the 1 degree hysteresis should cut down on the frequent ON / OFF switching.

/* An Arduino controlled circuit that maintains a temperature range, either by heating the environment or cooling the environment using peltier plates, which are
represented by a red LED and a blue LED as circuits.io doesn't have peltier plates in the components list. It will also use a fan to maximize the environment control*/

//Assign pins their names
//these integers will remain the same i.e, constant
const int fan = 3;    //pin3 has a fan attached to it
const int cold = 4;   //pin 4 has a peltier that cools attached to it
const int hot = 5;    //pin 5 has a peltier that heats attached to it
const int therm = A1; //analog pin A1 has a thermometer attached to it
const long interval = 120000; //pause for 2 minutes using long as an integer cannot store the
                              //value of time as it will get too large
//these integers will change
int thermValue = 0; //integer to store the thermometer value

unsigned long previousMillis = 0;
int displayUpDate = 5000;
void setup() {
  pinMode(fan, OUTPUT);    //set fan pin to output
  pinMode(cold, OUTPUT);   //set cold pin to output
  pinMode(hot, OUTPUT);    //set hot pin to output
  Serial.begin(9600);     //start serial connection
} //close setup

void loop(){
  int thermValue = analogRead(therm); //read the value of the thermometer at pin A1
 
  //display the thermometer value in serial view as a celsius value
  float mv = (thermValue/1024.0)*5000;
  float cel = mv/10;

  if(millis() - previousMillis > displayUpDate) // timer has expired
  { 
    Serial.print("TEMPERATURE = ");     
    Serial.print(cel);
    Serial.print("*C");
    Serial.println();
    previousMillis = millis(); // reset timer
  }
 
  //if the temperature reported by the thermometer in celsius goes above 20 turn on the cooling peltier else remain off
  if (cel > 20)
  {
    digitalWrite(cold, HIGH);
  } //close if statement
  else if(cel < 19)
  {
    digitalWrite(cold, LOW);
  }//close else statement
 
  //if the temperature reported by the thermometer in celsius goes below 15 turn on the fan else remain off
  if (cel < 15)
  {
    digitalWrite(hot, HIGH);
  } //close else statement
 
  else if(cel > 16)
  {
    digitalWrite(hot, LOW);
  } //close the else statement
 
  //if the temperature reported by the thermometer in celsius goes above 25 turn the fan on else remain off
  if (cel > 25)
  {
    digitalWrite(fan, HIGH);
  } //close the if statement
 
    else if(cel < 24)
  {
    digitalWrite(fan, LOW);
  } //close the else statement
 
    //if the temperature reported by the thermometer goes below 10 turn the fan on else remain off
    if (cel < 10)
    {
      digitalWrite(fan, HIGH);
    } //close the if statement
 
    else if(cel > 11)
    {
      digitalWrite(fan, LOW);
    } //close the else statement
   
  /*commented out the delay as it pauses the whole code. I want to add an
  lcd screen with a button that switches on the lcd for a certain amount
  of time and delay would cause problems with monitoring the button state*\
  //delay(10000); //delay 10 seconds to stop the constant switching of peltier plates at seesaw temperatures.
*/ 
  }

You may still have a problem with ADC jitter making the temperature reading jump around, if so, report back and we’ll work on that.

Looks like you have not one but two void loop();s in there. I doubt the compiler is going to let that slide.

-jim lee

@ jimLee HAH! How'd I miss that? Must have been in the original copy & pasted code. ;) TNX Hawkeye. :)

The demo Several Things at a Time illustrates the use of millis() to manage timing. It may help with understanding the technique.

...R

Hey guys. Thanks for all the replys. I'll have a look at the demo, thanks robin2 and thanks outsider. the code worked.

Just a small piece of advice. It is much easier to help if you reply quickly while we can still remember your project.

...R

Hi Robin, I know, I am sorry for my awful reply times, I have been working away in the middle of nowhere and wifi etc were hard to come by. I am now back at home.

Ok, i have tried the new code, and it does work. However. When the temp drops below 10c the fan spins at <1RPM, but when the temp is above 25c the fan spins at over 1000RPM.
Im not sure why.

I’m not sure if i have mentioned but i am using circuits.io to simulate the arduino, could that have something to do it?

Thanks again, and once again i am sorry for my poor replies and thanks for sticking with me!

Again, post your code when asking a question or you will be yapped at by the big boys.

-jim lee

Sorry and thank you!

/* An Arduino controlled circuit that maintains a temperature range, either by heating the environment or cooling the environment using peltier plates, which are
represented by a red LED and a blue LED as circuits.io doesn't have peltier plates in the components list. It will also use a fan to maximize the environment control*/

//Assign pins their names
//these integers will remain the same i.e, constant
const int fan = 8;    //pin3 has a fan attached to it
const int cold = 6;   //pin 4 has a peltier that cools attached to it
const int hot = 7;    //pin 5 has a peltier that heats attached to it
const int therm = A1; //analog pin A1 has a thermometer attached to it
const long interval = 120000; //pause for 2 minutes using long as an integer cannot store the
                              //value of time as it will get too large
//these integers will change
int thermValue = 0; //integer to store the thermometer value
bool delayActive = 0;
unsigned long previousMillis = 0;
int displayUpDate = 10;
void setup() {
  pinMode(fan, OUTPUT);    //set fan pin to output
  pinMode(cold, OUTPUT);   //set cold pin to output
  pinMode(hot, OUTPUT);    //set hot pin to output
  Serial.begin(9600);     //start serial connection
  
} //close setup

void loop(){
  int thermValue = analogRead(therm); //read the value of the thermometer at pin A1
 
  //display the thermometer value in serial view as a celsius value
  float mv = (thermValue/1024.0)*5000;
  float cel = mv/10;

  if(millis() - previousMillis > displayUpDate) // timer has expired
  { 
    Serial.print("TEMPERATURE = ");     
    Serial.print(cel);
    Serial.print("*C");
    Serial.println();
    previousMillis = millis(); // reset timer
  }
 if (delayActive == 0) {
    if (cel > 20)
  {
    digitalWrite(cold, HIGH);
  } //close if statement
  else if(cel < 19)
  {
    digitalWrite(cold, LOW);
  }//close else statement
 
  //if the temperature reported by the thermometer in celsius goes below 15 turn on the fan else remain off
  if (cel < 15)
  {
    digitalWrite(hot, HIGH);
  } //close else statement
 
  else if(cel > 16)
  {
    digitalWrite(hot, LOW);
  } //close the else statement
 
  //if the temperature reported by the thermometer in celsius goes above 25 turn the fan on else remain off
  if (cel > 25)
  {
    digitalWrite(fan, HIGH);
  } //close the if statement
 
    else if(cel < 24)
  {
    digitalWrite(fan, LOW);
  } //close the else statement
 
    //if the temperature reported by the thermometer goes below 10 turn the fan on else remain off
    if (cel < 10)
    {
      digitalWrite(fan, HIGH);
    } //close the if statement
 
    else if(cel > 11)
    {
      digitalWrite(fan, LOW);
    } //close the else statement
    delayActive = 1;
    }

if (millis() - previousMillis > 10) {
    delayActive = 0;
    previousMillis = millis();
    }   
  //if the temperature reported by the thermometer in celsius goes above 20 turn on the cooling peltier else remain off
  
   
  /*commented out the delay as it pauses the whole code. I want to add an
  lcd screen with a button that switches on the lcd for a certain amount
  of time and delay would cause problems with monitoring the button state*\
  //delay(10000); //delay 10 seconds to stop the constant switching of peltier plates at seesaw temperatures.
*/ 
  }
.
.
.
if(cel < 24)
  {
    digitalWrite(fan, LOW);

.
.
.
if (cel < 10)
    {
      digitalWrite(fan, HIGH);
    } //close the if statement

.
.
.

You are telling your machine two different things to do. And like a good little machine, its doing it. :slight_smile:

-jim lee

I see what you're saying. Ok, do i need to use the 1 degree hysterisis if i'm using millis?

No… The read deal is you are assuming that once you find a choice the machine won’t check all the other choices as well. You need/should restructure your decision code to be more straight forward.

Think of temp as a line and you check different regions for actions.

(cel>15 && cel<20) See? This is a temp segment that can’t be mixed up with (cel>0 && cel<11)

You are looking t open ended things (cel>0) and they will always overlap.

-jim lee

OK, i think i understand let me do some googling and come back. Would i be right in saying i need to set the range i don't want the fan on, and some how say if the temperature is outside the range turn the fan on.

  //display the thermometer value in serial view as a celsius value
  float mv = (thermValue/1024.0)*5000;
  float cel = mv/10;

Why not kill the floats?

  //display the thermometer value in serial view as a celsius value
  int mv = (thermValue*5000L)/1024;
  int cel = mv/10;

(The reason I typed 5000L instead of just typing 5000 was to force the use of longs for an intermediate calculation.)

Why even use mv?

  //display the thermometer value in serial view as a celsius value
  int cel = (thermValue*500L)/1024;

I thought a float was supposed to be used where there is a decimal? Can long store these too?