Hello,
I have an experimental setup where I am trying to heat an aluminum plate at a controlled and specified rate by applying a silicon heating pad to the bottom of the plate and temperature sensor to the top. Each minute I specify a new set temperature and the heat turns on and off to maintain the aluminum block at that set temperature. The heating occurs in constant temperature, cold water. The heat ramp for the aluminum block starts at 13C and goes to 30C over the course of several hours, but the water it is sitting in is always at 13C.
I tried to use PID control and the PID library to achieve good control in this system, but after at least a week of continuous tuning I was unable to get a suitable ramp when the aluminum plate was immersed in the water (the PID did seem to work well on my desk, however).
So in a desperate move to get this project finished I resorted to a brute force method (see below). This involves calculating the difference between the actual temperature and the set temperature and then turning the heater on for different amounts of time depending on how large the differential is. What I also find is that I need to change how aggressive the heater is as I get to higher temperatures because the aluminum plate temperature can change rapidly when the differential between the aluminum plate temperature and the water it is immersed in are large. In the code below the "aggressiveness" changes above 19C, and again above 25C.
This heater function is run on a timer repeating every 5000 ms. Thus having the heater on for 4000ms (delay(4000)) means it is on for most of each cycle. However, as everyone knows using delays here is really not good, because nothing else in the code can take place during the delay.
All in all this code is not ideal and I was hoping someone with better coding experience could provide me with some pointers for how I might make this shorter, involving no (or at least fewer) delays. I have only included the heater function here, but I can provide the entire code if that seems helpful. Note there is also an indicator LED to show when the heater is on.
Thanks so much for any advice,
Nate
//---------------------------------------------------------
//heater function. Specifies when (at what temperature differential)
//to turn on the heater and for how long to get a consistent ramp
//---------------------------------------------------------
void heater() {
float deltaT = Tset - temp; //define variable calculating temperature differential
float invertDeltaT = temp - Tset; //define an inverse differential
if (Tset < 19) {
if (deltaT < 0.05 && invertDeltaT < 0.1) { //use invert differential to make sure heating continues
digitalWrite(Heater_Relay, HIGH); //even when temp is just above Tset (a little overshoot keeps the mean at
digitalWrite(Heater_LED, HIGH); //closer to Tset)
delay(500);
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
} else if (deltaT >= 0.05 && deltaT < 0.09) {
digitalWrite(Heater_Relay, HIGH);
digitalWrite(Heater_LED, HIGH);
delay(1500);
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
} else if (deltaT >= 0.09 && deltaT < 0.18) {
digitalWrite(Heater_Relay, HIGH);
digitalWrite(Heater_LED, HIGH);
delay(2000);
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
} else if (deltaT >= 0.24) {
digitalWrite(Heater_Relay, HIGH);
digitalWrite(Heater_LED, HIGH);
delay(4000);
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
} else {
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
}
} else if (Tset >= 19 && Tset < 25) { //change parameters at temps above 19 and below 25C
if (deltaT < 0.05 && invertDeltaT < 0.1 ) {
digitalWrite(Heater_Relay, HIGH);
digitalWrite(Heater_LED, HIGH);
delay(1000);
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
} else if (deltaT >= 0.05 && deltaT < 0.18) {
digitalWrite(Heater_Relay, HIGH);
digitalWrite(Heater_LED, HIGH);
delay(2000);
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
} else if (deltaT >= 0.18) {
digitalWrite(Heater_Relay, HIGH);
digitalWrite(Heater_LED, HIGH);
delay(4000);
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
}
} else if (Tset >= 25) { //change parameters again above 25C (make heating more aggressive)
if (deltaT < 0.05 && invertDeltaT < 0.1) {
digitalWrite(Heater_Relay, HIGH);
digitalWrite(Heater_LED, HIGH);
delay(2000);
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
} else if (deltaT >= 0.05) {
digitalWrite(Heater_Relay, HIGH);
digitalWrite(Heater_LED, HIGH);
delay(4000);
digitalWrite(Heater_Relay, LOW);
digitalWrite(Heater_LED, LOW);
}
}
}
//---------------------------------------------------------