1 # Copyright (C) 2011-2012 W. Trevor King <wking@tremily.us>
3 # This file is part of pypid.
5 # pypid is free software: you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation, either version 3 of the License, or (at your option) any later
10 # pypid is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License along with
15 # pypid. If not, see <http://www.gnu.org/licenses/>.
17 "Assorted PID tuning rules"
20 def ziegler_nichols_step_response(process_gain, dead_time, decay_time, mode='PID'):
21 K,L,T = (process_gain, dead_time, decay_time)
24 _LOG.warn(('Ziegler-Nichols not a good idea when '
25 'dead-time/decay_time = {:n}').format(r))
28 return (pkern, float('inf'), 0)
30 return (0.9*pkern, 3.3*L, 0)
32 return (1.2*pkern, 2*L, L/2.)
33 raise ValueError(mode)
35 def ziegler_nichols_bang_bang_response(amplitude, period, max_current,
39 center-to-peak amplitude (in K) of bang-bang oscillation
41 period (in seconds) of the critical oscillation
43 "bang" current (in amps)
45 proportional = float(max_current)/amplitude
46 period = float(period)
48 return (proportional/2, float('inf'), 0)
50 return (proportional/3, 2*period, 0)
52 return (proportional/2, period, period/4)
53 raise ValueError(mode)
55 def ziegler_nichols_ultimate_cycle_response(proportional, period):
58 critical P-only process_gain (ultimate process_gain, for sustained oscillation)
60 period (in seconds) of the critical oscillation
62 Microstar Laboratories has a `nice analysis`_ on ZN
63 limitations, which points out that ZN-tuning assumes your
64 system has the FOPDT transfer function (see `TestBackend` for
67 .. _nice analysis: http://www.mstarlabs.com/control/znrule.html
70 return (0.50*proportional, float('inf'), 0)
72 return (0.45*proportional, period/1.2, 0)
74 return (0.60*proportional, period/2, period/8)
75 raise ValueError(mode)
77 def cohen_coon_step_response(process_gain, dead_time, decay_time, mode='PID'):
78 K,L,T = (process_gain, dead_time, decay_time)
82 return (pkern*(1+r/3.), float('inf'), 0)
84 return (pkern*(0.9+r/12.), (30.+3*r)/(9+20*r)*dead_time, 0)
85 elif mode == 'PD': # double check
86 return (1.24*pkern*(1+0.13*tf), float('inf'),
87 (0.27-0.36*t)/(1-0.87*t)*dead_time)
89 return (pkern*(4./3+r/4.), (32.-6*r)/(13.-8*r)*dead_time,
90 4/(11.+2*r)*dead_time)
91 raise ValueError(mode)
93 def wang_juang_chan_step_response(process_gain, dead_time, decay_time, mode='PID'):
94 """Wang-Juang-Chan tuning
96 K,L,T = (process_gain, dead_time, decay_time)
98 return ((0.7303+0.5307*T/L)*(T+0.5*L)/(K*(T+L)),
100 0.5*L*T / (T + 0.5*L))
101 raise ValueError(mode)