from components.plant.pot import Pot from matplotlib.pyplot import plot, figure, subplot, title, xlabel, ylabel, grid, show, legend from components.pid import Pid, Kalman import numpy as np from utils.value import AttributeChange from enum import Enum class States(Enum): IDLE = 0, HEAT = 1, HOLD = 2 class TempController(AttributeChange): def __init__(self, params_pid, params_kalman): AttributeChange.__init__(self) self.pid_hold = Pid(params_pid['Hold']) self.pid_rate = Pid(params_pid['Heat']) self.theta_ist_set = 20 self.theta_soll_set = 0 self.heatrate_ist_set = 0 self.heatrate_soll_set = 1.0 self.heatrate_soll = 1.0 self.theta_ist = 0 self.heatrate_ist = 0 self.params = params_pid self.kalman = Kalman(params_kalman) self.y = -1 self.state = States.IDLE self.use_kalman = True self.kalman.initial((self.theta_ist_set, 0)) def set_theta_ist(self, value): self.theta_ist_set = value def set_heatrate_ist(self, value): self.heatrate_ist_set = value def set_theta_soll(self, value): self.theta_soll_set = value def set_heatrate_soll(self, value): self.heatrate_soll_set = value def process(self): # Process Kalman if self.use_kalman: Z = self.kalman.process_measurement((self.theta_ist_set, 0), 0.0) xp = self.kalman.process(Z) self.theta_ist = xp[0, 0] self.heatrate_ist = xp[1, 0] * 60 else: self.theta_ist = self.theta_ist_set self.heatrate_ist = self.heatrate_ist_set self.heatrate_soll = self.heatrate_soll_set * self.pid_hold.get_y() theta_err = self.theta_soll_set - self.theta_ist heatrate_err = self.heatrate_soll - self.heatrate_ist # Process state state_next = self.state 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_rate.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 diff < -THRESH_IDLE: state_next = States.IDLE elif diff < THRESH_HEAT_HOLD: state_next = States.HOLD self.pid_hold.reset() self.pid_hold.process(theta_err) self.pid_rate.process(heatrate_err) self.y = self.pid_rate.get_y() if state_next != self.state: self.state = state_next print("New state = {}".format(state_next)) def get_power(self): return self.y if __name__ == '__main__': params = { "Hold": { "dt": 1.0, "kp": 0.5, "ki": 0.0, "kd": 0.0, "kt": 0.0 }, "Heat": { "dt": 1.0, "kp": 0.1, "ki": 0.01, "kd": 0.0, "kt": 1.0 } } pot_params = { "dt" : 1.0, "theta" : 20, "C" : 4190, "M" : 20, "L" : 0.05, "Td" : 12, "kn" : 0.2 } # Kalman Filter kalman_params = { "dt" : 1.0, "var_P" : 1, "var_Q" : 0.0001, "var_R" : 1 } temp_ist = 0 temp_soll = 20 ctrl = TempController(params, kalman_params) plant = Pot(pot_params) _temp_ist = np.empty(0) _temp_soll = np.empty(0) _y = np.empty(0) _fb = np.empty(0) _t = np.empty(0) _heatrate_ist_kalman = np.empty(0) _temp_ist_kalman = np.empty(0) a = 0.5 fb = 0 rho = 0.02 temps = [{'Temp': 20, 'Duration': 1000}, {'Temp': 40, 'Duration': 1000}, {'Temp': 50, 'Duration': 1000}, {'Temp': 60, 'Duration': 1000}, {'Temp': 70, 'Duration': 1000}, {'Temp': 80, 'Duration': 1000}, {'Temp': 78, 'Duration': 1000}] t = 0 for temp in temps: temp_soll = temp['Temp'] hold_counter = temp['Duration'] hold = False ctrl.set_theta_soll(temp_soll) ctrl.set_heatrate_soll(2.5) while True: if hold: if hold_counter == 0: break hold_counter -= 1 ctrl.process() plant.process() temp_ist = plant.getTemperature() + 0.0*np.random.randn() ctrl.set_theta_ist(temp_ist) y = 3500*ctrl.get_power() power = max(0, 250+y) plant.setPower(power) fb = plant.getPower() if abs(temp_ist - temp_soll) < 0.1: hold = True temp_ist -= rho _temp_ist = np.append(_temp_ist, temp_ist) _temp_soll = np.append(_temp_soll, temp_soll) _y = np.append(_y, y) _fb = np.append(_fb, fb) _t = np.append(_t, t) _heatrate_ist_kalman = np.append(_heatrate_ist_kalman, min(3, ctrl.heatrate_ist)) _temp_ist_kalman = np.append(_temp_ist, ctrl.theta_ist) t += 1 figure(1) subplot(3, 1, 1) plot(_t, _temp_ist, _t, _temp_soll, 'r-', linewidth=1) legend(["ist", "soll"]) grid(True) subplot(3, 1, 2) plot(_t, _y, '-b', _t, _fb, '-r', linewidth=1) legend(["y", "pot"]) grid(True) subplot(3, 1, 3) plot(_t, _heatrate_ist_kalman, '-b', linewidth=1) legend(["heatrate"]) grid(True) show() print("End of program")