forked from M-Labs/thermostat
Autotune
This commit is contained in:
parent
c9e8c4f4a1
commit
4635e71ebf
@ -14,5 +14,5 @@ setup(
|
|||||||
"tec_qt = tec_qt:main",
|
"tec_qt = tec_qt:main",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
py_modules=['tec_qt', 'ui_tec_qt'],
|
py_modules=['tec_qt', 'ui_tec_qt', 'autotune'],
|
||||||
)
|
)
|
||||||
|
@ -15,6 +15,7 @@ import asyncio
|
|||||||
from pytec.aioclient import Client, StoppedConnecting
|
from pytec.aioclient import Client, StoppedConnecting
|
||||||
import qasync
|
import qasync
|
||||||
from qasync import asyncSlot, asyncClose
|
from qasync import asyncSlot, asyncClose
|
||||||
|
from autotune import PIDAutotune, PIDAutotuneState
|
||||||
|
|
||||||
# pyuic6 -x tec_qt.ui -o ui_tec_qt.py
|
# pyuic6 -x tec_qt.ui -o ui_tec_qt.py
|
||||||
from ui_tec_qt import Ui_MainWindow
|
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': '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': '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': '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'},
|
{'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)
|
for ch in range(2)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
self.autotuners = [
|
||||||
|
PIDAutotune(25)
|
||||||
|
for _ in range(2)
|
||||||
|
]
|
||||||
|
|
||||||
self.hw_rev_data = None
|
self.hw_rev_data = None
|
||||||
|
|
||||||
if args.connect:
|
if args.connect:
|
||||||
@ -656,6 +664,61 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
self.params[i].child('Load from flash').sigActivated.connect(load)
|
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)
|
@pyqtSlot(list)
|
||||||
def update_pid(self, pid_settings):
|
def update_pid(self, pid_settings):
|
||||||
for settings in pid_settings:
|
for settings in pid_settings:
|
||||||
|
Loading…
Reference in New Issue
Block a user