mantic (9) pid.9.gz

Provided by: linuxcnc-uspace_2.9.0~pre1+git20230208.f1270d6ed7-1_amd64 bug

NAME

       pid - proportional/integral/derivative controller with automatic tuning support

SYNOPSIS

       loadrt pid [num_chan=num | names=name1[,name2...]] [debug=dbg]

DESCRIPTION

       pid  is a classic Proportional/Integral/Derivative controller, used to control position or
       speed feedback loops for servo motors and other closed-loop applications.

       pid supports a maximum of sixteen controllers.  The number that are actually loaded is set
       by  the  num_chan  argument  when the module is loaded.  Alternatively, specify names= and
       unique names separated by commas.

       The num_chan= and names= specifiers are mutually  exclusive.   If  neither  num_chan=  nor
       names=  are  specified,  the default value is three.  If debug is set to 1 (the default is
       0), some additional HAL parameters will be exported, which might be useful for tuning, but
       are otherwise unnecessary.

       In  the  following  description,  it  is  assumed  that  we are discussing position loops.
       However this component can be used to implement other loops such  as  speed  loops,  torch
       height control, and others.

       Each  loop has a number of pins and parameters, whose names begin with 'pid.N.', where 'N'
       is the channel number.  Channel numbers start at zero.

       The three most important pins are 'command', 'feedback', and  'output'.   For  a  position
       loop,  'command'  and  'feedback' are in position units.  For a linear axis, this could be
       inches, mm, metres, or whatever is relevant.  Likewise, for a angular axis,  it  could  be
       degrees,  radians, etc.  The units of the 'output' pin represent the change needed to make
       the feedback match the command.  As such, for a position loop 'output' is a  velocity,  in
       inches/sec, mm/sec, degrees/sec, etc.

       Each  loop has several other pins as well. 'error' is equal to 'command' minus 'feedback'.
       'enable' is a bit that enables the loop.  If 'enable' is false, all integrators are reset,
       and the output is forced to zero.  If 'enable' is true, the loop operates normally.

       The  PID  gains,  limits,  and  other  'tunable'  features  of the loop are implemented as
       parameters.  These are as follows:

       Pgain Proportional gain
       Igain Integral gain
       Dgain Derivative gain
       bias Constant offset on output
       FF0  Zeroth order Feedforward gain
       FF1  First order Feedforward gain
       FF2  Second order Feedforward gain
       FF3  Third order Feedforward gain
       deadband Amount of error that will be ignored
       maxerror Limit on error
       maxerrorI Limit on error integrator
       maxerrorD Limit on error differentiator
       maxcmdD Limit on command differentiator
       maxcmdDD Limit on command 2nd derivative
       maxcmdDDD Limit on command 3rd derivative
       maxoutput Limit on output value

       All of the limits (max____) are implemented such that if  the  parameter  value  is  zero,
       there is no limit.

       A  number of internal values which may be useful for testing and tuning are also available
       as parameters.  To avoid cluttering  the  parameter  list,  these  are  only  exported  if
       "debug=1" is specified on the insmod command line.

       errorI Integral of error
       errorD Derivative of error
       commandD Derivative of the command
       commandDD 2nd derivative of the command
       commandDDD 3rd derivative of the command

       The  PID  loop calculations are as follows (see the code in pid.c for all the nitty gritty
       details):

              error = command - feedback
              if ( abs(error) < deadband ) then error = 0
              limit error to +/- maxerror
              errorI += error * period
              limit errorI to +/- maxerrorI
              errorD = (error - previouserror) / period
              limit errorD to +/- maxerrorD
              commandD = (command - previouscommand) / period
              limit commandD to +/- maxcmdD
              commandDD = (commandD - previouscommandD) / period
              limit commandDD to +/- maxcmdDD
              commandDDD = (commandDD - previouscommandDD) / period
              limit commandDDD to +/- maxcmdDDD
              output = bias + error * Pgain + errorI * Igain +
                       errorD * Dgain + command * FF0 + commandD * FF1 +
                       commandDD * FF2 + commandDDD * FF3
              limit output to +/- maxoutput

       This component has a built in auto tune mode. It works by setting  up  a  limit  cycle  to
       characterize  the  process.   This  is  called  the Relay method and described in the 1984
       Automation paper Automatic Tuning of Simple Regulators with Specifications  on  Phase  and
       Amplitude      Margins      by     Karl     Johan     Åström     and     Tore     Hägglund
       (doi:10.1016/0005-1098(84)90014-1),
       https://lup.lub.lu.se/search/ws/files/6340936/8509157.pdf.      Using     this     method,
       Pgain/Igain/Dgain  or  Pgain/Igain/FF1  can  be  determined  using   the   Ziegler-Nichols
       algorithm.  When using FF1 tuning, scaling must be set so that output is in user units per
       second.

       During auto tuning, the command input should not change.  The limit cycle is setup  around
       the commanded position.  No initial tuning values are required to start auto tuning.  Only
       tune-cycles, tune-effort and tune-mode need be set before starting auto tuning.  Note that
       setting  tune-mode  to  true  disable  the  control loop.  When auto tuning completes, the
       tuning parameters will be set, the  output  set  to  bias  and  the  controller  still  be
       disabled.   If running from LinuxCNC, the FERROR setting for the axis being tuned may need
       to be loosened up, as it must be larger than the limit cycle amplitude in order to avoid a
       following error.

       To  perform  auto  tuning,  take the following steps.  Move the axis to be tuned somewhere
       near the center of it's travel.  Set tune-cycles (the default value should be fine in most
       cases) and tune-mode.  Set tune-effort to a small value. Set enable to true. Set tune-mode
       to true.  Set tune-start to true. If no oscillation occurs,  or  the  oscillation  is  too
       small, slowly increase tune-effort.  Set tune-start to true.  If no oscillation occurs, or
       the oscillation is too small, slowly increase tune-effort Auto tuning can  be  aborted  at
       any time by setting enable or tune-mode to false.

NAMING

       The names for pins, parameters, and functions are prefixed as:
         pid.N. for N=0,1,...,num-1 when using num_chan=num
         nameN. for nameN=name1,name2,... when using names=name1,name2,...

       The pid.N. format is shown in the following descriptions.

FUNCTIONS

       pid.N.do-pid-calcs (uses floating-point) Does the PID calculations for control loop N.

PINS

       pid.N.command float in
              The desired (commanded) value for the control loop.

       pid.N.Pgain float in
              Proportional  gain.   Results  in  a  contribution  to the output that is the error
              multiplied by Pgain.

       pid.N.Igain float in
              Integral gain.  Results in a contribution to the output that is the integral of the
              error  multiplied  by  Igain.   For example an error of 0.02 that lasted 10 seconds
              would result in an integrated error (errorI) of  0.2,  and  if  Igain  is  20,  the
              integral term would add 4.0 to the output.

       pid.N.Dgain float in
              Derivative  gain.   Results  in  a  contribution  to the output that is the rate of
              change (derivative) of the error multiplied by Dgain.  For example  an  error  that
              changed  from  0.02  to  0.03  over 0.2 seconds would result in an error derivative
              (errorD) of of 0.05, and if Dgain is 5, the derivative term would add 0.25  to  the
              output.

       pid.N.feedback float in
              The actual (feedback) value, from some sensor such as an encoder.

       pid.N.output float out
              The output of the PID loop, which goes to some actuator such as a motor.

       pid.N.command-deriv float in
              The derivative of the desired (commanded) value for the control loop.  If no signal
              is connected then the derivative will be estimated numerically.

       pid.N.feedback-deriv float in
              The derivative of the actual (feedback) value for the control loop.  If  no  signal
              is  connected then the derivative will be estimated numerically.  When the feedback
              is from a quantized position source (e.g., encoder feedback position), behavior  of
              the  D  term  can be improved by using a better velocity estimate here, such as the
              velocity output of encoder(9) or hostmot2(9).

       pid.N.error-previous-target bit in
              Use previous invocation's target vs. current position for error  calculation,  like
              the  motion controller expects.  This may make torque-mode position loops and loops
              requiring a  large  I  gain  easier  to  tune,  by  eliminating  velocity-dependent
              following error.

       pid.N.error float out
              The difference between command and feedback.

       pid.N.enable bit in
              When  true,  enables  the  PID  calculations.   When false, output is zero, and all
              internal integrators, etc, are reset.

       pid.N.index-enable bit in
              On the falling edge of index-enable, pid  does  not  update  the  internal  command
              derivative estimate.  On systems which use the encoder index pulse, this pin should
              be connected to the index-enable signal.   When  this  is  not  done,  and  FF1  is
              nonzero,  a step change in the input command causes a single-cycle spike in the PID
              output.  On systems which use exactly one of the -deriv inputs, this affects the  D
              term as well.

       pid.N.bias float in
              bias  is a constant amount that is added to the output.  In most cases it should be
              left at zero.  However, it can sometimes be useful to  compensate  for  offsets  in
              servo  amplifiers,  or  to  balance  the weight of an object that moves vertically.
              bias is turned off when the PID loop is disabled, just like all other components of
              the  output.  If a non-zero output is needed even when the PID loop is disabled, it
              should be added with an external HAL sum2 block.

       pid.N.FF0 float in
              Zero order feed-forward term.  Produces a contribution to the output  that  is  FF0
              multiplied  by  the commanded value.  For position loops, it should usually be left
              at zero.  For velocity loops, FF0 can compensate for friction or motor  counter-EMF
              and may permit better tuning if used properly.

       pid.N.FF1 float in
              First  order  feed-forward term.  Produces a contribution to the output that is FF1
              multiplied by the derivative of the  commanded  value.   For  position  loops,  the
              contribution  is  proportional to speed, and can be used to compensate for friction
              or motor CEMF.  For velocity loops, it is  proportional  to  acceleration  and  can
              compensate  for  inertia.   In  both  cases, it can result in better tuning if used
              properly.

       pid.N.FF2 float in
              Second order feed-forward term.  Produces a contribution to the output that is  FF2
              multiplied  by  the  second derivative of the commanded value.  For position loops,
              the contribution is proportional to acceleration, and can be used to compensate for
              inertia.   For velocity loops, the contribution is proportional to jerk, and should
              usually be left at zero.

       pid.N.FF3 float in
              Third order feed-forward term.  Produces a contribution to the output that  is  FF3
              multiplied by the third derivative of the commanded value.  For position loops, the
              contribution is proportional to jerk, and can be used to  compensate  for  residual
              errors  during  acceleration.  For velocity loops, the contribution is proportional
              to snap(jounce), and should usually be left at zero.

       pid.N.deadband float in
              Defines a range of "acceptable" error.  If the absolute value of error is less than
              deadband,  it will be treated as if the error is zero.  When using feedback devices
              such as encoders that are inherently quantized, the deadband should be set slightly
              more  than  one-half count, to prevent the control loop from hunting back and forth
              if the command is between two adjacent encoder values.  When the absolute value  of
              the  error  is greater than the deadband, the deadband value is subtracted from the
              error before performing the loop calculations, to prevent a step  in  the  transfer
              function at the edge of the deadband (see BUGS).

       pid.N.maxoutput float in
              Output  limit.   The  absolute  value of the output will not be permitted to exceed
              maxoutput, unless maxoutput is  zero.   When  the  output  is  limited,  the  error
              integrator will hold instead of integrating, to prevent windup and overshoot.

       pid.N.maxerror float in
              Limit  on the internal error variable used for P, I, and D.  Can be used to prevent
              high Pgain values from generating large outputs under conditions when the error  is
              large  (for  example,  when the command makes a step change).  Not normally needed,
              but can be useful when tuning non-linear systems.

       pid.N.maxerrorD float in
              Limit on the error derivative.  The rate of change of error used by the Dgain  term
              will  be limited to this value, unless the value is zero.  Can be used to limit the
              effect of Dgain and prevent large output spikes due to steps on the command  and/or
              feedback.  Not normally needed.

       pid.N.maxerrorI float in
              Limit  on  error  integrator.   The error integrator used by the Igain term will be
              limited to this value, unless it is zero.  Can be used to prevent integrator windup
              and the resulting overshoot during/after sustained errors.  Not normally needed.

       pid.N.maxcmdD float in
              Limit on command derivative.  The command derivative used by FF1 will be limited to
              this value, unless the value is zero.  Can be used to prevent  FF1  from  producing
              large output spikes if there is a step change on the command.  Not normally needed.

       pid.N.maxcmdDD float in
              Limit on command second derivative.  The command second derivative used by FF2 will
              be limited to this value, unless the value is zero.  Can be  used  to  prevent  FF2
              from  producing  large output spikes if there is a step change on the command.  Not
              normally needed.

       pid.N.maxcmdDDD float in
              Limit on command third derivative.  The command third derivative used by  FF3  will
              be  limited  to  this  value, unless the value is zero.  Can be used to prevent FF3
              from producing large output spikes if there is a step change on the  command.   Not
              normally needed.

       pid.N.saturated bit out
              When true, the current PID output is saturated.  That is,
                   output = ± maxoutput.

       pid.N.saturated-s float out
       pid.N.saturated-count s32 out
              When  true,  the  output  of  PID  was  continually saturated for this many seconds
              (saturated-s) or periods (saturated-count).

   Additional auto tuning pins
       pid.N.tune-mode bit in
              When true, enables auto  tune  mode.   When  false,  normal  PID  calculations  are
              performed.

       pid.N.tune-start bit io
              When set to true, starts auto tuning.  Cleared when the auto tuning completes.

       pid.N.tune-type u32 rw
              When set to 0, Pgain/Igain/Dgain are calculated. When set to 1, Pgain/Igain/FF1 are
              calculated.

       pid.N.tune-cycles u32 rw
              Determines the number of cycles to run to characterize  the  process.   tune-cycles
              actually  sets  the  number of half cycles.  More cycles results in a more accurate
              characterization as the average of all cycles is used.

       pid.N.tune-effort float rw
              Determines the  effort  used  in  setting  up  the  limit  cycle  in  the  process.
              tune-effort  should  be  set  to  a positive value less than maxoutput.  Start with
              something small and work up to a value that  results  in  a  good  portion  of  the
              maximum motor current being used.  The smaller the value, the smaller the amplitude
              of the limit cycle.

       pid.N.ultimate-gain float ro (only if debug=1)
              Determined from process characterization. ultimate-gain is the ratio of tune-effort
              to the limit cycle amplitude multiplied by 4.0 divided by Pi.

       pid.N.ultimate-period float ro (only if debug=1)
              Determined  from  process  characterization.  ultimate-period  is the period of the
              limit cycle.

PARAMETERS

       pid.N.errorI float ro (only if debug=1)
              Integral of error.  This is the value that is multiplied by Igain  to  produce  the
              Integral term of the output.

       pid.N.errorD float ro (only if debug=1)
              Derivative  of error.  This is the value that is multiplied by Dgain to produce the
              Derivative term of the output.

       pid.N.commandD float ro (only if debug=1)
              Derivative of command.  This is the value that is multiplied by FF1 to produce  the
              first order feed-forward term of the output.

       pid.N.commandDD float ro (only if debug=1)
              Second  derivative  of  command.   This  is  the value that is multiplied by FF2 to
              produce the second order feed-forward term of the output.

       pid.N.commandDDD float ro (only if debug=1)
              Third derivative of command.  This is the  value  that  is  multiplied  by  FF3  to
              produce the third order feed-forward term of the output.

BUGS

       Some  people would argue that deadband should be implemented such that error is treated as
       zero if it is within the deadband, and be unmodified if it is outside the deadband.   This
       was  not  done because it would cause a step in the transfer function equal to the size of
       the deadband.  People who prefer that behavior are welcome to add a  parameter  that  will
       change  the behavior, or to write their own version of pid.  However, the default behavior
       should not be changed.

       Negative gains may lead to unwanted behavior.  It is  possible  in  some  situations  that
       negative FF gains make sense, but in general all gains should be positive.  If some output
       is in the wrong direction, negating gains  to  fix  it  is  a  mistake;  set  the  scaling
       correctly elsewhere instead.