PDI Feedback Controller Program

I've built a PDI feedback controller for the AVR which can seek and hold a specific value. Load is still a capacitor+resistor hooked up to a VCO. The controller uses 3 terms to set the output from the input:

1. Proportional: a multiple of the error.
2. Derivative: a multiple of the first derivative of the error.
3. Integral: a multiple of the sum over time of the error.

This is a standard controller type which is easily implemented in software. The salient code is:

for (i = 0; i < SUM_LENGTH - 1; i ++) error[i] = error[i + 1];
error[SUM_LENGTH - 1] = input - target;
deltaError = error[SUM_LENGTH - 1] - error[SUM_LENGTH - 2];
sumError = 0;
for (i = 0; i < SUM_LENGTH; i ++) sumError += error[i];
y = output + kP * error[SUM_LENGTH - 1] + kD * deltaError + (kI * sumError) / SUM_LENGTH;
newOutput = y + 0.5;

where the equation for y updates the output using the P, D, and I terms. Currently I am sampling and making 1 correction per second.

The coefficients for the controller can be set graphically by observing the step response to the system. The attached screenshots (60 sec per plot) show:

1. A step response from 0 to 127 (half the range) using a P coefficient of -0.5. The control signal is in blue, the hardware response is in red, and the target value is green. The system shows a damped oscillation about the target value.

2. Decreasing the P term to -2.25 just produces a sustained oscillation.

3. Adding a D term of -3.25 damps the oscillation without overshoot.

4. Adding an I term of -0.125 adds just a little overshoot, slightly decreases setting time, and increases stability.

5. System response to changing the target from 127 to 63, to 191, and back to 127.

6. Uncontrolled response to varying the load by inserting and removing a resistor across the capacitor.

7. Tracked response to the same varying load.

As you can see, the transient response to a large change is a little better than to a smaller change, but there are some things I can do about that. The next thing is to do this with a real motor!

İSky Coyote 2006