Improving Glycol Chiller Code

Hi All,

A few weeks ago I decided to try and turn an old AC unit and immersion heater I had into a glycol chiller - partly because it would be useful for my homebrewing hobby but mostly because it would give me a vested interest in learning to improve my coding skills.

I've hacked away at it for some time and have what I would call a 95% complete code.

I am able to communicate with an ESP 32 and the Arduino IoT Cloud to monitor temperature of both the fermenter (temp1) and the glycol (temp2) I am using a sliding widget to set the desired temperature for temp1 but there are some quirks in the program I have not been able to debug - mainly the compressor/heating/pump delay.

It seems that whenever there is a call for heating, cooling, or pumping the program will turn the relay on for the appropriate circuit but then at the next loop it will turn it off, starting the short cycle delay countdown after the delay the relay will turn on and stay on as desired.

I would greatly appreciate some fresh eyes on the code to point out where this is being commanded.

Also, if there are more efficient ways to code this system, I would love to hear suggestions.

Thanks!

/*
  Sketch generated by the Arduino IoT Cloud Thing
  https://create.arduino.cc/cloud/things/180cb205-21a4-4b99-a011-6addd679374e

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  String status_update; // Update Status to Message Widget for Information and Troubleshooting
  float temp1; // Temperature read by the fermenter probe
  float temp2; // Temperature read by the glycol probe
  int set1; // Desired Temperature of the fermenter probe
  bool cooling; //Lockout of the cooling relay via IoT Widget
  bool heating; //Lockout of the heating relay via IoT Widget
  bool mix; //Lockout of the mix relay via IoT Widget
  bool pump; //Lockout of the pump relay via IoT Widget

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.

TL:DR

Description:

The connected device monitors temperature of a remote vessle (fermenter) as well as the working fluid vessle (glycol)
By heating or cooling the working fluid vessle and then pumping this fluid through a heat exchanger in the remote vessle the temperature can be controlled.
There is an additional aggitator (mix) within the glycol vessel to help maintain an accurate and uniform temperature within the glycol.
The temperature of the working fluid vessle is recorded to prevent over heating/cooling of the working fluid

Pseudocode:

1. Read Temperatures of glycol and fermenter

2. Take current time reading to compare against delays

3. Evaluate if the heating conditions are all met
If so: Turn it on 
If not: Keep it off

4. Evaluate if the cooling conditions are all met
If so: Turn it on 
If not: Keep it off

5. Evaluate if the pump conditions are all met
If so: Turn it on 
If not: Keep it off

6. Evaluate if the mix conditions are all met
If so: Turn it on 
If not: Keep it off

Repeat


*/


#include "thingProperties.h" // IoT Program
#include <OneWire.h> // Temperature Probe Program
#include <DallasTemperature.h> // Temperature Probe Program

//temp1 is the variable for Measured Fermentation Temperature in F
//temp2 is the variable for Measured Coolant Temperature in F

#define ONE_WIRE_BUS 13        // Temperature probes connected to GPIO13
#define heating_relay 12       // Relay Signal Pin connected to GPIO12
#define cooling_relay 14       // Relay Signal Pin connected to GPIO14
#define pump_relay 27          // Relay Signal Pin connected to GPIO27
#define mix_relay 26           // Relay Signal Pin connected to GPIO26

int min_coolant = 32;       // Keep the glycol from freezing by not allowing it to get colder than 32F
int max_coolant = 100;      // Keep the glycol from overheating by not allowing it to get hotter than 100F
int deadzone = 2.5;         // Temperature buffer to keep hysteysis lower while maintaining somewhat consistent temperature 
int set_temp = 62;          // Default temperature if there is no input from IoT

bool last_heat_state = HIGH; //Initialize the last stored heating state to OFF
bool last_cool_state = HIGH; //Initialize the last stored heating state to OFF
bool last_pump_state = HIGH; //Initialize the last stored heating state to OFF

bool demand_heat; // Variable to determine if the heat should be turned on
bool demand_cool; // Variable to determine if the cooling should be turned on
bool demand_pump; // Variable to determine if the pump should be turned on
bool demand_mix; // Variable to determine if the agitation should be turned on

// All below conditions must be met to turn heating on
bool Heat_Condition1;
bool Heat_Condition2;
bool Heat_Condition3;
bool Heat_Condition4;
bool Heat_Condition5;
bool Heat_Condition6;

// All below conditions must be met to turn cooling on
bool Cool_Condition1;
bool Cool_Condition2;
bool Cool_Condition3;
bool Cool_Condition4;
bool Cool_Condition5;

// All below conditions must be met to turn pump on
bool Pump_Condition1;
bool Pump_Condition2;
bool Pump_Condition3;
bool Pump_Condition4;

// All below conditions must be met to turn the agitator on
bool Mix_Condition1;
bool Mix_Condition2;
bool Mix_Condition3;


unsigned long Current_Time = 0;  // Intitialize current timer as 0

unsigned long Cooling_Last_Off = 0; // Initialize component to be last off at startup
unsigned long Cooling_Last_On = 0; // Initialize component to be last on at startup


unsigned long Heating_Last_Off = 0;// Initialize component to be last off at startup
unsigned long Heating_Last_On = 0; // Initialize component to be last on at startup

unsigned long Pump_Last_Off=0;// Initialize component to be last off at startup

unsigned long Cooling_Delay = 10 * 60 * 1000; // Make sure Cooling has been off for 10 min before starting again
unsigned long Heating_Delay = 2 * 60 * 1000;  // Make sure Heating has been off for 10 min before starting again
unsigned long Pump_Delay = 2 * 60 * 1000;     // Make sure Pump has been off for 10 min before starting again
unsigned long Mix_Delay = 2 * 60 * 1000;      // Make sure Mix has been off for 10 min before starting again

signed long Cooling_Off_Time = 0; // Initialize the Off Time at startup
signed long Cooling_On_Time = 0; // Initialize the On Time at startup

signed long Heating_Off_Time = 0; // Initialize the Off Time at startup
signed long Heating_On_Time = 0; // Initialize the On Time at startup

signed long Pump_Off_Time = 0; // Initialize the Off Time at startup

// Initialize all state variables for troubleshooting to off
String cool_state = "OFF"; 
String heat_state = "OFF";
String pump_state = "OFF";
String mix_state = "OFF";

String mode = "Starting Up"; // Intialize the status update variable

// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);

// Pass oneWire reference to DallasTemperature library
DallasTemperature sensors(&oneWire);

void setup() {
  //Declare Relays as OUTPUTS
  pinMode(heating_relay, OUTPUT);
  pinMode(cooling_relay, OUTPUT);
  pinMode(pump_relay, OUTPUT);
  pinMode(mix_relay, OUTPUT);
  
  //Initialize all relays to "OFF"
  digitalWrite(heating_relay, HIGH);
  digitalWrite(cooling_relay, HIGH);
  digitalWrite(pump_relay, HIGH);
  digitalWrite(mix_relay, HIGH);
  
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  
  // Defined in thingProperties.h
  initProperties();
  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
  Serial.println(mode);
}

void loop()
{
//RETRIEVE CURRENT VALUES FOR TEMPS AND TIME FOR NEXT LOOP
  ArduinoCloud.update();
  sensors.requestTemperatures();     //Return Temperatures
  temp1 = round(sensors.getTempFByIndex(0)); //Fermenter Temperature
  temp2 = round(sensors.getTempFByIndex(1)); // Coolant Temperature
  Current_Time = millis();          // Clock Update
//_________________________________________________________________________________________________________________

//TIMER SETUP FOR HEATING, COOLING AND PUMP DELAY

  // Evaluate how long the cooling relay has been off
  if (digitalRead(cooling_relay) == HIGH && last_cool_state != digitalRead(cooling_relay)) // If the Cooling Relay is OFF and it wasn't just OFF
  {
    Cooling_Last_Off = millis(); // The Current Timestamp is the moment after the Cooling was last OFF
    last_cool_state = digitalRead(cooling_relay); //Reset the state to match
  }

  // Evaluate how long the cooling relay has been on
  if (digitalRead(cooling_relay) == LOW && last_cool_state != digitalRead(cooling_relay))// If the Heating Relay is ON and it wasn't just ON
  {
    Cooling_Last_On = millis(); // The Current Timestamp is the moment after the Cooling was last ON
    last_cool_state = digitalRead(cooling_relay); //Reset the state to match
  }

  // Evaluate how long the heating relay has been off
  if (digitalRead(heating_relay) == HIGH && last_heat_state != digitalRead(heating_relay))// If the Heating Relay is OFF and it wasn't just OF
  {
    Heating_Last_Off = millis(); // The Current Timestamp is the moment after the Heating was last OFF
    last_heat_state = digitalRead(heating_relay); //Reset the state to match
  }
 
  // Evaluate how long the heating relay has been on
  if (digitalRead(heating_relay) == LOW && last_heat_state != digitalRead(heating_relay))// If the Heating Relay is ON and it wasn't just ON
  {
    Heating_Last_On = millis(); // The Current Timestamp is the moment after the Heating was last ON
    last_heat_state = digitalRead(heating_relay); //Reset the state to match
  }
  
  
 // Evaluate how long the pump relay has been off
  if (digitalRead(pump_relay) == HIGH && last_pump_state != digitalRead(pump_relay))// If the Pump Relay is OFF and it wasn't just OF
  {
    Pump_Last_Off = millis(); // The Current Timestamp is the moment after the Heating was last OFF
    last_pump_state = digitalRead(pump_relay); //Reset the state to match
  }
  
  // Evaluate how long the pump relay has been on
  if (digitalRead(pump_relay) == LOW && last_pump_state != digitalRead(pump_relay))// If the Pump Relay is ON and it wasn't just ON
  {
    last_pump_state = digitalRead(pump_relay); //Reset the state to match
  }

//___________________________________________________________________________________________________________

//OPERATING CONDITIONS

//___________________________________________________________________________________________________________
//HEATING REQUIREMENTS : THE HEATING SHOULD TURN ON IF ALL OF THESE ARE YES/TURE/HIGH/1

  Heat_Condition1 = temp1 > min_coolant && temp2 > min_coolant; // Are both temperatures warmer than minimum allowable temp? (An unplugged temp probe will default to -197F)
  Heat_Condition2 = Current_Time >= Heating_Delay; // Has the ESP been on longer than the set Heating delay?
  Heat_Condition3 = temp1 <= (set_temp - deadzone); // Is the Fermenter Temperature lower than or equal to the set temperatur minus the deadzone buffer?
  Heat_Condition4 = temp2 < max_coolant; // Is the temperature of the glycol lower than the maximum allowed?
  
  // Check if heating delay has been met
  if (digitalRead(heating_relay) == LOW) // If the heat is on
  {
    Heat_Condition5 = 1;                          //Keep it On
  }
  else if ((digitalRead(heating_relay) == HIGH))  //If heat is off
  {
    Heat_Condition5 = Heating_Off_Time >= Heating_Delay; // Turn it on only IF it has been off longer than the Heating Delay
  }
  
  Heat_Condition6 = heating; //Check the IoT lockout input if heating is allowed

//___________________________________________________________________________________________________________________________
//COOLING REQUIREMENTS : THE COOLING SHOULD TURN ON IF ALL OF THESE ARE YES/TURE/HIGH/1

  Cool_Condition1 = Current_Time >= Cooling_Delay; // Has the ESP been on longer than the set Cooling delay?
  Cool_Condition2 = temp1 >= (set_temp + deadzone); // Is the Fermenter Temperature higher than or equal to the set temperatur plus the deadzone buffer?
  Cool_Condition3 = temp2 > min_coolant; // Is the glycol warmer than the minimum allowable temperature?
  
  // Condition to check if cooling delay has been met
  if (digitalRead(cooling_relay) == LOW) //If the cooling relay is on
  {
    Cool_Condition4 = 1; // Keep it on
  }
  else if ((digitalRead(cooling_relay) == HIGH)) // If the cooling relay is off
  {
    Cool_Condition4 = Cooling_Off_Time >= Cooling_Delay; // Turn it on only IF it has been off longer than the Cooling Delay
  }
  
  Cool_Condition5 = cooling; //Check the IoT lockout input if cooling is allowed
  
//_____________________________________________________________________________________________________________
// PUMP REQUIREMENTS : THE PUMP SHOULD TURN ON IF ALL OF THESE ARE YES/TURE/HIGH/1

  Pump_Condition1 = (abs(temp1 - set_temp) > (deadzone * 0.25) ); // If the fermenter temperature is more than 75% of the deadzone buffer away from the nominal desired temperature
  Pump_Condition2 = (set_temp > temp2 > temp1) || (set_temp < temp2 < temp1) || (temp2 > set_temp > temp1) || (temp2 < set_temp < temp1); // Conditions to make sure the glycol will only pump if it is closer to the set temperature than the fermenter is.
  
  // Condition to check if Pump Delay has been met
  if (digitalRead(pump_relay) == LOW) // If the pump is already on
  {
    Pump_Condition3= 1;                          // Keep it On
  }
  else if ((digitalRead(pump_relay) == HIGH))  //If pump is off
  {
    Pump_Condition3 = Pump_Off_Time >= Pump_Delay; // Turn it on If it has been off longer than the Pump Delay
  }
  
  Pump_Condition4 = pump; //Check the IoT lockout input if the pump is allowed
  
//_________________________________________________________________________________________________________________
// MIX REQUIREMENTS  : THE MIX SHOULD TURN ON IF ALL OF THESE ARE YES/TURE/HIGH/1
  
  Mix_Condition1 = (Heating_Off_Time < Mix_Delay) || (Cooling_Off_Time < Mix_Delay); // Has the heating or cooling been on within the last 2 min? (Mix Delay Set Time)
  Mix_Condition2 = Current_Time > Mix_Delay; // Has the ESP32 been on longer than the Mix Delay?
  Mix_Condition3 = mix; //Check the IoT lockout input if the mix is allowed



// If all the respective conditions are Yes/True/High/1 - Rewrite the demand variable to High/True/1

  demand_heat = (Heat_Condition1 && Heat_Condition2 && Heat_Condition3 && Heat_Condition4 && Heat_Condition5 && Heat_Condition6);
  demand_cool = (Cool_Condition1 && Cool_Condition2 && Cool_Condition3 && Cool_Condition4 && Cool_Condition5);
  demand_pump = (Pump_Condition1 && Pump_Condition2 && Pump_Condition3 && Pump_Condition4);
  demand_mix = (Mix_Condition1 && Mix_Condition2 && Mix_Condition3);

  Serial.println((String)"Demand_Heat:" + demand_heat + " Demand_Cool:" + demand_cool + " Demand_Pump:" + demand_pump + " Demand_Mix:" + demand_mix);

  // Conditions are met to Turn Heat On
  if (demand_heat == 1)
  {
    digitalWrite(heating_relay, LOW); // Turn Heating Relay ON
    heat_state = "ON"; // Declare the Heating Relay ON
    Heating_On_Time = Current_Time - Heating_Last_On; // Update the Timestamp that the Heating Relay was recently turned ON
    Heating_Off_Time = 0; // Continually reset the Timestamp that the Heating Relay in no longer OFF
  }
  else if (demand_heat == 0)
  {
    digitalWrite(heating_relay, HIGH); // Turn Heating Relay ON
    heat_state = "OFF"; // Declare the Heating Relay OFF
    Heating_Off_Time = Current_Time - Heating_Last_Off; // Update the Timestamp that the Heating Relay was recently turned OFF
    Heating_On_Time = 0; // Continually reset the Timestamp that the Heating Relay in no longer ON
  }

  // Conditions are met to Turn Cooling On
  if (demand_cool == 1)
  {
    digitalWrite(cooling_relay, LOW);
    cool_state = "ON";
    Cooling_On_Time = Current_Time - Cooling_Last_On;
    Cooling_Off_Time = 0;
  }
  else if (demand_cool == 0)
  {
    digitalWrite(cooling_relay, HIGH);
    cool_state = "OFF";
    Cooling_Off_Time = Current_Time - Cooling_Last_Off;
    Cooling_On_Time = 0;
  }

  // Conditions to Turn Pump On
  if (demand_pump == 1)
  {
    digitalWrite(pump_relay, LOW);
    pump_state = "ON";
    Pump_Off_Time=0;
  }
  else if (demand_pump == 0)
  {
    digitalWrite(pump_relay, HIGH);
    pump_state = "OFF";
    Pump_Off_Time = Current_Time - Pump_Last_Off;
  }

  // Conditions to Turn Mix
  if (demand_mix == 1)
  {
    digitalWrite(mix_relay, LOW);
    mix_state = "ON";
  }
  else if (demand_mix == 0)
  {
    digitalWrite(mix_relay, HIGH);
    mix_state = "OFF";
  }
  //_____________________________________________________________________________________________________________
  //Report Status and Pause Before Repeating Code
  if (((Current_Time <= Cooling_Delay) || (Current_Time <= Heating_Delay)) && digitalRead(pump_relay) == HIGH && digitalRead(mix_relay) == HIGH)
  {
    if (Heat_Condition2 && Heat_Condition3 && Heat_Condition4 == 1)
    {
      mode = ((String)"START UP DELAY - HEATER ON IN: " + (Heating_Delay - Current_Time) / 1000 + " Seconds");
    }
    else if (Cool_Condition2 && Cool_Condition3 == 1)
    {
      mode = ((String)"START UP DELAY - COOLER ON IN: " + (Cooling_Delay - Current_Time) / 1000 + " Seconds");
    }

  }
  if (temp1 <= 0 || temp2 <= 0)
  {
    mode = ((String)"THERMOCOUPLES NOT FOUND! :");
  }
  if (digitalRead(heating_relay) == LOW && digitalRead(pump_relay) == LOW && digitalRead(mix_relay) == LOW && digitalRead(cooling_relay) == HIGH)
  {
    mode = ((String)"ACTIVE HEATING: ");
  }
  if (digitalRead(cooling_relay) == LOW && digitalRead(pump_relay) == LOW && digitalRead(mix_relay) == LOW && digitalRead(heating_relay) == HIGH)
  {
    mode = ((String)"ACTIVE COOLING: ");
  }
  if (temp1 > set_temp && digitalRead(pump_relay) == LOW && digitalRead(heating_relay)==HIGH && digitalRead(cooling_relay) == HIGH)
  {
    if (Cool_Condition1 && Cool_Condition2 && Cool_Condition3 == 1)
    {
      mode = ((String)"SHORT CYCLE COOLING DELAY: PASSIVE COOLING INSTEAD  - COOLER ON IN: " + (Cooling_Delay - (Current_Time-Cooling_Last_Off)) / 1000 + " Seconds");
    }
    else
    {
      mode = ((String)"PASSIVE COOLING: ");
    }
  }
  if (temp1 < set_temp && digitalRead(pump_relay) == LOW && digitalRead(heating_relay)==HIGH && digitalRead(cooling_relay) == HIGH)
  {
    if (Heat_Condition1 && Heat_Condition2 && Heat_Condition3 && Heat_Condition4 == 1)
    {
      mode = ((String)"SHORT CYCLE HEATING DELAY: PASSIVE HEATING INSTEAD  - HEATER ON IN: " + (Heating_Delay - (Current_Time-Heating_Last_Off)) / 1000 + " Seconds");
    }
    else
    {
      mode = ((String)"PASSIVE HEATING: ");
    }
  }
  if (digitalRead(cooling_relay) == LOW && digitalRead(pump_relay) == HIGH)
  {
    mode = ((String)"CHILLING COOLANT: ");
  }
  if (digitalRead(heating_relay) == LOW && digitalRead(pump_relay) == HIGH)
  {
    mode = ((String)"HEATING COOLANT: ");
  }
  if (digitalRead(heating_relay) == HIGH && digitalRead(cooling_relay) == HIGH && digitalRead(pump_relay) == HIGH && abs(set_temp - temp1) <= deadzone)
  {
    mode = ((String)"TARGET TEMPERATURE REACHED - STANDBY: ");
  }
  else
  {
  status_update = ((String)mode + "Heating:" + heat_state + "/" + heating + " Cooling:" + cool_state + "/" + cooling + " Pump:" + pump_state + "/" + pump + " Agitation:" + mix_state + "/" + mix);
  mode=((String)status_update); 
  }
  delay(500); // 10 Second Update Delay
}

// State Change Actions
void onSet1Change()  {
  if (temp1>set_temp)
  {
  set_temp= set1-(0.75*deadzone);
  }
  else if (temp1<set_temp)
  {
  set_temp= set1+(0.75*deadzone);  
  }
  else
  {
  set_temp=set1;
  }
  
}
void onCoolingChange()
{
  if (digitalRead(cooling)==0)
  {
  mode=((String)"COOLING DISABLED");
  }
  else
  {
  mode=((String)"COOLING ENABLED"); 
  }
}
void onHeatingChange()
{
  if (digitalRead(heating)==0)
  {
  mode=((String)"HEATING DISABLED");
  }
  else
  {
  mode=((String)"HEATING ENABLED"); 
  } 
}
void onPumpChange()
{
  if (digitalRead(pump)==0)
  {
  mode=((String)"PUMP DISABLED");
  }
  else
  {
  mode=((String)"PUMP ENABLED"); 
  }
}
void onMixChange()
{
  if (digitalRead(mix)==0)
  {
  mode=((String)"COOLING DISABLED");
  }
  else
  {
  mode=((String)"COOLING ENABLED"); 
  }
}

Nope.

1 Like

Any time you find yourself making variables with the same name except for a number at the end, you probably need to be using an array.

Without the array, you are forced to copy + paste the same (almost) code multiple times for each variable. With an array, you can avoid all that repeated code, by using a loop to perform the same code for each element of the array.

Your code above becomes

bool Heat_Condition[6];
1 Like

Hi,
What I'm going to report has nothing to do with arduino, but I report it because it's a question of danger.
If it is not relevant, I ask a moderator to delete the post.
I will understand.

Be very careful with the handling of Glycol in refrigeration in brewing.
A glycol leak in a brewery here in Brazil caused many deaths from poisoning in consumers who drank the contaminated beer.

I know the news is in Portuguese, but nothing like a "translate to English" to help.

Glycol = diethylene glycol

"https://g1.globo.com/ciencia-e-saude/noticia/2020/01/09/entenda-o-que-e-o-diethyleneglicol-substancia-encontrada-em-cerveja-de-belo-horizonte.ghtml

I have worked with chillers in and around food processing and similar things. I used Propylene glycol, not the cheapest but life is important. Note is considerably less toxic than ethylene glycol. It is possible it could actually be labelled 'non-toxic'. It is generally in food processing systems where accidental ingestion could happen.

Good Catch! I had it at 3 and in debugging I played around with it and must have forgot what int meant.

I appreciate the concern! I am using the non toxic form of glycol that is used for this purpose and have taken some additional precautions to avoid any connections over or within the fermenter - all single piece stainless tubing until it is over the floor - also will keep an eye on any corrosion.

I never knew that you could compress variables this way! I like it. Thanks!

One of the conditions that caused the relay to turn on, must no longer be true on the next loop. I suggest you add some debug code to determine which one. Something like...

  demand_heat = (Heat_Condition1 && Heat_Condition2 && Heat_Condition3 && Heat_Condition4 && Heat_Condition5 && Heat_Condition6);

  Serial.println("demand_heat debug");
  Serial.println(Heat_Condition1);
  Serial.println(Heat_Condition2);
  Serial.println(Heat_Condition3);
  Serial.println(Heat_Condition4);
  Serial.println(Heat_Condition5);
  Serial.println(Heat_Condition6);

Hi!

There's many warnings in your code.

Maybe it can be the root of your problems.

src/main.cpp: In function 'void loop()':
src/main.cpp:259:40: warning: comparison of integer expressions of different signedness: 'long int' and 'long unsigned int' [-Wsign-compare]
  259 |     Heat_Condition5 = Heating_Off_Time >= Heating_Delay; // Turn it on only IF it has been off longer than the Heating Delay
      |                       ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
src/main.cpp:278:40: warning: comparison of integer expressions of different signedness: 'long int' and 'long unsigned int' [-Wsign-compare]
  278 |     Cool_Condition4 = Cooling_Off_Time >= Cooling_Delay; // Turn it on only IF it has been off longer than the Cooling Delay
      |                       ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
src/main.cpp:287:31: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
  287 |   Pump_Condition2 = (set_temp > temp2 > temp1) || (set_temp < temp2 < temp1) || (temp2 > set_temp > temp1) || (temp2 < set_temp < temp1); // Conditions to make sure the glycol will only pump if it is closer to the set temperature than the fermenter is.
      |                      ~~~~~~~~~^~~~~~~
src/main.cpp:287:61: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
  287 |   Pump_Condition2 = (set_temp > temp2 > temp1) || (set_temp < temp2 < temp1) || (temp2 > set_temp > temp1) || (temp2 < set_temp < temp1); // Conditions to make sure the glycol will only pump if it is closer to the set temperature than the fermenter is.
      |                                                    ~~~~~~~~~^~~~~~~
src/main.cpp:287:88: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
  287 |   Pump_Condition2 = (set_temp > temp2 > temp1) || (set_temp < temp2 < temp1) || (temp2 > set_temp > temp1) || (temp2 < set_temp < temp1); // Conditions to make sure the glycol will only pump if it is closer to the set temperature than the fermenter is.
      |                                                                                  ~~~~~~^~~~~~~~~~
src/main.cpp:287:118: warning: comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
  287 |   Pump_Condition2 = (set_temp > temp2 > temp1) || (set_temp < temp2 < temp1) || (temp2 > set_temp > temp1) || (temp2 < set_temp < temp1); // Conditions to make sure the glycol will only pump if it is closer to the set temperature than the fermenter is.
      |                                                                                                                ~~~~~~^~~~~~~~~~
src/main.cpp:296:37: warning: comparison of integer expressions of different signedness: 'long int' and 'long unsigned int' [-Wsign-compare]
  296 |     Pump_Condition3 = Pump_Off_Time >= Pump_Delay; // Turn it on If it has been off longer than the Pump Delay
      |                       ~~~~~~~~~~~~~~^~~~~~~~~~~~~
src/main.cpp:304:38: warning: comparison of integer expressions of different signedness: 'long int' and 'long unsigned int' [-Wsign-compare]
  304 |   Mix_Condition1 = (Heating_Off_Time < Mix_Delay) || (Cooling_Off_Time < Mix_Delay); // Has the heating or cooling been on within the last 2 min? (Mix Delay Set Time)
      |                     ~~~~~~~~~~~~~~~~~^~~~~~~~~~~
src/main.cpp:304:72: warning: comparison of integer expressions of different signedness: 'long int' and 'long unsigned int' [-Wsign-compare]
  304 |   Mix_Condition1 = (Heating_Off_Time < Mix_Delay) || (Cooling_Off_Time < Mix_Delay); // Has the heating or cooling been on within the last 2 min? (Mix Delay Set Time)

Also I can see some waste of memory on code. There's many variables used only on loop but are declared as global.

For example:

//Global
bool Heat_Condition1;

void loop()
{
  Heat_Condition1 = temp1 > min_coolant && temp2 > min_coolant;
}

It could be:

void loop()
{
  bool Heat_Condition1 = temp1 > min_coolant && temp2 > min_coolant;
}

I never knew that you could compress variables this way! I like it. Thanks!

In this case you could use bit manipulation to use 1 byte of memory instead 8.

For example:

bool Heat_Condition1;
bool Heat_Condition2;
bool Heat_Condition3;
bool Heat_Condition4;

void loop()
{
  Heat_Condition1 = temp1 > min_coolant && temp2 > min_coolant; 
  Heat_Condition2 = Current_Time >= Heating_Delay;
  Heat_Condition3 = temp1 <= (set_temp - deadzone);
  Heat_Condition4 = temp2 < max_coolant; 
}

Could become:

// Global
byte Heat_Condition = 0;

void loop()
{
  bitWrite(Heat_Condition, 0, temp1 > min_coolant && temp2 > min_coolant);
  bitWrite(Heat_Condition, 1, Current_Time >= Heating_Delay);
  bitWrite(Heat_Condition, 2, temp1 <= (set_temp - deadzone));
  bitWrite(Heat_Condition, 3, temp1 > temp2 < max_coolant);
}

Then use in this way:

if(bitRead(Heat_Condition, 0) == true) // Heat_Condition1
{
}

if(bitRead(Heat_Condition, 1) == true) // Heat_Condition2
{
}

if(bitRead(Heat_Condition, 2) == true) // Heat_Condition3
{
}

if(bitRead(Heat_Condition, 3) == true) // Heat_Condition4
{
}

I would like to ask if there's some advantage to use this approach:

void loop()
{
  bool Heat_Condition1 = temp1 > min_coolant && temp2 > min_coolant;

  if(Heat_Condition1)
  {
  }
}

Instead:

void loop()
{
  if((temp1 > min_coolant) && (temp2 > min_coolant))
  {
  }
}

Best regards.

Thanks for the in-depth review Fernando! I appreciate learning all of the different ways to improve code.

The reason I created simple variables was to help check where errors would be when debugging, once I get the issue resolved I intend to optimize the coding as best as I am able.

Thanks again!

Hint to save a lot of grief when the compressor is on leave it on for at least 6 minutes and the same for off. If you short cycle it you will short life it as well. If it is to long of an on time and if you have the skill set add hot gas bypass, this takes some of the liquid refrigerant and passes it directly into the suction side of the compressor. With that you may be able to leave the compressor keep running. You need to be very cognizant of the refrigeration pressures and temperature.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.