Move pid autotuning request to CtrlPanel

And update autotune UI only on state change instead of every single
report update
This commit is contained in:
atse 2024-08-27 16:46:48 +08:00
parent 4407e5c97a
commit 3aeef04330
3 changed files with 27 additions and 34 deletions

View File

@ -1,9 +1,11 @@
from PyQt6.QtCore import QObject, pyqtSlot from PyQt6.QtCore import QObject, pyqtSlot, pyqtSignal
from qasync import asyncSlot from qasync import asyncSlot
from autotune import PIDAutotuneState, PIDAutotune from autotune import PIDAutotuneState, PIDAutotune
class PIDAutoTuner(QObject): class PIDAutoTuner(QObject):
autotune_state_changed = pyqtSignal(int, PIDAutotuneState)
def __init__(self, parent, thermostat, num_of_channel): def __init__(self, parent, thermostat, num_of_channel):
super().__init__(parent) super().__init__(parent)
@ -37,9 +39,11 @@ class PIDAutoTuner(QObject):
self.lookback[ch], self.lookback[ch],
) )
self.autotuners[ch].setReady() self.autotuners[ch].setReady()
self.autotune_state_changed.emit(ch, self.autotuners[ch].state())
async def stop_pid_from_running(self, ch): async def stop_pid_from_running(self, ch):
self.autotuners[ch].setOff() self.autotuners[ch].setOff()
self.autotune_state_changed.emit(ch, self.autotuners[ch].state())
await self._thermostat.set_param("pwm", ch, "i_set", 0) await self._thermostat.set_param("pwm", ch, "i_set", 0)
@asyncSlot(list) @asyncSlot(list)
@ -65,6 +69,7 @@ class PIDAutoTuner(QObject):
case PIDAutotuneState.STATE_SUCCEEDED: case PIDAutotuneState.STATE_SUCCEEDED:
kp, ki, kd = self.autotuners[ch].get_tec_pid() kp, ki, kd = self.autotuners[ch].get_tec_pid()
self.autotuners[ch].setOff() self.autotuners[ch].setOff()
self.autotune_state_changed.emit(ch, self.autotuners[ch].state())
await self._thermostat.set_param("pid", ch, "kp", kp) await self._thermostat.set_param("pid", ch, "kp", kp)
await self._thermostat.set_param("pid", ch, "ki", ki) await self._thermostat.set_param("pid", ch, "ki", ki)
@ -76,4 +81,5 @@ class PIDAutoTuner(QObject):
) )
case PIDAutotuneState.STATE_FAILED: case PIDAutotuneState.STATE_FAILED:
self.autotuners[ch].setOff() self.autotuners[ch].setOff()
self.autotune_state_changed.emit(ch, self.autotuners[ch].state())
await self._thermostat.set_param("pwm", ch, "i_set", 0) await self._thermostat.set_param("pwm", ch, "i_set", 0)

View File

@ -6,6 +6,7 @@ from pyqtgraph.parametertree import (
registerParameterType, registerParameterType,
) )
from qasync import asyncSlot from qasync import asyncSlot
from autotune import PIDAutotuneState
import pytec.gui.view.lockable_unit import pytec.gui.view.lockable_unit
@ -26,7 +27,6 @@ class CtrlPanel(QObject):
info_box, info_box,
trees_ui, trees_ui,
param_tree, param_tree,
sigActivated_handles,
parent=None, parent=None,
): ):
super().__init__(parent) super().__init__(parent)
@ -67,8 +67,9 @@ class CtrlPanel(QObject):
param.child("load").sigActivated.connect( param.child("load").sigActivated.connect(
partial(self.load_settings, ch) partial(self.load_settings, ch)
) )
for handle in sigActivated_handles[ch]: param.child("pid", "pid_autotune", "run_pid").sigActivated.connect(
param.child(*handle[0]).sigActivated.connect(handle[1]) partial(self.pid_auto_tune_request, ch)
)
def _indicate_usage(param, control_method="constant_current"): def _indicate_usage(param, control_method="constant_current"):
for item in param.child("i_set").items: for item in param.child("i_set").items:
@ -247,3 +248,16 @@ class CtrlPanel(QObject):
f"Channel {ch} settings has been saved to flash.\n" f"Channel {ch} settings has been saved to flash.\n"
"It will be loaded on Thermostat reset, or when settings are explicitly loaded.", "It will be loaded on Thermostat reset, or when settings are explicitly loaded.",
) )
@asyncSlot()
async def pid_auto_tune_request(self, ch=0):
match self.autotuners.get_state(ch):
case PIDAutotuneState.STATE_OFF | PIDAutotuneState.STATE_FAILED:
self.autotuners.load_params_and_set_ready(ch)
case (
PIDAutotuneState.STATE_READY
| PIDAutotuneState.STATE_RELAY_STEP_UP
| PIDAutotuneState.STATE_RELAY_STEP_DOWN
):
await self.autotuners.stop_pid_from_running(ch)

View File

@ -76,28 +76,18 @@ class MainWindow(QtWidgets.QMainWindow):
self.thermostat.connection_state_changed.connect(self._on_connection_changed) self.thermostat.connection_state_changed.connect(self._on_connection_changed)
self.autotuners = PIDAutoTuner(self, self.thermostat, 2) self.autotuners = PIDAutoTuner(self, self.thermostat, 2)
self.autotuners.autotune_state_changed.connect(self.pid_autotune_handler)
def get_ctrl_panel_config(args): def get_ctrl_panel_config(args):
with open(args.param_tree, "r", encoding="utf-8") as f: with open(args.param_tree, "r", encoding="utf-8") as f:
return json.load(f)["ctrl_panel"] return json.load(f)["ctrl_panel"]
param_tree_sigActivated_handles = [
[
[
["pid", "pid_autotune", "run_pid"],
partial(self.pid_autotune_request, ch),
],
]
for ch in range(self.NUM_CHANNELS)
]
self.ctrl_panel_view = CtrlPanel( self.ctrl_panel_view = CtrlPanel(
self.thermostat, self.thermostat,
self.autotuners, self.autotuners,
self.info_box, self.info_box,
[self.ch0_tree, self.ch1_tree], [self.ch0_tree, self.ch1_tree],
get_ctrl_panel_config(args), get_ctrl_panel_config(args),
param_tree_sigActivated_handles,
) )
self.zero_limits_warning = ZeroLimitsWarningView( self.zero_limits_warning = ZeroLimitsWarningView(
@ -107,8 +97,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.zero_limits_warning.set_limits_warning self.zero_limits_warning.set_limits_warning
) )
self.thermostat.report_update.connect(self.pid_autotune_handler)
self.thermostat.hw_rev_update.connect(self._status) self.thermostat.hw_rev_update.connect(self._status)
self.report_apply_btn.clicked.connect( self.report_apply_btn.clicked.connect(
lambda: self.thermostat.set_update_s(self.report_refresh_spin.value()) lambda: self.thermostat.set_update_s(self.report_refresh_spin.value())
@ -218,23 +206,8 @@ class MainWindow(QtWidgets.QMainWindow):
else: else:
await self.thermostat.end_session() await self.thermostat.end_session()
@asyncSlot() @asyncSlot(int, PIDAutotuneState)
async def pid_autotune_request(self, ch=0): async def pid_autotune_handler(self, _ch, _state):
match self.autotuners.get_state(ch):
case PIDAutotuneState.STATE_OFF | PIDAutotuneState.STATE_FAILED:
self.autotuners.load_params_and_set_ready(ch)
case (
PIDAutotuneState.STATE_READY
| PIDAutotuneState.STATE_RELAY_STEP_UP
| PIDAutotuneState.STATE_RELAY_STEP_DOWN
):
await self.autotuners.stop_pid_from_running(ch)
# To Update the UI elements
self.pid_autotune_handler([])
@asyncSlot(list)
async def pid_autotune_handler(self, _):
ch_tuning = [] ch_tuning = []
for ch in range(self.NUM_CHANNELS): for ch in range(self.NUM_CHANNELS):
match self.autotuners.get_state(ch): match self.autotuners.get_state(ch):