Needed: more efficient code, need to learn about functions i think!.....help!

Hey, this is a fairly straight forward code which samples a temperature reading and turns relays on and off which control heat, ac, and fan.

Im new to writing code and I need some help with my code as follows.....Rather than having all the "if" statements within the loop to control the hvac equipment, is it possible to have other functions "do the work" which are called from the loop? Delays are needed for fan control during heating and it's delaying the entire code downstream of the delay.
example>>>>
heatControl()
turn heat on below a setpoint
delay
turn fan on

acControl()
turn ac on below a setpoint

void loop()
if heatControl()
turn heat and fan on

I hope thats clear as mud! hah XD

I'm sure once I see somthing written in my code I could learn alot and use this ability to add saftey functions (if blank happens dont allow the fan to come on) etc. Eventually I'm going to add zones with dampers and there will be a need for an end switch which closes when the damper fully opens, then allowing the fan to turn on. for example.

Any help is much appreciated

Chris

#include <math.h>

//------------------------------------------------------------------------------------------------------------------------------------

long HeatAutoOn = 18;  
long AcAutoOn = 25;  
long CheckTemp = 20000;
float TempDiffHeat = HeatAutoOn+1.5;   
float TempDiffAc = AcAutoOn-1.5;
//--------------------------------------------------------------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------------------------------------------------------
unsigned long time;
long previoustime;
int w = 7;
int g = 9;
int y = 8;
boolean heat = false;
boolean ac = false;
boolean off = false;
//----------------------------------------------------------------------------------------------------------------------------------------------





void setup(){

  pinMode (w, OUTPUT);
  pinMode (g, OUTPUT);
  pinMode (y, OUTPUT);
  Serial.begin(9600);
}



//THERMISTER CALCULATIONS FOR TEMPERATURE CONVERSION----------------------------------------------------------------------------------------------

double Thermister(int RawADC) 
{
  double Temp;
  Temp = log(((10240000/RawADC) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
  Temp = Temp - 273.15;            // Convert Kelvin to Celcius
  //Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
  return Temp;
}

//-------------------------------------------------------------------------------------------------------------------------------------------------



void loop()
{
  
  Serial.print("Degrees C");
  Serial.println(int(Thermister(analogRead(0))));  // display C
  delay(1000);
  
  int command = Serial.read();

    if(command == '1')
    {
      digitalWrite(w, HIGH);
      Serial.println("MANUAL HEAT ON");
      delay(4000);
      digitalWrite(g, HIGH);
    }
    if (command == '2')
    {
      digitalWrite(w, LOW);
      Serial.println("MANUAL HEAT OFF");
      delay(4000);
      digitalWrite(g, LOW);

    }
    if(command == '3')
    {
      digitalWrite(y, HIGH);
      digitalWrite(g, HIGH);
      Serial.println("MANUAL A/C ON");
    }
    if (command == '4')
    {
      digitalWrite(y, LOW);
      digitalWrite(g, LOW);
      Serial.println("MANUAL A/C OFF");
    }
    if(command == '5')
    {
      digitalWrite(g, HIGH);
      Serial.println("MANUAL FAN ON");

    }
    if (command == '6')
    {
      digitalWrite(g, LOW);
      Serial.println("MANUAL FAN OFF");

    }
   
   if ((int(Thermister(analogRead(0)))) >= TempDiffHeat && (int(Thermister(analogRead(0)))) <= TempDiffAc && off == false){ //turns HVAC off
      digitalWrite(w, LOW);
      digitalWrite(y, LOW);
      Serial.println("AUTO HVAC SATISFIED");
      delay(5000);
      digitalWrite(g, LOW);
      off = true;
      heat = false;
      ac = false;
    }

  time = millis();
  if ((time - previoustime) > CheckTemp ){ 
    previoustime = time;


    if ((int(Thermister(analogRead(0)))) <= HeatAutoOn && heat == false) {      //turns heat on

      digitalWrite(w, HIGH);
      Serial.println("AUTO HEAT ON");
      delay(4000);
      digitalWrite(g, HIGH);
      heat = true;
      ac = false;
      off = false;
    }
   
   if ( (int(Thermister(analogRead(0)))) >= AcAutoOn && ac == false) {                // turns A/C on 
    digitalWrite(y, HIGH);
    digitalWrite(g, HIGH);
    Serial.println("AUTO A/C ON");
    heat = false;
    ac = true;
    off = false;
   }

  }
}

It's the millis(); thing
Blink Without Delay

The millis(), is a blink without delay which controls how often the program checks the temperature. That does not effect it atall, it's the delays within :

if ((int(Thermister(analogRead(0)))) <= HeatAutoOn && heat == false) { //turns heat on

digitalWrite(w, HIGH);
Serial.println("AUTO HEAT ON");
delay(4000);
digitalWrite(g, HIGH);
heat = true;
ac = false;
off = false;
}

I tried to make a blink without delay inside this if statement but I cannot get it to turn on. I labeled the constants and variables for the fan delay. Again, any help is greatly appreciated...

Thanks!

#include <math.h>

//-----------------------------------------------------------------------------------------------------------------------------------


long HeatAutoOn = 18;  
long AcAutoOn = 25;  
long CheckTemp = 20000;
float TempDiffHeat = HeatAutoOn+1.5;   
float TempDiffAc = AcAutoOn-1.5;
//-----------------------------------------------------------------------------------------------------------------------------------


//-----------------------------------------------------------------------------------------------------------------------------------

unsigned long time;
long previoustime;
int w = 7;
int g = 9;
int y = 8;
boolean heat = false;
boolean ac = false;
boolean off = false;
//-----------------------------------------------------------------------------------------------------------------------------------


//FAN DELAY "BLINK WITHOUT DELAY"----------------------------------------------------------------------------------------------------
unsigned long currentDelay;
long previousDelay;
long fanInterval = 4000;
//----------------------------------------------------------------------------------------------------------------------




void setup(){

  pinMode (w, OUTPUT);
  pinMode (g, OUTPUT);
  pinMode (y, OUTPUT);
  Serial.begin(9600);
}



//THERMISTER CALCULATIONS FOR TEMPERATURE CONVERSION---------------------------------------------------------------------------------


double Thermister(int RawADC) 
{
  double Temp;
  Temp = log(((10240000/RawADC) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
  Temp = Temp - 273.15;            // Convert Kelvin to Celcius
  //Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
  return Temp;
}

//-----------------------------------------------------------------------------------------------------------------------------------




void loop()
{

  Serial.print("Degrees C");
  Serial.println(int(Thermister(analogRead(0))));  // display C
  delay(1000);



  currentDelay = millis();
  int command = Serial.read();

//TRYING THE "BLINK WITHOUT DELAY" INSIDE THIS JUST TO TEST IF IT WORKS BUT I CANNOT GET IT TO TURN ON---------------------------------
  if(command == '1'){
    Serial.println("MANUAL HEAT ON");
    digitalWrite(w, HIGH);
    if ((currentDelay - previousDelay) > fanInterval){
      previousDelay = currentDelay;
      digitalWrite(g, HIGH);
    }
//------------------------------------------------------------------------------------------------------------------------------------
   
    if (command == '2')
    {
      digitalWrite(w, LOW);
      Serial.println("MANUAL HEAT OFF");
      delay(4000);
      digitalWrite(g, LOW);

    }
    if(command == '3')
    {
      digitalWrite(y, HIGH);
      digitalWrite(g, HIGH);
      Serial.println("MANUAL A/C ON");
    }
    if (command == '4')
    {
      digitalWrite(y, LOW);
      digitalWrite(g, LOW);
      Serial.println("MANUAL A/C OFF");
    }
    if(command == '5')
    {
      digitalWrite(g, HIGH);
      Serial.println("MANUAL FAN ON");

    }
    if (command == '6')
    {
      digitalWrite(g, LOW);
      Serial.println("MANUAL FAN OFF");
    }
  }






  if ((int(Thermister(analogRead(0)))) >= TempDiffHeat && (int(Thermister(analogRead(0)))) <= TempDiffAc && off == false){ //turns HVAC off


    digitalWrite(w, LOW);
    digitalWrite(y, LOW);
    off = true;
    heat = false;
    ac = false;
    Serial.println("AUTO HVAC SATISFIED");
    digitalWrite(g, LOW);

  }

  time = millis();
  if ((time - previoustime) > CheckTemp ){ 
    previoustime = time;


    if ((int(Thermister(analogRead(0)))) <= HeatAutoOn && heat == false) {      //turns heat on

      digitalWrite(w, HIGH);
      Serial.println("AUTO HEAT ON");
      delay(4000);
      digitalWrite(g, HIGH);
      heat = true;
      ac = false;
      off = false;
    }

    if ( (int(Thermister(analogRead(0)))) >= AcAutoOn && ac == false) {                // turns A/C on 
      digitalWrite(y, HIGH);
      digitalWrite(g, HIGH);
      Serial.println("AUTO A/C ON");
      heat = false;
      ac = true;
      off = false;
    }

  }
}

Think you just should check the temperature and if it is too low switch heater and fan on and if it is too low switch both off. (Why those 4 seconds?)
As loop is executed multiple times per second you do not need delay's or so.

What is important is to keep the state and the previous state of the fan.

Partial code to get the idea

int heaterHIgh = 40;
int heaterLow = 35;
boolean heaterOn = false;   // simple state machine reflecting the heater
boolean prevState = false;

void setup()
{
  //...
}


void loop()
{
  // READ SENSOR
  int t = Thermister(analogRead(0));

  // DO SOME STATE MACHINE MATH
  if (t <= heaterLow) heaterOn = true;
  else if (t >= heaterHIgh) heaterOn = false;

  // ADJUST HEATER AND FAN
  if ((heaterOn == true) && (prevState != true))  // state changed to true
  {
    prevState = true;
    digitalWrite(w, HIGH);
    Serial.println("AUTO HEAT ON"); 
    digitalWrite(g, HIGH);
  }
  if ((heaterOn == false) && (prevState != false)) // state chenged to false
  {
    prevState = false;
    digitalWrite(w, LOW);
    Serial.println("AUTO HEAT OFF"); 
    digitalWrite(g, LOW);
  }

  // other code can be here

}

Code above can be expanded so that you can set heaterhigh and heaterLow over the serial port
Furthermore it might be possible to steer the fan by means of PWM and let the RPM depend on the actual temperature.

2 cents,

Someone got on this while I was typing, so just to tag on..
The idea, in "millisizing" delay(4000);, is to take note of the time when you initiate an action and then terminate it when the time has gone 4000 past that noted time.

Thanks rob for the input,

I'll try to implement that into the code as I learn more. The 4 second delay is for testing purposes, once I have everything dialed in I would raise it to about 45 seconds. This is done so the heat exchanger in the furnace heats up before the fan turns on( as to not blow cold air), and after the heat call is satisfied the fan stays for a minute or so to cool the heat exchanger.

I would use two heat sensors one to switch on the heater, and when it is heat enought switch on the fan.

But if you want to do it with a fixed (programmable) delay you should indeed check the blink without delay example as that is elementary for making responsive applications.

chris8644:
That does not effect it atall, it's the delays within :

No, not directly. However if you use variables to track if the fan should be on and how long it has been on, then you can certainly use millis().

You can setup state variables for things like a fan. Your functions set the state variable to be on or off.

In your main loop() you check those states and set the fan accordingly. You use a variables to track how long the fan has been on. When it has been on for long enough, set the state back to off.

It changes the logic from direct instruction sequence to more of a state machine.

Ok so I have re written my code and tried to make it more of a state machine sequence...i think..haha...and I actually quite like using booleans now!

This system is controlling one hvac system with two zones, pretty straight forward relay board with it. Now, I want to install a mechanical end switch which closes when the damper opens.

My question is how to do that in the code; send 5VDC out to switch, switch closes and inputs 5vdc back to micro controller which allows the code to continue, else if switch does not close system goes into a fault mode and does not allow code to continue?

**you will notice there is a 2 min delay after the heat is turned off, this is due to the fan will stay on (internal mechanical switch in furnace) until it cools down. I dont want the damper closing while the fan is still on! Did not want to go the hassle of a "blink on delay" and besides a two min delay in the system will not affect overall home comfort!!

Again any help is very appreciated thanks all!!

#include <math.h>
//FIRST FLOOR INTEGERS-------------------------------------------------------------------------------
int heatOn = 18; 
int heatOff = 19.5;
int airCon = 25;  
int acOff = 23;
int wOne = 0;
int yOne = 2;
int gOne = 4;
int damperOpen = 6;
//---------------------------------------------------------------------------------------------------

//SECOND FLOOR INTEGERS------------------------------------------------------------------------------
int heatOnTwo = 18;
int heatOffTwo = 19.5;
int airConTwo = 25;  
int acOffTwo = 23;
int wTwo = 1;
int yTwo = 3;
int gTwo = 5;
int damperOpenTwo;
//---------------------------------------------------------------------------------------------------
 
//TEMPERATURE CHECK DELAY-----------------------------------------------------------------------------
long checkTemp = 20000; 
long previoustime;
unsigned long time;
//----------------------------------------------------------------------------------------------------

//FIRST FLOOR BOOLEANS--------------------------------------------------------------------------------
boolean heaterOn = false;
boolean acOn = false;
boolean heatState = false;
boolean acState = false;
boolean damperOn = false;
boolean damperState = false;
//------------------------------------------------------------------------------------------------------

//SECOND FLOOR BOOLEANS---------------------------------------------------------------------------------
boolean heaterOnTwo = false;
boolean acOnTwo = false;
boolean heatStateTwo = false;
boolean acStateTwo = false; 
boolean damperOnTwo = false;
boolean damperStateTwo = false;
//-----------------------------------------------------------------------------------------------------



void setup()
 {
  pinMode (wOne, OUTPUT);
  pinMode (gOne, OUTPUT);
  pinMode (yOne, OUTPUT);
  pinMode (wTwo, OUTPUT);
  pinMode (gTwo, OUTPUT);
  pinMode (yTwo, OUTPUT);
  pinMode (damperOpen, OUTPUT);
  pinMode (damperOpenTwo, OUTPUT);
  Serial.begin(9600);
  }


double Thermister(int RawADC) 
{
  double Temp;
  Temp = log(((10240000/RawADC) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
  Temp = Temp - 273.15;            // Convert Kelvin to Celcius
  //Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
  return Temp;
}



void loop()
{
  
  int t = Thermister(analogRead(0));

  time = millis();
  if((time - previoustime) > checkTemp)
  {
  
    

    
 //HEAT CYCLE FIRST FLOOR-----------------------------------------------------------------------
  
  if (t <= heatOn) heaterOn = true, damperOn = true;
  else if (t >= heatOff) heaterOn = false, damperOn = false;
  
  if ((damperOn == true) && (damperState != true));
  {
    damperState = true;
    digitalWrite(damperOpen, HIGH);
  }
    

  if ((heaterOn == true) && (heatState != true));
  {
  heatState = true;
  digitalWrite(wOne, HIGH);
  Serial.println("AUTO HEAT ON");
  digitalWrite(gOne, HIGH);
  }

  if((heaterOn == false) && (heatState != false));
  {
  heatState = false;
  digitalWrite(wOne, LOW);
  Serial.println("AUTO HEAT OFF");
  digitalWrite(gOne, LOW);
  delay(120000);
  }
  
  if ((damperOn == false) && (damperState != false));
  {
    damperState = false;
    digitalWrite(damperOpen, LOW);
  }
  //-------------------------------------------------------------------------------------
  
  
  
//AC CYCLE FIRST FLOOR---------------------------------------------------------------------------------

  if (t >= airCon) acOn = true, damperOn = true;
  else if (t <= acOff) acOn = false, damperOn = false;

  if((damperOn == true) && (damperState != true));
  {
    damperState = true;
    digitalWrite(damperOpen, HIGH);
  }
  
  
  if((acOn == true) && (acState != true));
  {
  acState = true;
  digitalWrite(yOne, HIGH);
  Serial.println("AUTO AC ON");
  digitalWrite(gOne, HIGH);
  }
  
  if((acOn == false) && (acState != false));
  {
  acState = false;
  digitalWrite(yOne, LOW);
  Serial.println("AC AUTO OFF");
  digitalWrite(gOne, LOW);
  }

 if((damperOn == false) && (damperState != false));
  {
  damperState = false;
  digitalWrite(damperOpen, LOW);
  }
  
  
//------------------------------------------------------------------------------------------


//HEAT CYCLE SECOND FLOOR-----------------------------------------------------------------------
  
  if (t <= heatOnTwo) heaterOnTwo = true, damperOnTwo = true;
  else if (t >= heatOffTwo) heaterOnTwo = false, damperOnTwo = true;
  
  if((damperOnTwo == true) && (damperStateTwo != true));
  {
    damperStateTwo = true;
    digitalWrite(damperOpenTwo, HIGH);
  }

  if ((heaterOnTwo == true) && (heatStateTwo != true));
  {
  heatStateTwo = true;
  digitalWrite(wTwo, HIGH);
  Serial.println("AUTO SECOND FLOOR HEAT ON");
  digitalWrite(gTwo, HIGH);
  }

  if((heaterOnTwo == false) && (heatStateTwo != false));
  {
  heatStateTwo = false;
  digitalWrite(wTwo, LOW);
  Serial.println("AUTO SECOND FLOOR HEAT OFF");
  digitalWrite(gTwo, LOW);
  delay(120000);
  }
  
   if((damperOnTwo == false) && (damperState != false));
  {
  damperState = false;
  digitalWrite(damperOpenTwo, LOW);
  }
  
  //-------------------------------------------------------------------------------------
  
  
  
//AC CYCLE SECOND FLOOR---------------------------------------------------------------------------------

  if (t >= airConTwo) acOnTwo = true;
  else if (t <= acOffTwo) acOnTwo = false;
  
  if((damperOnTwo == true) && (damperStateTwo != true));
  {
    damperStateTwo = true;
    digitalWrite(damperOpen, HIGH);
  }

  if((acOnTwo == true) && (acStateTwo != true));
  {
  acState = true;
  digitalWrite(yTwo, HIGH);
  Serial.println("AUTO SECOND FLOOR AC ON");
  digitalWrite(gTwo, HIGH);
  }

  if((acOnTwo == false) && (acStateTwo != false));
  {
  acStateTwo = false;
  digitalWrite(yTwo, LOW);
  Serial.println("AUTO SECOND FLOOR AC OFF");
  digitalWrite(gTwo, LOW);
  }
  
   if((damperOnTwo == false) && (damperState != false));
  {
  damperState = false;
  digitalWrite(damperOpenTwo, LOW);
  }
  
}
}
  
//------------------------------------------------------------------------------------------

One of the nice thing about using booleans is that conditional statements can be shorter and cleaner. It's basically redundant to compare a boolean to a value as they are either zero or non-zero.

if ((damperOn == true) && (damperState != true));

As damperOn and damperState are both booleans this statement is more verbose than it needs to be.

if (damperOn && !damperState)

Is the same thing. It's not wrong to do it the other way and if it's easier for you to read and understand then do it.

One more important note is that semicolon at the end of your statement will keep it from doing anything.

  if ((damperOn == true) && (damperState != true))
  {
    damperState = true;
    digitalWrite(damperOpen, HIGH);
  }

This will work, you need to get rid of the semicolons you used like that.

Great! thanks for the tip about the semicolons Jimmy, I'm sure that would have taken me a while to figure that out.

if (damperOn && !damperState)

damperOn is a great name. It implies that a damper is either on or not on.

damperState is a lousy name. It implies what? Nothing.