diff --git a/brewpi.py b/brewpi.py index a87a9dc..aee6b2d 100644 --- a/brewpi.py +++ b/brewpi.py @@ -7,7 +7,7 @@ from components.plant.pot import Pot, APlant from components.actor.heater import Heater, AHeater from components.pid import kalman, temp_controller from ws.message import MsgIo, MessageDispatcher -from utils.value import Value, ValueChanged +from utils.value import Value, ChangedFloat, ChangedInteger TC_DT = 0.1 @@ -41,7 +41,7 @@ class TempSensorTask(ATask): async def on_process(self): print("{}: Started with interval {} s".format(self.msg_handler.get_key(), self.interval)) - temp = ValueChanged(self.on_temp_changed, prec=1) + temp = ChangedFloat(self.on_temp_changed, prec=1) self.sensor.set_on_changed("temp", temp.set) while True: self.sensor.process() @@ -126,6 +126,10 @@ class TcTask(ATask): self.tc = tc self.temp_soll = 30 + def on_state_changed(self, state): + print ("State change to {}".format(state)) + asyncio.create_task(self.send({'State': state.value})) + async def recv(self, data): print(data) for pair in data.items(): @@ -138,6 +142,9 @@ class TcTask(ATask): async def on_process(self): print("{}: Started with interval {} s".format(self.msg_handler.get_key(), self.interval)) temp_soll = Value() + + self.tc.set_on_changed('state', ChangedInteger(self.on_state_changed).set) + while True: temp_soll.set(self.temp_soll) if temp_soll.is_changed(): @@ -201,12 +208,12 @@ if __name__ == '__main__': "kn" : 0.2 } pot = Pot(pot_params, 20) - pot.set_on_changed("temp", ValueChanged(sensor.set_fake_temp, prec=3).set) + pot.set_on_changed("temp", ChangedFloat(sensor.set_fake_temp, prec=3).set) taskmgr.add(PotTask(pot, TC_DT, dispatcher.msgio_get("Pot"))) # Heater heater = Heater() - heater.set_on_changed("power_eff", ValueChanged(pot.setPower, prec=0).set) + heater.set_on_changed("power_eff", ChangedFloat(pot.setPower, prec=0).set) heater_task = HeaterTask(heater, TC_DT, dispatcher.msgio_get("Heater")) taskmgr.add(heater_task) @@ -231,7 +238,7 @@ if __name__ == '__main__': tc.set_on_changed("y", heater_task.actor) tc_task = TcTask(tc, TC_DT, dispatcher.msgio_get("TempCtrl")) taskmgr.add(tc_task) - sensor.set_on_changed("temp", ValueChanged(tc.set_theta_ist, prec=2).set) + sensor.set_on_changed("temp", ChangedFloat(tc.set_theta_ist, prec=2).set) # Message dispatcher h_dispatcher = taskmgr.start() diff --git a/components/pid/temp_controller.py b/components/pid/temp_controller.py index 8549395..a0958eb 100644 --- a/components/pid/temp_controller.py +++ b/components/pid/temp_controller.py @@ -28,7 +28,7 @@ class TempController(AttributeChange): self.params = params_pid self.kalman = kalman.Kalman(params_kalman) self.y = 0 - self.state = States.HOLD + self.state = States.IDLE self.use_kalman = True self.kalman.initial((20, 0)) @@ -60,12 +60,30 @@ class TempController(AttributeChange): # Process state state_next = self.state - if self.state == States.HOLD: - if (self.theta_ist + 1.0) < self.theta_soll_set: + diff = self.theta_soll_set - self.theta_ist + + THRESH_HEAT = 1.0 + THRESH_IDLE = 1.0 + THRESH_IDLE_HOLD = 0.1 + THRESH_HEAT_HOLD = 1.0 + + if self.state == States.IDLE: + if diff > THRESH_HEAT: state_next = States.HEAT self.pid_rate.reset() + elif diff > -THRESH_IDLE_HOLD: + state_next = States.HOLD + self.pid_hold.reset() + elif self.state == States.HOLD: + if diff > THRESH_HEAT: + state_next = States.HEAT + self.pid_rate.reset() + elif diff < -THRESH_IDLE_HOLD: + state_next = States.IDLE elif self.state == States.HEAT: - if (self.theta_ist + 1.0) >= self.theta_soll_set: + if diff < -THRESH_IDLE: + state_next = States.IDLE + elif diff < THRESH_HEAT_HOLD: state_next = States.HOLD self.pid_hold.reset() @@ -75,8 +93,10 @@ class TempController(AttributeChange): if self.state == States.HEAT: self.y = self.pid_rate.get_y() - else: + elif self.state == States.HOLD: self.y = self.pid_hold.get_y() + else: + self.y = 0 if state_next != self.state: print("New state = {}".format(state_next)) diff --git a/utils/value.py b/utils/value.py index 598a904..1aeb0c5 100644 --- a/utils/value.py +++ b/utils/value.py @@ -15,7 +15,7 @@ class Value: return self.value -class ValueChanged(object): +class ChangedFloat(object): def __init__(self, on_changed, prec=2, initial=None): self.on_changed = on_changed self.prec = prec @@ -32,6 +32,21 @@ class ValueChanged(object): self.on_changed(value_rounded) +class ChangedInteger(object): + def __init__(self, on_changed, initial=None): + self.on_changed = on_changed + self.value = initial + + def set(self, value): + has_changed = True + if self.value is not None: + has_changed = self.value != value + + self.value = value + if has_changed: + self.on_changed(value) + + class AttributeChange(object): def __init__(self): self.callbacks = {}