diff --git a/client/brewpi_gui.py b/client/brewpi_gui.py index edf3004..e30fcc2 100755 --- a/client/brewpi_gui.py +++ b/client/brewpi_gui.py @@ -308,10 +308,11 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.statusBar().addPermanentWidget(self.status_label_env) self.update_status_env_label() - # Blinking indicator for a Sud ramp step that's cooling down - # (target below the current temperature - the heater is forced off - # server-side and we just wait for ambient loss to catch up). - self.sud_cooling = False + # Blinking indicator for the temperature controller's own COOL + # state (target below the current temperature - the heater is + # forced off server-side and we just wait for ambient loss to + # catch up). + self.tc_cooling = False self.status_label_cooling = QtWidgets.QLabel("Cool down") self.status_label_cooling.setStyleSheet("color: blue; font-weight: bold;") self.status_label_cooling.setVisible(False) @@ -496,7 +497,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.sud_step_type = None self.sud_hold_remaining = 0.0 self.forecast_history = [] - self.set_sud_cooling(False) + self.set_tc_cooling(False) self.update_sud_actions() self.update_status_env_label() self.setWindowTitle("BrewPi") @@ -551,10 +552,10 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): title += " - {}".format(description) return title - def set_sud_cooling(self, cooling): - if cooling == self.sud_cooling: + def set_tc_cooling(self, cooling): + if cooling == self.tc_cooling: return - self.sud_cooling = cooling + self.tc_cooling = cooling if cooling: self.status_label_cooling.setVisible(True) self.cooling_blink_timer.start(500) @@ -651,6 +652,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): for key in msg: if 'State' in key: self.label_state.setText(msg['State']) + self.set_tc_cooling(msg['State'] == 'States.COOL') elif "Soll" in key: submsg = msg['Soll'] if 'Temp' in submsg: @@ -800,7 +802,6 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.sud_step_index = step.get('Index') self.sud_step_descr = step.get('Descr') self.sud_step_type = step.get('Type') - self.set_sud_cooling(step.get('Cooling', False)) self.update_status_step_label() elif "HoldRemaining" in key: self.sud_hold_remaining = msg['HoldRemaining'] diff --git a/components/pid/temp_controller_base.py b/components/pid/temp_controller_base.py index 1bd1557..6a64db1 100644 --- a/components/pid/temp_controller_base.py +++ b/components/pid/temp_controller_base.py @@ -45,14 +45,6 @@ class TempControllerBase(APid): self.pid_rate.set_params(params['Heat']) self.pid_cool.set_params(params['Cool']) self.is_startup = True - # Explicit override for a ramp step whose target is below the - # current temperature: forces y to 0 immediately rather than - # waiting for the FSM's own (slower, hysteresis-based) COOL - # transition, as soon as the caller (SudTask) knows the step needs - # to passively cool down. Mostly superseded by the COOL state - # below for a heat-only actuator (both end up clamped to 0 - # power) - kept for the immediate, decided-in-advance response. - self.cooling = False # Master on/off switch: while disabled, the FSM is held in IDLE and # the controller tries not to drive the heater at all (output # forced to 0) - off by default, enabled either by the user @@ -91,9 +83,6 @@ class TempControllerBase(APid): def set_heatrate_soll(self, value): self.heatrate_soll_set = value - def set_cooling(self, value): - self.cooling = value - def set_enabled(self, value): self.enabled = value @@ -150,7 +139,7 @@ class TempControllerBase(APid): self.pid_rate.process(heatrate_err, -self.heatrate_ist) self.pid_cool.process(heatrate_err, -self.heatrate_ist) - if self.state == States.IDLE or self.cooling: + if self.state == States.IDLE: self.y = 0 elif self.state == States.COOL: self.y = self.pid_cool.get_y() diff --git a/scripts/demos/sud/demo_sud.py b/scripts/demos/sud/demo_sud.py index 329f832..6551c19 100644 --- a/scripts/demos/sud/demo_sud.py +++ b/scripts/demos/sud/demo_sud.py @@ -87,14 +87,6 @@ if __name__ == '__main__': ramping = sud.state == SudState.RAMPING phase = step['ramp'] if ramping and 'ramp' in step else step.get('hold', {}) - # A ramp step whose target is below the current temperature can - # only be reached by passive cooling - force the heater off, - # mirroring tasks/sud.py's SudTask. - cooling = bool(ramping and 'ramp' in step and step['temperature'] < ctrl.get_theta_ist() - TEMP_REACHED_TOLERANCE) - ctrl.set_cooling(cooling) - if cooling: - print(" -> cooling down to {}".format(step['temperature'])) - print(f"Step {step['number']}: {step['descr']}") apply_plant_params(step) if ramping and 'ramp' in step: diff --git a/tasks/sud.py b/tasks/sud.py index 0ae0c78..793817c 100644 --- a/tasks/sud.py +++ b/tasks/sud.py @@ -61,17 +61,6 @@ class SudTask(ATask): ramping = self.sud.state == SudState.RAMPING phase = ramp if ramping and ramp is not None else hold - # A ramp step whose target is below the current temperature can - # only be reached by passive cooling - force the heater off for - # its whole duration (decided once, here, rather than re-checked - # every tick) instead of relying on the controller's own FSM to - # notice and idle out. - # bool(...): get_theta_ist() can be a numpy.float64 (Pot's transport - # delay line is a numpy array internally) - the '<' comparison would - # then yield numpy.bool_, which json.dumps() can't serialize. - cooling = bool(ramping and ramp is not None and step['temperature'] < self.tc.get_theta_ist() - TEMP_REACHED_TOLERANCE) - self.tc.set_cooling(cooling) - if step is not None: self.apply_plant_params(step) if ramping and ramp is not None: @@ -87,7 +76,6 @@ class SudTask(ATask): 'Rate': ramp.get('rate') if ramp else None, 'Duration': hold.get('duration') if (hold is not None and not ramping) else None, 'WaitForUser': step.get('user_wait_for_continue', False) if step else None, - 'Cooling': cooling, }})) def on_state_changed(self, value):