pytec: autotune formatting
This commit is contained in:
parent
aab0d6d25c
commit
9f872c0113
|
@ -2,8 +2,8 @@ import math
|
||||||
import logging
|
import logging
|
||||||
from time import time
|
from time import time
|
||||||
from collections import deque, namedtuple
|
from collections import deque, namedtuple
|
||||||
from pytec.client import Client
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from pytec.client import Client
|
||||||
|
|
||||||
# Based on hirshmann pid-autotune libiary
|
# Based on hirshmann pid-autotune libiary
|
||||||
# See https://github.com/hirschmann/pid-autotune
|
# See https://github.com/hirschmann/pid-autotune
|
||||||
|
@ -17,12 +17,10 @@ class PIDAutotuneState(Enum):
|
||||||
STATE_SUCCEEDED = 'succeeded'
|
STATE_SUCCEEDED = 'succeeded'
|
||||||
STATE_FAILED = 'failed'
|
STATE_FAILED = 'failed'
|
||||||
|
|
||||||
class PIDAutotune():
|
class PIDAutotune():
|
||||||
|
|
||||||
PIDParams = namedtuple('PIDParams', ['Kp', 'Ki', 'Kd'])
|
PIDParams = namedtuple('PIDParams', ['Kp', 'Ki', 'Kd'])
|
||||||
|
|
||||||
PEAK_AMPLITUDE_TOLERANCE = 0.05
|
PEAK_AMPLITUDE_TOLERANCE = 0.05
|
||||||
|
|
||||||
|
|
||||||
_tuning_rules = {
|
_tuning_rules = {
|
||||||
"ziegler-nichols": [0.6, 1.2, 0.075],
|
"ziegler-nichols": [0.6, 1.2, 0.075],
|
||||||
|
@ -36,19 +34,8 @@ class PIDAutotune():
|
||||||
def __init__(self, setpoint, out_step=10, lookback=60, noiseband=0.5, sampletime=1.2):
|
def __init__(self, setpoint, out_step=10, lookback=60, noiseband=0.5, sampletime=1.2):
|
||||||
if setpoint is None:
|
if setpoint is None:
|
||||||
raise ValueError('setpoint must be specified')
|
raise ValueError('setpoint must be specified')
|
||||||
# if out_step < 1:
|
|
||||||
# raise ValueError('out_step must be greater or equal to 1')
|
|
||||||
# if sampletime < 1:
|
|
||||||
# raise ValueError('sampletime must be greater or equal to 1')
|
|
||||||
# if lookback < sampletime:
|
|
||||||
# raise ValueError('lookback must be greater or equal to sampletime')
|
|
||||||
# if out_min >= out_max:
|
|
||||||
# raise ValueError('out_min must be less than out_max')
|
|
||||||
|
|
||||||
# self._time = time
|
|
||||||
# logging = logging.getLogger(type(self).__name__)
|
|
||||||
self._inputs = deque(maxlen=round(lookback / sampletime))
|
self._inputs = deque(maxlen=round(lookback / sampletime))
|
||||||
# self._sampletime = sampletime * 1000
|
|
||||||
self._setpoint = setpoint
|
self._setpoint = setpoint
|
||||||
self._outputstep = out_step
|
self._outputstep = out_step
|
||||||
self._noiseband = noiseband
|
self._noiseband = noiseband
|
||||||
|
@ -65,18 +52,15 @@ class PIDAutotune():
|
||||||
self._induced_amplitude = 0
|
self._induced_amplitude = 0
|
||||||
self._Ku = 0
|
self._Ku = 0
|
||||||
self._Pu = 0
|
self._Pu = 0
|
||||||
|
|
||||||
|
|
||||||
def state(self):
|
def state(self):
|
||||||
"""Get the current state."""
|
"""Get the current state."""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
|
|
||||||
def output(self):
|
def output(self):
|
||||||
"""Get the last output value."""
|
"""Get the last output value."""
|
||||||
return self._output
|
return self._output
|
||||||
|
|
||||||
# @property
|
|
||||||
def tuning_rules(self):
|
def tuning_rules(self):
|
||||||
"""Get a list of all available tuning rules."""
|
"""Get a list of all available tuning rules."""
|
||||||
return self._tuning_rules.keys()
|
return self._tuning_rules.keys()
|
||||||
|
@ -90,9 +74,7 @@ class PIDAutotune():
|
||||||
"""
|
"""
|
||||||
divisors = self._tuning_rules[tuning_rule]
|
divisors = self._tuning_rules[tuning_rule]
|
||||||
kp = self._Ku * divisors[0]
|
kp = self._Ku * divisors[0]
|
||||||
# ki = kp / (self._Pu / divisors[1])
|
|
||||||
ki = divisors[1] * self._Ku / self._Pu
|
ki = divisors[1] * self._Ku / self._Pu
|
||||||
# kd = kp * (self._Pu / divisors[2])
|
|
||||||
kd = divisors[2] * self._Ku * self._Pu
|
kd = divisors[2] * self._Ku * self._Pu
|
||||||
return PIDAutotune.PIDParams(kp, ki, kd)
|
return PIDAutotune.PIDParams(kp, ki, kd)
|
||||||
|
|
||||||
|
@ -100,7 +82,8 @@ class PIDAutotune():
|
||||||
"""To autotune a system, this method must be called periodically.
|
"""To autotune a system, this method must be called periodically.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
input_val (float): The input value.
|
input_val (float): The temperature input value.
|
||||||
|
time_input (float): Current time in seconds.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
`true` if tuning is finished, otherwise `false`.
|
`true` if tuning is finished, otherwise `false`.
|
||||||
|
@ -110,10 +93,9 @@ class PIDAutotune():
|
||||||
if (self._state == PIDAutotuneState.STATE_OFF
|
if (self._state == PIDAutotuneState.STATE_OFF
|
||||||
or self._state == PIDAutotuneState.STATE_SUCCEEDED
|
or self._state == PIDAutotuneState.STATE_SUCCEEDED
|
||||||
or self._state == PIDAutotuneState.STATE_FAILED):
|
or self._state == PIDAutotuneState.STATE_FAILED):
|
||||||
self._initTuner(input_val, now)
|
self.init_tuner(input_val, now)
|
||||||
|
|
||||||
self._last_run_timestamp = now
|
self._last_run_timestamp = now
|
||||||
# print("temp : ", input_val)
|
|
||||||
|
|
||||||
# check input and change relay state if necessary
|
# check input and change relay state if necessary
|
||||||
if (self._state == PIDAutotuneState.STATE_RELAY_STEP_UP
|
if (self._state == PIDAutotuneState.STATE_RELAY_STEP_UP
|
||||||
|
@ -197,7 +179,6 @@ class PIDAutotune():
|
||||||
|
|
||||||
if amplitude_dev < PIDAutotune.PEAK_AMPLITUDE_TOLERANCE:
|
if amplitude_dev < PIDAutotune.PEAK_AMPLITUDE_TOLERANCE:
|
||||||
self._state = PIDAutotuneState.STATE_SUCCEEDED
|
self._state = PIDAutotuneState.STATE_SUCCEEDED
|
||||||
# logging.debug('peak finding succeeded')
|
|
||||||
|
|
||||||
# if the autotune has not already converged
|
# if the autotune has not already converged
|
||||||
# terminate after 10 cycles
|
# terminate after 10 cycles
|
||||||
|
@ -225,13 +206,12 @@ class PIDAutotune():
|
||||||
print('rule: {0}'.format(rule))
|
print('rule: {0}'.format(rule))
|
||||||
print('Kp: {0}'.format(params.Kp))
|
print('Kp: {0}'.format(params.Kp))
|
||||||
print('Ki: {0}'.format(params.Ki))
|
print('Ki: {0}'.format(params.Ki))
|
||||||
print('Kd: {0}'.format(params.Kd))
|
print('Kd: {0}'.format(params.Kd))
|
||||||
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _initTuner(self, inputValue, timestamp):
|
def init_tuner(self, inputValue, timestamp):
|
||||||
self._peak_type = 0
|
self._peak_type = 0
|
||||||
self._peak_count = 0
|
self._peak_count = 0
|
||||||
self._output = 0
|
self._output = 0
|
||||||
|
@ -245,7 +225,6 @@ class PIDAutotune():
|
||||||
self._state = PIDAutotuneState.STATE_RELAY_STEP_UP
|
self._state = PIDAutotuneState.STATE_RELAY_STEP_UP
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
# Auto tune parameters
|
# Auto tune parameters
|
||||||
# Thermostat channel
|
# Thermostat channel
|
||||||
channel = 0
|
channel = 0
|
||||||
|
@ -260,7 +239,7 @@ def main():
|
||||||
|
|
||||||
# logging.basicConfig(level=logging.DEBUG)
|
# logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
tec = Client() #(host="localhost", port=6667)
|
tec = Client()
|
||||||
|
|
||||||
data = next(tec.report_mode())
|
data = next(tec.report_mode())
|
||||||
ch = data[channel]
|
ch = data[channel]
|
||||||
|
@ -268,7 +247,6 @@ def main():
|
||||||
tuner = PIDAutotune(target_temperature, output_step, lookback, noiseband, ch['interval'])
|
tuner = PIDAutotune(target_temperature, output_step, lookback, noiseband, ch['interval'])
|
||||||
|
|
||||||
for data in tec.report_mode():
|
for data in tec.report_mode():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ch = data[channel]
|
ch = data[channel]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue