Temperature control system

[From Bill Powers (960124.2345 MST)]

Remi Cote 012196.1050 --

     The only way to model a thermostat with stella is to use an if-then
     (I discovered that 10 minutes ago).

     If I want to heat a room at 20 degree and the heater is heating at
     the rate of 1 degree a minute and the room is cooling at the rate
     of 0.3 degree a minute, and if I want to maintain the temperature
     around 20 degree, I have to command the heater to eat if the
     temperature is below 20 degree, or else not to heat. I guess
     that's the way our own body thermostat work with metabolism, and or
     glucoreceptor with insulin.

Congratulations! You actually have a simulation running. I think you can
make it work like a continuous control system with just a little more
design effort.

I don't know the details of Stella, but apparently you have simulated a
heater that puts some flow of heat into the environment, an environment
that rises in temperature as the heat flow continues or cools off if it
stops, and a sensor that detects the temperature. You also have defined
a reference temperature and are comparing the sensed temperature with
it. That's most of what you need.

To get a continuous control system, you need to change the if-then
comparator to a continuous comparator.

Let T represent the actual temperature, and T' represent the reference
temperature. If these two quantities are fed into a weighted summation,
the output should be the error signal, e = T' - T. If this output is
then made into the input of the heater, the rate of heat flow will vary
continuously with the error signal. In other words, you want the room to
heat at "e" degrees a minute instead of a fixed 1 degree a minute. In
other words, instead of saying

if T < T' then heat output = 1 else heat output = 0,

you say

heat output = 0.1 * (T' - T)

To be realistic, you will want to put a limit on heat output so it can't
go less than zero:

if heat output < 0 then heat output = 0.

This system will bring the temperature T to the value T'. You can make
T' adjustable -- T' determines the set point or reference level of the
control system. If you change T' while the simulation is running, the
actual temperature will soon change to T'.

You can also vary the rate of cooling while the simulation is running.
If you increase or decrease the rate of cooling, the heat output will
quickly rise or fall to counteract the change, and the temperature will
hardly change at all.

Schematically, the setup you want is this (not in Stella notation, but
perhaps you can translate):

                                T' reference temperature
           actual |
         temperature + v error
            T -------------->Subtractor -> (e = T' - T) ->-
            ^ - |
            > v
            > amplifier
            > + |
             ----<---- Integrator <------------------------
                                 ^ - output heat = 0.1*e
                                 >
                rate of cooling--

This is the kind of temperature control that is used when very smooth
and close control is required. The human body uses this sort of
continuous temperature control rather than the on-off kind you get with
your if-then comparator.

Let me know how this works out.

···

----------------------------------------------------------------------
Best,

Bill P.

[from Gary Cziko 960125.1420 GMT]

Bill Powers (960124.2345 MST) responding to Remi Cote:

you want the room to
heat at "e" degrees a minute instead of a fixed 1 degree a minute.

Shouldn't you be specifying the OUTPUT function. How can you have a heater
put out 1 (or any specified) degrees per minute without assuming already
that it is controlling its input (rate of perceived temperature change).
Instead shouldn't you be talking about a heat OUTPUT like calories or BTUs?

--Gary

Remi Cote 012596.0945

I tried to simulate the system suggested by Bill and here is the result.

I think I made a mistake. I need detective here:

output of eat = 0.1 * (T'-T) If (T'-T) > 0
thermostat set to 20 degree
Initial room temp was 0
cooling was set to 0.3 by dt
Here are the run:
01) 0.1*(20-0) - cooling of 0.3 = 1.7 of eat output
2) 3.23 = 0.1*(20-1.7)=1.83 + 1.7 = 3.53 - cooling 0.3 = 3.23
3) 4.61
and the rest, 5.85, 6.96, 7.97, 8.87, 9.68, 10.41, 11.07, 11.67, 12.20, 12.68,
13.11, 13.50, 13.85, 14.10, 14.45, 14.70, 14.93, 15.14, 15.33, 15.49, 15.64,
15.78, 15.90, 16.01, 16.11, 16.20, 16.28, 16.42, 16.47, 16.53, 16.62, 16.69,
16.72, 16.75, 16.77
it is an asymptote heading to 17... not 20 degree.

I think I made a mistake but don't know what.

REMI

<[Bill Leach 960125.23:44 U.S. Eastern Time Zone]

Remi Cote 012596.0945

Unfortunately, I am completely ignorant of Stella (though I think that it
is one of the "flow chart" type programming languages that have become so
popular as "multimedia program languages").

I suspect however, from your "symptom" that your problem is probably that
you are somehow subtracting 10 times your cooling factor prior to
displaying the "current temperature".

···

------
I see from one of Bill's posting that he suspects a different problem but
from you post of 1926 hours, I believe that you are confirming my guess.

Again, I don't not know the formula or program that you are using but
suspect that is yet very realistic.

For example, the thermal transfer rate in an actual system is _always_ a
function of "delta-T". That is, the greater the temperature difference
between the two regions, objects or systems, then the greater the heat
transfer rate.

This applies to both the "heater" portion of your simulation as well as
to the "heat loss" portion.

Thus, for a simulation to have characteristics similar to a real system,
it is necessary for you to use a heat loss "factor" that is related to
the the temperature of the object whose temperature is being controlled.
So that if at 10 degrees the heat loss rate was .3 calorie/second, then
at 15 degrees the rate might be .6 calories/second, 20 degrees 1.2
calories/second... etc.

A similar situation exists for the heater portion of the system. The
thermal energy transfer rate between the heater and the thing being
heated is again a function of the temperature difference between the two.

For the parameters that you have in your present simulation the changes
in thermal transfer rates between the heater and the object being heated
would be necessary for an accurate run however, normally the changes in
the thermal transfer rate from the heater can be ignored. That is, the
difference between the maximum rate and the minimum rate are small
compared to the average rate (usually the temperature of the actually
heating element is >> than the controlled value and because of the
physical characteristics of the system, the temperature of the heating
element increases if thermal energy transfer rate decreases which is a
negative feedback equilibrium system tending to stablize the maximum
transfer rate).

Bill's suggesting to use thermal energy units for the "heat input" as a
function of the operation of the heater is a very good one (particularly
for a simple system).

The heat loss rate however must be based upon thermal energy difference
(temperature difference) for the simulation to even begin to behave in a
fashion similar to a real system.

In any such system as you are trying to model, there is a unique
"equilibrium temperature" for any specific "heat input" value.

In a practical temperature control system, the "thermal capacity"
(maximum heat input capability of the heater) must at least exceed the
maximum possible heat loss rate at the maximum temperature at which
control may be desired. This is the condition that I believe that Bill
Powers thought that you are not meeting (which may or may not be correct
as far as I know -- but in any event is not specifically what I think is
wrong with your model as it is currently running).

-----------
Going back and trying to understand your posting... and I am becoming
even more confused -- not necessarily an unusual state for me! :slight_smile:

It looks as though you are setting the "heat input" rate at .1 * delta-T
minus .3 (and then maybe subtracting the .3 again for each calculation).

Playing around with another programming language, I believe that the
formula that you are using is equivalent to:

setpoint=20
heatfactor=0.1
coolfactor=0.3
temperature(0)=0
deltaT = setpoint - temperature(n-1)

temperature(n)=heatfactor * deltaT - coolfactor + temperature(n-1)

At least with this formula, I obtained the same results as you posted.

The problem then, I think, is that this formula with the parameters use
can not work as a control system. The heat input (essentially system
gain is too low). Additionally, in my opinion, making the heat input
capacity so greatly dependent upon the controlled temperature is
unrealistic.

A sample run of the program (using the parameter given in the program):

R(10);01.716 7:00PM> simpletempcontrol

Run Temp Heat | Run Temp Heat | Run Temp Heat | Run Temp Heat
-------------------------------------------------------------------------
01 = 9.60 ON | 02 = 13.11 ON | 03 = 16.55 ON | 04 = 19.92 ON
05 = 23.22 OFF | 06 = 22.69 OFF | 07 = 22.16 OFF | 08 = 21.64 OFF
09 = 21.12 OFF | 10 = 20.61 OFF | 11 = 20.10 OFF | 12 = 19.60 ON
13 = 22.91 OFF | 14 = 22.38 OFF | 15 = 21.86 OFF | 16 = 21.34 OFF
17 = 20.83 OFF | 18 = 20.32 OFF | 19 = 19.82 ON | 20 = 23.12 OFF
21 = 22.59 OFF | 22 = 22.07 OFF | 23 = 21.55 OFF | 24 = 21.04 OFF
25 = 20.53 OFF | 26 = 20.03 OFF | 27 = 19.53 ON | 28 = 22.84 OFF
29 = 22.31 OFF | 30 = 21.79 OFF | 31 = 21.27 OFF | 32 = 20.76 OFF
33 = 20.25 OFF | 34 = 19.75 ON | 35 = 23.06 OFF | 36 = 22.53 OFF
37 = 22.01 OFF | 38 = 21.49 OFF | 39 = 20.98 OFF | 40 = 20.47 OFF

R(10);01.783 7:00PM>

This is written in Rexx but is probably readable by most people as the
syntax is not complex.

------------snip snip snip = 22.59 OFF | 22 = 22.07 OFF | 23 = 21.55 OFF | 24 = 21.04 OFF
25 = 20.53 OFF | 26 = 20.03 OFF | 27 = 19.53 ON | 28 = 22.84 OFF
29 = 22.31 OFF | 30 = 21.79 OFF | 31 = 21.27 OFF | 32 = 20.76 OFF
33 = 20.25 OFF | 34 = 19.75 ON | 35 = 23.06 OFF | 36 = 22.53 OFF
37 = 22.01 OFF | 38 = 21.49 OFF | 39 = 20.98 OFF | 40 = 20.47 OFF

R(10);01.783 7:00PM>

This is written in Rexx but is probably readable by most people as the
syntax is not complex.

------------snip snip snip --------------
   /* Initial conditions and parameters: */
NUMERIC DIGITS 4 /* Display reasonable precision numbers */
HEAT='OFF' /* Set the initial condition for the heater (flag) */
setpoint=20 /* This is the Control setpoint -- REFERENCE */
temp=10 /* This is the initial temperature */
inputtemp=400 /* This is the assumed temp of heater unit when on */
heatinput=0 /* Gain_deltaT * thermfactor; 0 until heater on */
sinktemp = -30 /* This is the assumed temp of sink for heat loss */
  /* heatloss= Loss_deltaT * thermfactor */
thermfactor=.01 /* arbitrarily picked thermal transfer efficiency */
run=0 /* used to help format output display */
iterations=10 /* number of iteration to run */

/* Make a display header: */
say " " /* Output an initial blank line */
say "Run Temp Heat | Run Temp Heat | Run Temp Heat | Run Temp Heat"
say "-------------------------------------------------------------------------"

do iterations /* One full row for each iteration */
do i = 1 to 4 /* Make nice columns for display */
     /* Do calculations and store in column */
run=run + 1 /* Increment the interation counter (for display) */

   /* To make the display line up, add a zero if the iteration counter
      is only one digit long */
if run < 10 then
  current = '0'||run /* Turn counter into a string so program does
                         not strip leading zero */
else /* Counter is already two digits */
  current = run

column.i = current ' = ' Calculate() HEAT /* Format single run output */
end
           /* Display the results */
say column.1 '|' column.2 '|' column.3 '|' column.4
end
say " " /* Output a final blank line */

   /* function to calculate next temperature and run controller: */
Calculate:

   /* Determine the disturbance: */
heatout=thermfactor * (temp-sinktemp) /* calculate our heat loss */

   /* Determine our perception: */
temp = temp + heatinput - heatout /* calculate new temperature */

   /* The following 4 lines are a kludge to make the display prettier */
if length(temp) < 5 then
  TEMP=' 'temp
else
  TEMP=temp

   /* This is the controller: */

   /* Is the perception less than the reference? */
if (setpoint - temp) > 0 then do /* This is the comparitor */

   /* Do this if the reference is greater than the perception: */
  heatinput= thermfactor * (inputtemp-temp) /* Yes, do it */
  HEAT='ON ' /* set display flag */
end

   /* Do this if reference is equal or less than perception: */
else do /* NO */
  heatinput=0 /* don't add heat */
  HEAT='OFF' /* set display flag */
end
return(TEMP) /* return result */
exit(1) /* do system clean-up and exit program */

-------------snip sinp sinp-------------

-bill