while?, do while?, how do i do this?

here is what I want it to do: when temp drops below 70 turn heater on till temp gets to 73 and if temp gets above 75 turn on A/C till it gets to 73, I want to still have time ticking away while this is going on if at all possible

#include <dht.h>
#include <Time.h>
#include <TimeLib.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define DS1307_I2C_ADDRESS 0x68   //RTC address

dht DHT;
  
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  

int Fahrenheit(int celsius)
  {
    return 1.8 * celsius + 32;  //calibrate temp here in C to F conversion
  }
byte decToBcd(byte val)
  {
    return((val/10*16) + (val%10)); 
  }
byte bcdToDec(byte val)
  {
    return((val/16*10) + (val%16));
  }
int DHT11_PIN = 3;
int HeaterPin = 4;
int CoolingPin = 5;
int LightingPin = 6;
int CT_Pin = A0;
int CT_Value;

void setup() //runs once
{
  Wire.begin();             
  Serial.begin(9600);        
  //setDS1307time(00,37,20,4,25,01,17); //set DS1307 Time&Date: seconds, minutes, hours, day, date, month, year; comment out after setting and re-upload
  pinMode(HeaterPin, OUTPUT);
  pinMode(CoolingPin, OUTPUT);
  pinMode(LightingPin, OUTPUT);
  lcd.begin(20,4);          
  lcd.setCursor(0, 1);      
  lcd.print("Tmp:");        
  lcd.setCursor(10, 1);
  lcd.print("Hmd: ");
  lcd.setCursor(0, 2);
  lcd.print("A/C: ");
  lcd.setCursor(9, 2);
  lcd.print("Ht: ");
  lcd.setCursor(0, 3);
  lcd.print("Lts: ");
  lcd.setCursor(9, 3);
  lcd.print("Pwr: ");
  lcd.setCursor(19, 3);
  lcd.print("W ");
}

void setDS1307time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)  
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}

void readDS1307time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0); 
  Wire.endTransmission(); 
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);  //requesting 7 bytes from DS1307 beginning at register 00h
  *second = bcdToDec(Wire. read() & 0x7f);
  *minute = bcdToDec(Wire. read());
  *hour = bcdToDec(Wire. read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire. read());
  *dayOfMonth = bcdToDec(Wire. read());
  *month = bcdToDec(Wire. read());
  *year = bcdToDec(Wire. read());
}

void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  readDS1307time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  lcd.setCursor(0, 0);  
  lcd.print(month, DEC);
  lcd.print("/");
  lcd.print(dayOfMonth, DEC);
  lcd.print("/");
  lcd.print(year, DEC);
  lcd.print(" ");
  lcd.print(hour, DEC);
  lcd.print(":");
  if(minute < 10)
    {
      lcd.print("0");
    }
  lcd.print(minute, DEC);
  lcd.print(":");
  if(second < 10)
    {
      lcd.print("0");
    }
  lcd.print(second, DEC);
  lcd.print(" ");
  switch(dayOfWeek)
    {
      case 1:
        lcd.print("Su ");
        break;
      case 2:
        lcd.print("Mo ");
        break;
      case 3:
        lcd.print("Tu ");
        break;
      case 4:
        lcd.print("We ");
        break;
      case 5:
        lcd.print("Th ");
        break;
      case 6:
        lcd.print("Fr ");
        break;
      case 7:
        lcd.print("Sa ");
        break;
    }
}

void displayDHT11() 
{
  int chk = DHT.read11(DHT11_PIN);
  /*Serial.print("C: ");    //debug 
  Serial.println(DHT.temperature);
  Serial.print(" F: ");
  Serial.print(Fahrenheit(DHT.temperature));*/
  delay(250);       //need to give the sensor a little time before next reading                         
  lcd.setCursor(5, 1);
  lcd.print(Fahrenheit(DHT.temperature)); 
  lcd.print(char(223));
  lcd.print("F");
  lcd.setCursor(15, 1);
  lcd.print(DHT.humidity, 0);
  lcd.print("%");
}

void displayPower() 
{ 
  CT_Value = analogRead(CT_Pin);
  //Serial.println(CT_Value); //debug
  int Wattage = (CT_Value*0.0575*116);    //calibration to go from 10 bit A/D reading to power, 0.0575 A/count 
  lcd.setCursor(14, 3);
  lcd.print(Wattage, DEC); 
}

void Switching() //function switches outlets on and off and displays statuses
{  
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; 
  int chk = DHT.read11(DHT11_PIN);
  readDS1307time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  if (5 < hour && hour < 18)
    {
      digitalWrite(LightingPin, HIGH);
      lcd.setCursor(5, 3);
      lcd.print("ON ");
    }
  else
    {
      digitalWrite(LightingPin, LOW);
      lcd.setCursor(5, 3);
      lcd.print("OFF");
    }
  /*Serial.print("C: ");    //debug 
  Serial.println(DHT.temperature);
  Serial.print(" F: ");
  Serial.print(Fahrenheit(DHT.temperature));*/
  if (Fahrenheit(DHT.temperature) < 70)  
   {
      digitalWrite(HeaterPin, HIGH);
      lcd.setCursor(13, 2);
      lcd.print("ON "); 
   } 
   else 
   {
     digitalWrite(HeaterPin, LOW);
     lcd.setCursor(13, 2);
     lcd.print("OFF");
   }
  if (Fahrenheit(DHT.temperature) > 75) 
   {
      digitalWrite(CoolingPin, HIGH);
      lcd.setCursor(5, 2);
      lcd.print("ON ");
   } 
   else 
   {
    digitalWrite(CoolingPin, LOW);
    lcd.setCursor(5, 2);
    lcd.print("OFF");
   }
}

void loop()
{
   displayTime();
   displayDHT11();
   displayPower();
   Switching();
   delay(675); 

   // to run forever
  
}

here is what I have tried

if (Fahrenheit(DHT.temperature) < 70)  
   {
      while (Fahrenheit(DHT.temperature) < 73)
      {
        digitalWrite(HeaterPin, HIGH);
        lcd.setCursor(13, 2);
        lcd.print("ON ");
      }
   } 
   else 
   {
     digitalWrite(HeaterPin, LOW);
     lcd.setCursor(13, 2);
     lcd.print("OFF");
   }
  if (Fahrenheit(DHT.temperature) > 75) 
   {
      while (Fahrenheit(DHT.temperature) > 73)
      {
        digitalWrite(CoolingPin, HIGH);
        lcd.setCursor(5, 2);
        lcd.print("ON ");
      }
   } 
   else 
   {
    digitalWrite(CoolingPin, LOW);
    lcd.setCursor(5, 2);
    lcd.print("OFF");
   }

also I have tried

if (Fahrenheit(DHT.temperature) < 70)  
   {
      do
      {
        digitalWrite(HeaterPin, HIGH);
        lcd.setCursor(13, 2);
        lcd.print("ON ");
      }while (Fahrenheit(DHT.temperature) < 73);

   } 
   else 
   {
     digitalWrite(HeaterPin, LOW);
     lcd.setCursor(13, 2);
     lcd.print("OFF");
   }
  if (Fahrenheit(DHT.temperature) > 75) 
   {
       do      {
        digitalWrite(CoolingPin, HIGH);
        lcd.setCursor(5, 2);
        lcd.print("ON ");
      }while (Fahrenheit(DHT.temperature) > 73);

   } 
   else 
   {
    digitalWrite(CoolingPin, LOW);
    lcd.setCursor(5, 2);
    lcd.print("OFF");
   }

anyway to accomplish this while everything else still runs? both seem to stop everything else while doing the while and do while

You do not need any kind of looping.

Suppose I asked you turn turn a light on when (NOT while) the temperature hit 75 degrees, and to turn the light off when the temperature hit 70 degrees. Could you do that?

Writing the code to make the Arduino do that is just as simple.

In pseudo-code:
read the temperature.
if(it is above 75)
turn the heater off
else if(it is below 70)
turn the heater on

No loops needed. There are only discrete events.

It doesn't hurt to keep turning the heater on every time you discover that it is below 70. It doesn't hurt to turn the heater off every time you discover that it is above 75.

Now, if you want the Arduino to do nothing else between the time it discovers that it is cold and the time that it discovers that it is warm enough, then you need to use a while loop. But, it seems silly to do nothing the whole time the heater is running (except read the temperature, that is).

I want to mitigate relays switching numerous times when temp is teetering at the boundaries

PaulS is correct.

I will add this:

(1) The loop() function is all the infinite loop that you should need.

(2) The while statement will execute zero or more times.
The do ... while statement will execute at least once and possibly more times.

To avoid relays switching a lot at boundaries, you need to use something called hysteresis. The threshold should change depending upon whether the relay is activated or not. The difference in the thresholds is a trade-off between how closely you want to maintain the temperature versus how much switching you will accept.

The pseudocode that was presented by PaulS has a five degree difference* in thresholds that accounts for precisely this.

  • The thresholds that were used by PaulS have a difference of five degrees, but the threshold difference may be greater depending upon how closely the temperature is measured.

I guess I don't see how the pseudocode is going to behave differently than mine right now??? is the else if apart of the if statement like my elses are?? if so how will get to the else if?

let me see if I can wrap my head around it.....

so in PaulS' code if the temp is above 75 the heater will be off if it drops below 70 then the heater will turn on until the temp reaches above 75? is this correct? is the if the stop point and else if the start point?

Very nice!! Thanks for the help.

dcrash36:
so in PaulS' code if the temp is above 75 the heater will be off if it drops below 70 then the heater will turn on until the temp reaches above 75? is this correct? is the if the stop point and else if the start point?

In most arduino programming, we rely on the fact that loop() gets called over and over by the underlying main() routine. Generally speaking, rather than looping, your "loop" function just checks to see if anything needs to be done right now, does that thing, and exits.

This makes it much easier to run multiple things.

Lets say that you had two things that you wanted to turn ojn and off with hysteresis, or one running on a timer and one using the sensor. Trying to write it as interlocking loops - you'd have to nest your loops infinitely deep to catch the (increasingly unlikely) possibilities. Instead, you just check each condition separately in the loop() and rely on the fact that the chip runs at 16MHz.