from components.pid.temp_controller_base import TempControllerBase class TempController(TempControllerBase): def __init__(self, dt): TempControllerBase.__init__(self, dt) self.dt = dt # None until the first process() tick - rather than hardcoding a # starting point (e.g. 20), which would make that very first # tick's heatrate come out as a bogus spike whenever the real # starting temperature isn't actually 20 (see # components/sud_forecast.py's SudForecastEstimator, which builds # a fresh TempController on every call - unlike the real one, # which only ever goes through this exactly once, it has no # earlier ticks to have already settled past that spike by). self.last_theta_ist = None self.heatrate_ist = 0 def process(self): self._require_params() # Process Kalman self.theta_ist = self.theta_ist_set heatrate = 0 if self.last_theta_ist is None else (self.theta_ist - self.last_theta_ist)/self.dt*60 alpha = 0.1 self.heatrate_ist = (1-alpha) * self.heatrate_ist + alpha*heatrate self.last_theta_ist = self.theta_ist # Compensate for max heat rate to reduce overshoot hold_scale = 1.0/self.heatrate_soll_set if self.heatrate_soll_set > 0 else 1.0 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 diff = self.theta_soll_set - self.theta_ist self.process_fsm(diff) self.process_pid(theta_err, heatrate_err, hold_scale)