- 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
This commit is contained in:
2019-04-23 13:04:29 +00:00
parent f088e9f4fe
commit 3742600b5a
3 changed files with 15 additions and 32 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ def results_plot(self):
grid(True) grid(True)
ylabel('°C') ylabel('°C')
subplot(4, 1, 2) 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') title('Power')
grid(True) grid(True)
ylabel('W') ylabel('W')
+13 -31
View File
@@ -25,6 +25,7 @@ class Controller(TimerListener):
self.dt = params['dt'] self.dt = params['dt']
self.params = params self.params = params
self.pid = Pid() self.pid = Pid()
self.pid_rate = Pid()
self.timer_ist = 0 self.timer_ist = 0
self.sensorTime_v = np.empty(0) self.sensorTime_v = np.empty(0)
self.theta_raw_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.heatrate_k_v = np.empty(0)
self.time_v = np.empty(0) self.time_v = np.empty(0)
self.power_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.error_v = np.empty(0)
self.time = 0 self.time = 0
self.report_interval = 1.0 self.report_interval = 1.0
@@ -199,9 +202,6 @@ class Controller(TimerListener):
# ------------------------------ # ------------------------------
# The loop # The loop
# ------------------------------ # ------------------------------
if self.ctrl_theta_soll < self.ctrl_theta:
return True
controllerStateNext = self.controllerState controllerStateNext = self.controllerState
ovenStateNext = self.ovenState ovenStateNext = self.ovenState
@@ -218,43 +218,23 @@ class Controller(TimerListener):
if ctrl_theta < self.ctrl_theta_soll: if ctrl_theta < self.ctrl_theta_soll:
ovenStateNext = ovenStates.HEAT ovenStateNext = ovenStates.HEAT
pid_err = 0
if self.ovenState == ovenStates.HEAT: 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: if (ctrl_theta + 1.0) >= self.ctrl_theta_soll:
ovenStateNext = ovenStates.HOLD ovenStateNext = ovenStates.HOLD
self.log("Set rast timer to {:0.1f} min.".format(timer_soll/60)) self.log("Set rast timer to {:0.1f} min.".format(timer_soll/60))
self.timer_ist = timer_soll self.timer_ist = timer_soll
if self.ovenState == ovenStates.HOLD: 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: if self.timer_ist == 0:
ovenStateNext = ovenStates.NOP ovenStateNext = ovenStates.NOP
doLoop = False
if self.ovenState != ovenStates.NOP: if self.ovenState != ovenStates.NOP:
if self.controllerState == controllerStates.ACQU: self.pid.process(self.dt, self.params['Hold']['Acqu']['Pid'], ctrl_theta_err)
pid_params = pid_params_acqu self.pid_rate.process(self.dt, self.params['Heat']['Acqu']['Pid'], ctrl_heatrate_err)
if abs(pid_err) < pid_thresh_acqu:
controllerStateNext = controllerStates.TRACK
if self.controllerState == controllerStates.TRACK: power_hold = max(self.params['P_min'], min(self.params['P_max'], self.params['P_max']*self.pid.get_y()))
pid_params = pid_params_track power_heat = max(self.params['P_min'], min(self.params['P_max'], self.params['P_max']*self.pid_rate.get_y()))
if abs(pid_err) > pid_thresh_track: power_soll = min(power_hold, power_heat)
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))
self.plant.setPower(power_soll) self.plant.setPower(power_soll)
power_ist = self.plant.getPower() power_ist = self.plant.getPower()
@@ -262,13 +242,15 @@ class Controller(TimerListener):
self.theta_v = np.append(self.theta_v, ctrl_theta) self.theta_v = np.append(self.theta_v, ctrl_theta)
self.heatrate_v = np.append(self.heatrate_v, ctrl_heatrate) self.heatrate_v = np.append(self.heatrate_v, ctrl_heatrate)
self.power_v = np.append(self.power_v, power_ist) 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: if ovenStateNext != self.ovenState:
self.log("{} -> {}".format(self.ovenState, ovenStateNext)) self.log("{} -> {}".format(self.ovenState, ovenStateNext))
self.pid.reset()
if ovenStateNext == ovenStates.HEAT: if ovenStateNext == ovenStates.HEAT:
self.pid_rate.reset()
self.stirrer.setSpeed(self.stirrSpeedHeat) self.stirrer.setSpeed(self.stirrSpeedHeat)
self.stirrer.setDutyCycle(1.0) self.stirrer.setDutyCycle(1.0)
@@ -289,4 +271,4 @@ class Controller(TimerListener):
else: else:
self.timer_ist = 0 self.timer_ist = 0
return self.ovenState == ovenStates.NOP
+1
View File
@@ -26,6 +26,7 @@ class Pid():
def reset(self): def reset(self):
self.yi = 0 self.yi = 0
self.xd = 0 self.xd = 0
self.diff_aw = 0.0
def process(self, dt, params, err, derr=None): def process(self, dt, params, err, derr=None):
kp = params['kp'] kp = params['kp']