add autotune

This commit is contained in:
topquark12 2022-06-07 13:54:18 +08:00 committed by Egor Savkin
parent ba39af4dfa
commit ccdff602c4
2 changed files with 54 additions and 9 deletions

View File

@ -17,6 +17,7 @@ class PIDAutotuneState(Enum):
STATE_RELAY_STEP_DOWN = 'relay step down' STATE_RELAY_STEP_DOWN = 'relay step down'
STATE_SUCCEEDED = 'succeeded' STATE_SUCCEEDED = 'succeeded'
STATE_FAILED = 'failed' STATE_FAILED = 'failed'
STATE_READY = 'ready'
class PIDAutotune: class PIDAutotune:
@ -56,6 +57,20 @@ class PIDAutotune:
self._Ku = 0 self._Ku = 0
self._Pu = 0 self._Pu = 0
def setParam(self, target, step, noiseband, sampletime, lookback):
self._setpoint = target
self._outputstep = step
self._out_max = step
self._out_min = -step
self._noiseband = noiseband
self._inputs = deque(maxlen=round(lookback / sampletime))
def setReady(self):
self._state = PIDAutotuneState.STATE_READY
def setOff(self):
self._state = PIDAutotuneState.STATE_OFF
def state(self): def state(self):
"""Get the current state.""" """Get the current state."""
return self._state return self._state
@ -81,6 +96,13 @@ class PIDAutotune:
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)
def get_tec_pid (self):
divisors = self._tuning_rules["tyreus-luyben"]
kp = self._Ku * divisors[0]
ki = divisors[1] * self._Ku / self._Pu
kd = divisors[2] * self._Ku * self._Pu
return kp, ki, kd
def run(self, input_val, time_input): def run(self, input_val, time_input):
"""To autotune a system, this method must be called periodically. """To autotune a system, this method must be called periodically.
@ -95,7 +117,8 @@ 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
or self._state == PIDAutotuneState.STATE_READY):
self._state = PIDAutotuneState.STATE_RELAY_STEP_UP self._state = PIDAutotuneState.STATE_RELAY_STEP_UP
self._last_run_timestamp = now self._last_run_timestamp = now

View File

@ -68,7 +68,8 @@ GUIparams = [[
{'name': 'Save to flash', 'type': 'action', 'tip': 'Save to flash'}, {'name': 'Save to flash', 'type': 'action', 'tip': 'Save to flash'},
] for _ in range(2)] ] for _ in range(2)]
autoTuneState = [PIDAutotuneState.STATE_OFF, 'idle'] autoTuner = [PIDAutotune(20, 1, 1, 1.5, refresh_period / 1000),
PIDAutotune(20, 1, 1, 1.5, refresh_period / 1000)]
## If anything changes in the tree, print a message ## If anything changes in the tree, print a message
def change(param, changes, ch): def change(param, changes, ch):
@ -88,6 +89,7 @@ def change(param, changes, ch):
tec.set_param('pwm', ch, 'i_set', 0) tec.set_param('pwm', ch, 'i_set', 0)
paramList[ch].child('Constant Current').child('Set Current').setValue(0) paramList[ch].child('Constant Current').child('Set Current').setValue(0)
paramList[ch].child('Temperature PID').setValue(False) paramList[ch].child('Temperature PID').setValue(False)
autoTuner[ch].setOff()
if (childName == 'Temperature PID'): if (childName == 'Temperature PID'):
if (data): if (data):
@ -130,7 +132,13 @@ def change(param, changes, ch):
tec.set_param('pid', ch, 'kd', data) tec.set_param('pid', ch, 'kd', data)
if (childName == 'PID Config.PID Auto Tune.Run'): if (childName == 'PID Config.PID Auto Tune.Run'):
autoTuneState[ch] = 'triggered' autoTuner[ch].setParam(paramList[ch].child('PID Config').child('PID Auto Tune').child('Target Temperature').value(),
paramList[ch].child('PID Config').child('PID Auto Tune').child('Test Current').value(),
paramList[ch].child('PID Config').child('PID Auto Tune').child('Temperature Swing').value(),
refresh_period / 1000,
1)
autoTuner[ch].setReady()
paramList[ch].child('Temperature PID').setValue(False)
if (childName == 'Save to flash'): if (childName == 'Save to flash'):
tec.save_config() tec.save_config()
@ -185,8 +193,8 @@ def TECsync():
if parents['tag'] == 'report': if parents['tag'] == 'report':
for data in tec.report_mode(): for data in tec.report_mode():
for children in parents['children']: for children in parents['children']:
print(data)
children['value'] = data[channel][children['tag']] children['value'] = data[channel][children['tag']]
print(data[channel][children['tag']])
if quit: if quit:
break break
if parents['tag'] == 'pwm': if parents['tag'] == 'pwm':
@ -226,10 +234,24 @@ def updateData():
ch0currentGraph.update(data, cnt) ch0currentGraph.update(data, cnt)
ch1currentGraph.update(data, cnt) ch1currentGraph.update(data, cnt)
for state in autoTuneState: for channel in range (2):
if state == 'triggered': if (autoTuner[channel].state() == PIDAutotuneState.STATE_READY or
state = 'tuning' autoTuner[channel].state() == PIDAutotuneState.STATE_RELAY_STEP_UP or
autoTuner[channel].state() == PIDAutotuneState.STATE_RELAY_STEP_DOWN):
autoTuner[channel].run(data[channel]['temperature'], data[channel]['time'])
tec.set_param('pwm', channel, 'i_set', autoTuner[channel].output())
elif (autoTuner[channel].state() == PIDAutotuneState.STATE_SUCCEEDED):
kp, ki, kd = autoTuner[channel].get_tec_pid()
autoTuner[channel].setOff()
paramList[channel].child('PID Config').child('kP').setValue(kp)
paramList[channel].child('PID Config').child('kI').setValue(ki)
paramList[channel].child('PID Config').child('kD').setValue(kd)
tec.set_param('pid', channel, 'kp', kp)
tec.set_param('pid', channel, 'ki', ki)
tec.set_param('pid', channel, 'kd', kd)
elif (autoTuner[channel].state() == PIDAutotuneState.STATE_FAILED):
tec.set_param('pwm', channel, 'i_set', 0)
autoTuner[channel].setOff()
if quit: if quit:
break break