View Single Post
  #6   Report Post  
Posted to rec.crafts.metalworking
Tim Wescott[_6_] Tim Wescott[_6_] is offline
external usenet poster
 
Posts: 223
Default PID calculations

On Mon, 22 Sep 2014 21:23:51 -0500, RogerN wrote:

I've seen calculations for PID in a microcontroller but I'm thinking
something is missing.. or perhaps I'm misunderstanding something.

So if Derivative = current_error - previous_error then it's just
effective for one cycle. It seems like it should be the change over a
period of time,
not necessarily one pass through the loop.


That depends on a number of factors, including but not limited to sampling
rate, the amount of noise in the system, your desired settling time, and
the settling time that you can actually achieve.

One way would be to have an array of error[xx] and take the difference
in change over a period of time involving several of times through the
loop.


That's a BAD way to do it. It's what's known in the more esoteric corners
of the trade as a non-minimum phase filter, which basically means that the
filter has more delay than necessary for the amount of amplitude shaping
vs. frequency. Delay is a Bad Thing in a control loop, and is to be
avoided.

Also, I've seen some PID that the I adjustment is in units of time.

This might not be a big deal if there is a real high resolution, but if
you have a temperature control that is heating for a 5 degree error,
chances are the derivative term isn't going to have much effect if it's
calculated every millisecond. If it's calculated over a longer period,
for example how much change in the last 10 minutes, it would be more
meaningful.


It would be perfectly meaningful if the system noise were low enough, and
if there weren't any unexpected, fast paths from heater to thermostat.

I know a way to do this but I'm just looking for better ideas, perhaps
more efficient memory usage.


You want a band-limited derivative term. The best way to do this is
pretty simple, too (calculate this as one hunk-of-code each sample time):

derivative = (current_error - average_error);

average_error = average_error + k * (current_error - average_error);

Here "derivative" is the answer you want, "average_error" is a number that
you carry from sample to sample (a so-called "state", like your integrator
state), and k is a gain from 0 to 1 that determines the dynamics of the
differentiator. The bigger k is the faster the derivative action, so the
more noise it passes through and the more it helps fast settling. The
smaller k, the less noise, and the less helpful the derivative action is
when you're trying for high speeds.

If you need to mess with band-limited derivative terms then you really
should be doing frequency-domain design at least, but you can sometimes
make things work with seat of the pants tuning. As a rule of thumb, set k
to (10) * (sampling interval) / (settling time), where you know the
sampling interval and, the settling time is what you're trying to
achieve. If you end up computing a k greater than 1, then you need to re-
think your sampling interval or your desired settling time.

The link on my website to the article you want to read is currently
broken: send me an email and I'll reply with a pdf.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com