From 3742600b5a019dec0035c6caf8be6ac9f271cf77 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Tue, 23 Apr 2019 13:04:29 +0000 Subject: [PATCH] - Controller have separate PID controller for heat and hold - do actor fusion - PID : fixed reset() git-svn-id: http://moon:8086/svn/projects/HendiControl@259 fda53097-d464-4ada-af97-ba876c37ca34 --- Control/brewpi/brewpi.py | 2 +- Control/brewpi/controller.py | 44 +++++++++++------------------------- Control/brewpi/pid.py | 1 + 3 files changed, 15 insertions(+), 32 deletions(-) diff --git a/Control/brewpi/brewpi.py b/Control/brewpi/brewpi.py index d76ffd8..b5d887d 100755 --- a/Control/brewpi/brewpi.py +++ b/Control/brewpi/brewpi.py @@ -29,7 +29,7 @@ def results_plot(self): grid(True) ylabel('°C') subplot(4, 1, 2) - plot(self.time_v, self.power_v, 'b-', linewidth=1) + plot(self.time_v, self.power_heat_v, self.time_v, self.power_hold_v, self.time_v, self.power_v, 'r-', linewidth=1) title('Power') grid(True) ylabel('W') diff --git a/Control/brewpi/controller.py b/Control/brewpi/controller.py index d3ee1ce..1c00661 100644 --- a/Control/brewpi/controller.py +++ b/Control/brewpi/controller.py @@ -25,6 +25,7 @@ class Controller(TimerListener): self.dt = params['dt'] self.params = params self.pid = Pid() + self.pid_rate = Pid() self.timer_ist = 0 self.sensorTime_v = np.empty(0) self.theta_raw_v = np.empty(0) @@ -34,6 +35,8 @@ class Controller(TimerListener): self.heatrate_k_v = np.empty(0) self.time_v = np.empty(0) self.power_v = np.empty(0) + self.power_heat_v = np.empty(0) + self.power_hold_v = np.empty(0) self.error_v = np.empty(0) self.time = 0 self.report_interval = 1.0 @@ -199,9 +202,6 @@ class Controller(TimerListener): # ------------------------------ # The loop # ------------------------------ - if self.ctrl_theta_soll < self.ctrl_theta: - return True - controllerStateNext = self.controllerState ovenStateNext = self.ovenState @@ -218,43 +218,23 @@ class Controller(TimerListener): if ctrl_theta < self.ctrl_theta_soll: ovenStateNext = ovenStates.HEAT - pid_err = 0 if self.ovenState == ovenStates.HEAT: - pid_err = ctrl_heatrate_err - pid_params_acqu = self.params['Heat']['Acqu']['Pid'] - pid_params_track = self.params['Heat']['Track']['Pid'] - pid_thresh_acqu = self.params['Heat']['Acqu']['thresh_leave'] - pid_thresh_track = self.params['Heat']['Track']['thresh_leave'] if (ctrl_theta + 1.0) >= self.ctrl_theta_soll: ovenStateNext = ovenStates.HOLD self.log("Set rast timer to {:0.1f} min.".format(timer_soll/60)) self.timer_ist = timer_soll if self.ovenState == ovenStates.HOLD: - pid_err = ctrl_theta_err - pid_params_acqu = self.params['Hold']['Acqu']['Pid'] - pid_params_track = self.params['Hold']['Track']['Pid'] - pid_thresh_acqu = self.params['Heat']['Acqu']['thresh_leave'] - pid_thresh_track = self.params['Heat']['Track']['thresh_leave'] if self.timer_ist == 0: ovenStateNext = ovenStates.NOP - doLoop = False if self.ovenState != ovenStates.NOP: - if self.controllerState == controllerStates.ACQU: - pid_params = pid_params_acqu - if abs(pid_err) < pid_thresh_acqu: - controllerStateNext = controllerStates.TRACK + self.pid.process(self.dt, self.params['Hold']['Acqu']['Pid'], ctrl_theta_err) + self.pid_rate.process(self.dt, self.params['Heat']['Acqu']['Pid'], ctrl_heatrate_err) - if self.controllerState == controllerStates.TRACK: - pid_params = pid_params_track - if abs(pid_err) > pid_thresh_track: - controllerStateNext = controllerStates.ACQU - - self.pid.process(self.dt, pid_params, pid_err) - - y = self.pid.get_y() - power_soll = max(self.params['P_min'], min(self.params['P_max'], self.params['P_max']*y)) + power_hold = max(self.params['P_min'], min(self.params['P_max'], self.params['P_max']*self.pid.get_y())) + power_heat = max(self.params['P_min'], min(self.params['P_max'], self.params['P_max']*self.pid_rate.get_y())) + power_soll = min(power_hold, power_heat) self.plant.setPower(power_soll) power_ist = self.plant.getPower() @@ -262,13 +242,15 @@ class Controller(TimerListener): self.theta_v = np.append(self.theta_v, ctrl_theta) self.heatrate_v = np.append(self.heatrate_v, ctrl_heatrate) self.power_v = np.append(self.power_v, power_ist) - self.error_v = np.append(self.error_v, pid_err) + self.power_hold_v = np.append(self.power_hold_v, power_hold) + self.power_heat_v = np.append(self.power_heat_v, power_heat) + self.error_v = np.append(self.error_v, ctrl_theta_err) # ----------------------------------------- if ovenStateNext != self.ovenState: self.log("{} -> {}".format(self.ovenState, ovenStateNext)) - self.pid.reset() if ovenStateNext == ovenStates.HEAT: + self.pid_rate.reset() self.stirrer.setSpeed(self.stirrSpeedHeat) self.stirrer.setDutyCycle(1.0) @@ -289,4 +271,4 @@ class Controller(TimerListener): else: self.timer_ist = 0 - + return self.ovenState == ovenStates.NOP diff --git a/Control/brewpi/pid.py b/Control/brewpi/pid.py index 687e02d..080d097 100644 --- a/Control/brewpi/pid.py +++ b/Control/brewpi/pid.py @@ -26,6 +26,7 @@ class Pid(): def reset(self): self.yi = 0 self.xd = 0 + self.diff_aw = 0.0 def process(self, dt, params, err, derr=None): kp = params['kp']