Ran update-copyright.py.
[pypid.git] / pypid / rules.py
1 # Copyright (C) 2011-2012 W. Trevor King <wking@tremily.us>
2 #
3 # This file is part of pypid.
4 #
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
8 # version.
9 #
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.
13 #
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/>.
16
17 "Assorted PID tuning rules"
18
19
20 def ziegler_nichols_step_response(process_gain, dead_time, decay_time, mode='PID'):
21     K,L,T = (process_gain, dead_time, decay_time)
22     r = L / T
23     if r > 1:
24         _LOG.warn(('Ziegler-Nichols not a good idea when '
25                    'dead-time/decay_time = {:n}').format(r))
26     pkern = 1/(K*r)
27     if mode == 'P':
28         return (pkern, float('inf'), 0)
29     elif mode == 'PI':
30         return (0.9*pkern, 3.3*L, 0)
31     elif mode == 'PID':
32         return (1.2*pkern, 2*L, L/2.)
33     raise ValueError(mode)
34
35 def ziegler_nichols_bang_bang_response(amplitude, period, max_current,
36                                        mode='PID'):
37     """
38     amplitude : float
39         center-to-peak amplitude (in K) of bang-bang oscillation
40     period : float
41         period (in seconds) of the critical oscillation
42     max_current : float
43         "bang" current (in amps)
44     """
45     proportional = float(max_current)/amplitude
46     period = float(period)
47     if mode == 'P':
48         return (proportional/2, float('inf'), 0)
49     elif mode == 'PI':
50         return (proportional/3, 2*period, 0)
51     elif mode == 'PID':
52         return (proportional/2, period, period/4)
53     raise ValueError(mode)
54
55 def ziegler_nichols_ultimate_cycle_response(proportional, period):
56     """
57     proportional : float
58         critical P-only process_gain (ultimate process_gain, for sustained oscillation)
59     period : float
60         period (in seconds) of the critical oscillation
61
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
65     details).
66
67     .. _nice analysis: http://www.mstarlabs.com/control/znrule.html
68     """
69     if mode == 'P':
70         return (0.50*proportional, float('inf'), 0)
71     elif mode == 'PI':
72         return (0.45*proportional, period/1.2, 0)
73     elif mode == 'PID':
74         return (0.60*proportional, period/2, period/8)
75     raise ValueError(mode)
76
77 def cohen_coon_step_response(process_gain, dead_time, decay_time, mode='PID'):
78     K,L,T = (process_gain, dead_time, decay_time)
79     r = L/T
80     pkern = 1/(K*r)
81     if mode == 'P':
82         return (pkern*(1+r/3.), float('inf'), 0)
83     elif mode == 'PI':
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)
88     elif mode == 'PID':
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)
92
93 def wang_juang_chan_step_response(process_gain, dead_time, decay_time, mode='PID'):
94     """Wang-Juang-Chan tuning
95     """
96     K,L,T = (process_gain, dead_time, decay_time)
97     if mode == 'PID':
98         return ((0.7303+0.5307*T/L)*(T+0.5*L)/(K*(T+L)),
99                 T + 0.5*L,
100                 0.5*L*T / (T + 0.5*L))
101     raise ValueError(mode)        
102