# PI controller algorithm

#### Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

•  Subject
• Author
• Posted on
Hi There,

I need to resolve following problem:
I have an led panel with an opto transistor on it that measures the
light emitted/reflected from the target. I want to control the emitted
light to be equal to a certain setpoint from what the opto transistor
measures. Does that make sense? I'm using an 18F pic to control the
whole circuit and I wanted to come up with a PI if not a PID
PID controllers but am not 100% sure about some things. So far I've
come up with below code:

#define OFFSET 0
#define P 1
#define I 1
int control_func(int measure, int setpoint)
{
static int intgrl_err=0;
int output;
int curr_err;

//P
curr_err=measure-setpoint;
output=(curr_err*P)+OFFSET;

//I
intgrl_err+=curr_err;
output*=g*I*intgrl_err;

return output;
}

I however am not exactly sure what the g variabl in the I part is. The
documentation i read doesn't outline it... :( Some assistance would be
appreciated.

Thank you very much!
Ron

Re: PI controller algorithm

Oh for clarification, maybe I should say that the LEDs are driven by
PWM and I would like to control the duty cycle which will be a value
from 0-50 (503D%100%).

Re: PI controller algorithm
Hi Ron,

The derivative term will most probably not be of any use to you  :>

In simplistic terms (PI):

Error = Value - Setpoint
Integrator += Error
Output = (Proportional_Gain * Error) + (Integral_Gain * Error)

Lather, rinse, repeat.

[This is the easiest way, IMO, to view what the loop does.
There are other forms for expressing it -- e.g., the "Standard
Form" as well as the Laplace transform (useful for mathematical
modeling tools)]

You typically add an integral term when there is an offset in
the "Value" that proportional control won't remove by itself
(the integrator accumulates this offset and "nudges" the output
accordingly)

In *practice*, you often want to impose a deadband on the
error signal (i.e., any error having a magnitude of "deadband"
or less is treated as having an error of "0").  This can be
useful when your control capabilities are too course wrt your
measurement capabilities.  E.g., you set your PWM to 23% duty
cycle and get an error that says "too low"; so, you bump it up
to 24% and then get an error that says "too high".  If you
have provisions for a deadband, you can just set that accordingly
and end up with "23%... close enough".

Also, depending on what you are controlling and how it is likely
to *fail*, you might want to put some anti-windup protection on
your integral term to keep "Integrator" from becoming *so*
large (positive or negative) that it dominates the loop's
performance for an inordinately long time.  E.g., imagine using
"doubles" for these variables.  Now, imagine the detector is
obstructed for 10,000 iterations of your control loop.  In
that case, you are likely to see a big "Error" *and* accumulate
it repeatedly -- regardless of what your control is trying to
do to compensate for it!  When the detector is eventually
unobstructed, the "Output" is way out of whack for a long
time (until the integrator "clears").

Some implementations clamp the magnitude of the Error signal.

Some loops clear the integrator automagically when the sign
of the Error changes.

Some loops "damp" changes to the setpoint (since a setpoint
change looks like a disturbance).  Bumpless transfer, etc.

You probably also want to apply some limits on the range of
"Output" values that you will deliver to the Field (if you
haven't already done so in the hardware that is driving the
LED, etc.)

The task of twiddling the various gains, clamps, etc. that
your particular implementation supports is called Tuning.
This is where the real work is!  :>  In your case, I suspect
this should be trivial unless you have a poorly regulated
power supply, ground bounce or radical changes in target
reflectivity, etc.  (only you can decide how fast and/or
stable the loop needs to be for your environment)

Note that all of the above is gross oversimplification -- but
should point you in the right direction.  And, it assumes you
are sampling at a fixed time interval (you can also compensate
for variations in sampling).

HTH,
--don

Re: PI controller algorithm
says...

......

As a general rule for any electronics or algorithm (software or
hardware) that is measuring light level from photodetectors to imaging
sensors should alwasy cope with the error conditions first of

a) The output is always minimum (obstruction/lens cap)

b) The output is always maximum (pointed at sun or bright light)

c) The output of the sensor is disconnected, or failed.

At start up I always ignore at least the FIRST two samples to determine
what the ambient condition is. In your case I would also every once
in a while do a detection cycle with the emitter OFF to get an ambient
condition. This is not used in control loop but tests the sensor is
working if ambient is not min or max. Then with emmitter ON your error
must be at least a minimum away from ambient for operations to be
useable.

If you sampling regime is 50 or 60 Hz you should be able to fit a test
sample inbetween sampling times without effecting the sampling times
without affecting the sampling loop.

....

--
Paul Carpenter          | snipped-for-privacy@pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/ PC Services
We've slightly trimmed the long signature. Click to see the full one.
Re: PI controller algorithm

Well, I have a software low passfilter after I read thwe adc and i let
it swing it on bootup, meaning i loop 20 * FILTER in order to get a
valid value, I determined that 20x is a pretty good value to get a
decent start value with a filter like this:
MyVal 3D% (MyVal * FILTER + ADCVal) / (FILTER + 1) and i'm currently
using a FILTER value of 10.

Yep, that's actually the plan, in between the LED-on cycles, I'm
sampling the ambient brightness which is fed back to the "main-brain"
of the system.

roN

Re: PI controller algorithm
In article <16c21154-6e25-4c2a-bf76-

You have heard of 'Garbage In Garbage Out' If all the readings are due
to pointing at a bright light, so reading is out of normal range, your
filter will still produce an out of output.

Do you do any the reading is meaningless do NOT process, flag error
states.

--
Paul Carpenter          | snipped-for-privacy@pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/ PC Services
We've slightly trimmed the long signature. Click to see the full one.
Re: PI controller algorithm

Response to a change in output is going to be picked up on the next
sample (I assume), so you really don't need anything other than integral
action -- proportional and derivative control are just invitations for
Fs/2 oscillation.

Normally, if you're not adjusting for sampling rate the overall
integrator gain is less than one -- I suspect that's what the 'g' is.
It would also be more clear to name your integrator state intgrl_state -
it's not really an error.  _Multiplying_ your proportional term by the
integrator state is _definitely weird_.

http://www.wescottdesign.com/articles/Sampling/pidwophd.html

then merge what you learned with this (decorations left as an exercise

int control_func(int measure, int setpoint)
{
static int int_state;
int output;

int_state -= (measure - setpoint);

// Some code to check for integrator overflow would be a Good
// Idea here

output = int_state >> INT_SHIFT;

return output;
}

--

Tim Wescott
Wescott Design Services
We've slightly trimmed the long signature. Click to see the full one.
Re: PI controller algorithm

Thank you both D & Tim for your contributions!
I have been reading the whole morning and will keep doing it for the
rest of today I assume... What I learned so far is, I don't need the D
part and neither do I need to I part. And just as a little
clarification, my pwm that activates the LEDs is having a frequency of
100kHz and will be active for 200-500uS while a "light pulse" is
active, that light pulse will come in 50 or 60Hz intervals.... does
this make it any more complicated? I might still need the I part as I
need to sample the adc (and run through the whole controller logic)
while the led is on which would directly interfer with the pwm time
being reset, I can't tell right now if the pwm needs to finish it's
current cycle before it starts the next one with the new duty cycle
tho. I'm using a PIC16F883 - maybe someone here knows...?

Thanks for everything! Your help is greatly appreciated!

Re: PI controller algorithm

Otherwise, I'd see it making sense if I buffered the controller output
and maybe average it during each Frequency pwm cycle(200-500uSec) and
once thas's done, apply the new pwm value to be used when the next
pulse comes around...

Re: PI controller algorithm
Hi Ron,

The Derivative term allows your controller to *anticipate*
(in a sense) the response of the system being controlled.  It is
useful when you have lots of lag in your measurement+control+system.
In your case (as I understand it) you are just looking at a reflection
and tweaking the "illumination" to achieve some desired result.

You have to look at the timing relationship between your "PWM drive"
and your measurement -- along with the response characteristics of the
emitter and detector.  E.g., if your emitter and detector are *ideal*,
then when the emitter is off, you will see "darkness" (nothing
reflected because the light is already *gone*).  So, if you are
sampling the detector "instantaneously* (no averaging or integration),
then sampling when the emitter is *on* will give you different signals
than when it is *off*.  If the timing of your sampling varies relative
to the drive of the emitter, then you will see apparent variations in
the measured signal that really aren't present in the *actual* signal
(sometimes it's on, sometimes it's off, etc.)

[I can't say what is right for you as I don't understand the
actual application you are facing]

A "P only" controller, IMO, is harder to tune than an "I only"
controller.  If you really only want to have *one* term to tweak,
then I vote for I (assuming your system can handle the response
times consequential to this).  If you have "enough headroom" in
the integrator, then you can have a painfully low integral gain
and still -- eventually -- get the system to be stable (assuming
you can tolerate the response time *and* that your system doesn't
change "too fast")

But, then again, I have already confessed my ignorance of your
application!  :>

In a purely generic sense, I would design:
- a measurement system that samples the detector "whenever it *should*"
- a drive system that runs the PWM at a particular duty cycle and rate
- a control system that straddles the two of these -- taking data from
the measurement system and "operating parameters" (setpoint, etc.)
from "somewhere" (the user?), computing the required "drive" (Output)
for the current state reported by the measurement system, and then
passing a new "command" to the drive system to effect the changes
required to get the system where you want it.

each individual PWM cycle by instantaneously observing the detector's
signal (?)

Re: PI controller algorithm
<snip>
Thank you both D & Tim for your contributions!
I have been reading the whole morning and will keep doing it for the
rest of today I assume... What I learned so far is, I don't need the D
part and neither do I need to I part.

** It's the D & P you don't need.

And just as a little clarification, my pwm that activates the LEDs is having
a frequency of
100kHz and will be active for 200-500uS while a "light pulse" is
active, that light pulse will come in 50 or 60Hz intervals.... does
this make it any more complicated? I might still need the I part as I
need to sample the adc (and run through the whole controller logic)
while the led is on which would directly interfer with the pwm time
being reset, I can't tell right now if the pwm needs to finish it's
current cycle before it starts the next one with the new duty cycle
tho. I'm using a PIC16F883 - maybe someone here knows...?

Thanks for everything! Your help is greatly appreciated!

Re: PI controller algorithm

today (and that was quite a few).
Thank you for that, I rewrote the code and came up with below which
should look better than what I had before:

typedef struct
{
signed float iState;
float iMax,
iMin;

float iGain,
pGain;
}SPid;

SPid CntrlData;
CntrlData.iGain=1;
CntrlData.pGain=1;
CntrlData.iMax50%;
CntrlData.iMin=0;

signed int8 error=0;
int8 target15%0;

CntrlLEDs(&CntrlData, error);
//-----------------------------------------------------------------------------
signed float CntrlLEDs(Spid *pid, signed int8 error)
{
signed float pTerm,iTerm;

/** P **/
pTerm = pid->pGain * error;

/** I **/
pid->iState += error;

if (pid->iState > pid->iMax)
pid->iState=pid->iMax;
else if (pid->iState < pid->iMin)
pid->iState=pid->iMin;

iTerm = pid->iGain * pid->iState;

return pTerm+iTerm;
}

Thanks again for your help and your article sure is a keeper!

Re: PI controller algorithm

Well, I'll use above PI controller for now, built it into my software
but can't test it yet as i don't have the hardware available yet...
any one know of a free controller tune application where i an enter my
possible values and maybe even let it run with my code...?

Thanks,
Ron