Needed 'C or C++' code a PID application

R

Thread Starter

Roy Stai

Does anyone have a PID alogrithm written in 'C' or 'C++'? Pseudo code would be useful.

I'm developing an embedded application that controls the output voltage of a high voltage power supply. The rise time (rate of change) and maxium ringing allowed prior to steady state are tightly spec'ed. In my assessment, the "Integral" parameter is critical in managing the ringing while the "Derivative" parameter will adjust the rate of change.
 
M

Michael Griffin

<p>I've done something similar (but for low voltage). Unless there is something very unusual about your hardware, rise time is going to be strictly a characteristic of the electrical circuit (including the power supply and the load), and not the software algorithm.

<p>Any true electrical "ringing" will also be due to the reactive electrical characteristics of your circuit, and I am not sure you can do anything about it in software. If you actually mean "overshoot" however, then that will be a
matter of your algorithm and tuning factors.

<p>Proportional is for a large immediate response to an error. Integral is for achieving zero error, not for "ringing". Derivative is for reducing overshoot. However, derivative can make the system unstable if you are not
very careful.

<p>I don't know how fast you require the system to be, but I would suggest trying it with integral only first and measuring it to see if that is good enough. Since a power supply typically reacts very fast and has no "friction" even an open loop command should get it very close to the set-point without any PID at all provided the system is properly calibrated. The integral component would then correct any small residual error.

<p>The basic algorithm is simple if you have a loop that is going at at constant rate (equal time between loop samples). The most important concept is to measure the "error" - the difference between the actual reading and the set-point (desired value). Then you add (or subtract) a value based the error each time through the loop.

<pre>
##################################
# set_point = desired value.
# actual = measured value.
# P_factor and I_factor are numbers between 0 and 1.
# min_output and max_output are the minimum and maximum
# physical output limits on the command signal.
##################################
# Proportional only.
Proportional:
error = set_point - actual
command_signal = set_point + (error * P_factor)

##################################
# Integral only. The "if" statement is for "anti-windup".
# error value must be preserved between iterations.
##################################
Integral:
if (command_signal > min_output .AND. command_signal < max_output)
error = error + (set_point - actual)

command_signal = set_point + (error * I_factor)


###################################
# Both proportional and integral.
# See "integral only" for additional explanations.
##################################
Proportional&Integral:
error_P = set_point - actual
correction_P = error_P * P_factor

if (command_signal > min_output .AND. command_signal < max_output)
error_I = error_I + (set_point - actual)

correction_I = error_I * I_factor
command_signal = set_point + correction_P + correction_I
</pre>

<p>I will leave derivative as an exercise for your imagination. For the integral component, "error" must be preserved between loop iterations, and it must be properly intialised to a suitable value when starting up the algorithm. "Anti-windup" prevents the integral component from accumulating any further if the output is already at the limits of the hardware response.
 
Top