[From Bill Powers (920616.1600) (The Control Systems Group)

Fang Zhong (Duke University 920616) --

Copy to CSGnet

Hello, Fang Zhong. You've been put in contact with a conference concerned

mainly with control theory as a tool for understanding behavior. As we use

pretty simple versions of control theory, maybe you've come to the right

place for a simple answer.

I have to make some guesses about the physical setup. I assume that your

heater is in contact with some thermal mass, perhaps water. So the mass

will heat up at a rate proportional to input power. There will also be a

thermal transport lag if the sensor is at all far from the heater. It's

mainly the transport lag that will cause the oscillations when you raise

the sensitivity. If you're using water, you can cut down on the transport

lag by madly stirring the water. But that's not your main problem.

Consider this line:

vh2 = prev_vh * prev_vh + (2 * cur_r - target_r - prev_r) * dv_dr

If you want to control temperature, you have to compare sensed temperature

with reference or target temperature. So the error signal would just be

(target_r - cur_r).

As you are using 2 * cur_r and subtracing prev_r, I assume you're adding

some first derivative of the error signal: that is,

total error = target - cur_r - (cur_r - prev_r)

<--error --> <-- deriv of error -->

This is my standard way of writing the error signal -- the sensor signal is

always subtracted from the reference signal. No particular reason, that's

just my convention. It keeps the feedback negative with all other constants

in the loop positive.

Now you want the heater voltage vh to be the integral of the error signal.

If you add the error signal to the SQUARE of the heater voltage (vh2),

you'll get a hybrid between the square of the integral and the integral of

the square. I don't think you want either one. It would be best to compute

first just the integral of the error:

vh2 = vh2 + (target_r - cur_r) - (cur_r - prev_r)

Now vh2 doesn't mean the square, it's just used as a dummy variable

(initialized to zero).

If you want heating rate to be linear with error, and I think this is best,

you should output a heater voltage proportional to the square root of vh2,

because power output goes as vh*vh. So your step

vh = sqrt(vh2)

is OK. It would be best to precede this step by

if(vh2 < 0) vh2 = 0

to avoid accidentally taking the square root of a negative number.

This will result in a linear heating system with integral error control,

some first-derivative phase advance, and another integration in the

environmental part of the loop that converts power output to rate of change

of temperature (temperature is roughly the integral of power output). If

the derivative contribution is large enough, you will get a system that

looks like a single integrator, and it will be stable save for the effects

of transport lag.

You need to be able to vary the amount of first derivative in relation to

the error signal, changing the first program line above to:

vh2 = vh2 + k1*(target_r - cur_r) - k2*(cur_r - prev_r).

By setting k1 VERY small and k2 zero, you can get a system that approaches

the reference temperature and stays there. It will act very slowly. Then

you can start increasing k1 to create oscillatory control, then k2 to

eliminate the oscillations. Eventually you will arrive at values of k1 and

k2 that give you the fastest possible control without oscillation. You

won't be able to go any faster than that because of transport lags.

Let us know how it works!

Best

Bill Powers

powers_w%flc@vaxf.colorado.edu