This commit is contained in:
atse 2023-08-30 15:23:03 +08:00
parent c9e8c4f4a1
commit 4635e71ebf
2 changed files with 65 additions and 2 deletions

View File

@ -14,5 +14,5 @@ setup(
"tec_qt = tec_qt:main",
]
},
py_modules=['tec_qt', 'ui_tec_qt'],
py_modules=['tec_qt', 'ui_tec_qt', 'autotune'],
)

View File

@ -15,6 +15,7 @@ import asyncio
from pytec.aioclient import Client, StoppedConnecting
import qasync
from qasync import asyncSlot, asyncClose
from autotune import PIDAutotune, PIDAutotuneState
# pyuic6 -x tec_qt.ui -o ui_tec_qt.py
from ui_tec_qt import Ui_MainWindow
@ -257,7 +258,9 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
{'name': 'Target Temperature', 'type': 'float', 'value': 20, 'step': 0.1, 'siPrefix': True, 'suffix': '°C'},
{'name': 'Test Current', 'type': 'float', 'value': 1, 'step': 0.1, 'siPrefix': True, 'suffix': 'A'},
{'name': 'Temperature Swing', 'type': 'float', 'value': 1.5, 'step': 0.1, 'siPrefix': True, 'prefix': '±', 'suffix': '°C'},
{'name': 'Run', 'type': 'action', 'tip': 'Run'},
{'name': 'Run', 'type': 'action', 'tip': 'Run', 'children': [
{'name': 'Autotuning...', 'type': 'progress', 'value': 0, 'readonly': True, 'visible': False},
]},
]},
]},
{'name': 'Save to flash', 'type': 'action', 'tip': 'Save config to thermostat, applies on reset'},
@ -299,6 +302,11 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
for ch in range(2)
]
self.autotuners = [
PIDAutotune(25)
for _ in range(2)
]
self.hw_rev_data = None
if args.connect:
@ -656,6 +664,61 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.params[i].child('Load from flash').sigActivated.connect(load)
@asyncSlot()
async def autotune(param, ch=i):
match self.autotuners[ch].state():
case PIDAutotuneState.STATE_OFF:
self.autotuners[ch].setParam(
param.parent().child('Target Temperature').value(),
param.parent().child('Test Current').value(),
param.parent().child('Temperature Swing').value(),
self.report_refresh_spin.value(),
3)
self.autotuners[ch].setReady()
param.child('Autotuning...').show(True)
param.setOpts(title="Stop")
self.client_watcher.report_update.connect(self.autotune_tick)
case PIDAutotuneState.STATE_READY | PIDAutotuneState.STATE_RELAY_STEP_UP | PIDAutotuneState.STATE_RELAY_STEP_DOWN:
self.autotuners[ch].setOff()
param.child('Autotuning...').hide()
param.setOpts(title="Run")
await self.client.set_param('pwm', ch, 'i_set', 0)
self.client_watcher.report_update.disconnect(self.autotune_tick)
param.child('Autotuning...').setValue(0)
self.params[i].child('PID Config', 'PID Auto Tune', 'Run').sigActivated.connect(autotune)
@asyncSlot(list)
async def autotune_tick(self, report):
for channel_report in report:
channel = channel_report['channel']
match self.autotuners[channel].state():
case PIDAutotuneState.STATE_READY | PIDAutotuneState.STATE_RELAY_STEP_UP | PIDAutotuneState.STATE_RELAY_STEP_DOWN:
self.autotuners[channel].run(channel_report['temperature'], channel_report['time'])
progress_bar = self.params[channel].child('PID Config', 'PID Auto Tune', 'Run', 'Autotuning...')
if progress_bar.value() < 99:
progress_bar.setValue(progress_bar.value() + 1) # TODO: Measure the progress better
await self.client.set_param('pwm', channel, 'i_set', self.autotuners[channel].output())
case PIDAutotuneState.STATE_SUCCEEDED:
kp, ki, kd = self.autotuners[channel].get_tec_pid()
self.autotuners[channel].setOff()
self.params[channel].child('PID Config', 'PID Auto Tune', 'Run').setOpts(title="Run")
self.params[channel].child('PID Config', 'PID Auto Tune', 'Run', 'Autotuning...').hide()
await self.client.set_param('pid', channel, 'kp', kp)
await self.client.set_param('pid', channel, 'ki', ki)
await self.client.set_param('pid', channel, 'kd', kd)
await self.client.set_param('pwm', channel, 'pid')
await self.client.set_param('pid', channel, 'target', self.params[channel].child("PID Config", "PID Auto Tune", "Target Temperature").value())
self.client_watcher.report_update.disconnect(self.autotune_tick)
self.params[channel].child('PID Config', 'PID Auto Tune', 'Run', 'Autotuning...').setValue(0)
case PIDAutotuneState.STATE_FAILED:
self.autotuners[channel].setOff()
self.params[channel].child('PID Config', 'PID Auto Tune', 'Run', 'Autotuning...').hide()
self.params[channel].child('PID Config', 'PID Auto Tune', 'Run').setOpts(title="Run")
await self.client.set_param('pwm', channel, 'i_set', 0)
self.client_watcher.report_update.disconnect(self.autotune_tick)
self.params[channel].child('PID Config', 'PID Auto Tune', 'Run', 'Autotuning...').setValue(0)
@pyqtSlot(list)
def update_pid(self, pid_settings):
for settings in pid_settings: