- tempcontroller: added heat rate control
This commit is contained in:
@@ -105,7 +105,7 @@ if __name__ == '__main__':
|
||||
params = {
|
||||
'dt' : dt,
|
||||
'var_P' : 1,
|
||||
'var_Q' : 0.001,
|
||||
'var_Q' : 0.0001,
|
||||
'var_R' : 1
|
||||
}
|
||||
k = Kalman(params)
|
||||
@@ -115,7 +115,7 @@ if __name__ == '__main__':
|
||||
_x2 = np.empty(0)
|
||||
_y2 = np.empty(0)
|
||||
|
||||
N = int(100/dt)
|
||||
N = int(1000/dt)
|
||||
seqn = range(0, N)
|
||||
|
||||
_seqn = range(0, 2*N)
|
||||
|
||||
@@ -35,10 +35,6 @@ class Pid:
|
||||
yd = kd/dt*(err - self.err)
|
||||
yp = kp * err
|
||||
|
||||
# Reset yi on error sign changes
|
||||
if yp > self.y_max or yp <= self.y_min:
|
||||
self.yi = 0
|
||||
|
||||
self.err = err
|
||||
|
||||
y = yp + self.yi + yd
|
||||
|
||||
@@ -1,52 +1,91 @@
|
||||
from components.pid.pid import Pid
|
||||
from components.pid import pid
|
||||
from components.pid import kalman
|
||||
from components.plant.pot import Pot
|
||||
from matplotlib.pyplot import plot, figure, subplot, title, xlabel, ylabel, grid, show
|
||||
from matplotlib.pyplot import plot, figure, subplot, title, xlabel, ylabel, grid, show, legend
|
||||
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):
|
||||
def __init__(self, params, params_kalman):
|
||||
AttributeChange.__init__(self)
|
||||
|
||||
self.dt = params['dt']
|
||||
self.pid_hold = Pid()
|
||||
self.pid_rate = Pid()
|
||||
self.pid_hold = pid.Pid()
|
||||
self.pid_rate = pid.Pid()
|
||||
self.theta_ist_set = 0
|
||||
self.theta_soll_set = 0
|
||||
self.heatrate_ist_set = 0
|
||||
self.heatrate_soll_set = 2.0
|
||||
self.theta_ist = 0
|
||||
self.theta_soll = 0
|
||||
self.heatrate_ist = 0
|
||||
self.heatrate_soll = 0
|
||||
self.params = params
|
||||
self.y_hold = 0
|
||||
self.y_heat = 0
|
||||
self.kalman = kalman.Kalman(params_kalman)
|
||||
self.y = 0
|
||||
self.state = States.HOLD
|
||||
self.use_kalman = True
|
||||
self.kalman.initial((20, 0))
|
||||
|
||||
def set_theta_ist(self, value):
|
||||
self.theta_ist = value
|
||||
self.theta_ist_set = value
|
||||
|
||||
def set_heatrate_ist(self, value):
|
||||
self.heatrate_ist = value
|
||||
self.heatrate_ist_set = value
|
||||
|
||||
def set_theta_soll(self, value):
|
||||
self.theta_soll = value
|
||||
self.theta_soll_set = value
|
||||
|
||||
def set_heatrate_soll(self, value):
|
||||
self.heatrate_soll = value
|
||||
self.heatrate_soll_set = value
|
||||
|
||||
def process(self):
|
||||
theta_err = self.theta_soll - self.theta_ist
|
||||
heatrate_err = self.heatrate_soll - self.heatrate_ist
|
||||
# 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.pid_hold.process(self.dt, self.params['Hold']['Pid'], theta_err)
|
||||
self.pid_rate.process(self.dt, self.params['Heat']['Pid'], heatrate_err)
|
||||
theta_err = self.theta_soll_set - self.theta_ist
|
||||
heatrate_err = self.heatrate_soll_set - self.heatrate_ist
|
||||
|
||||
self.y_hold = self.pid_hold.get_y()
|
||||
self.y_heat = self.pid_rate.get_y()
|
||||
# Process state
|
||||
state_next = self.state
|
||||
if self.state == States.HOLD:
|
||||
if (self.theta_ist + 1.0) < self.theta_soll_set:
|
||||
state_next = States.HEAT
|
||||
self.pid_rate.reset()
|
||||
elif self.state == States.HEAT:
|
||||
if (self.theta_ist + 1.0) >= self.theta_soll_set:
|
||||
state_next = States.HOLD
|
||||
self.pid_hold.reset()
|
||||
|
||||
def get_power_hold(self):
|
||||
return self.y_hold
|
||||
if self.state != States.IDLE:
|
||||
self.pid_hold.process(self.dt, self.params['Hold']['Pid'], theta_err)
|
||||
self.pid_rate.process(self.dt, self.params['Heat']['Pid'], heatrate_err)
|
||||
|
||||
def get_power_heat(self):
|
||||
return self.y_heat
|
||||
if self.state == States.HEAT:
|
||||
self.y = self.pid_rate.get_y()
|
||||
else:
|
||||
self.y = self.pid_hold.get_y()
|
||||
|
||||
if state_next != self.state:
|
||||
print("New state = {}".format(state_next))
|
||||
|
||||
self.state = state_next
|
||||
|
||||
def get_power(self):
|
||||
return self.y
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
@@ -54,16 +93,16 @@ if __name__ == '__main__':
|
||||
"dt": 1.0,
|
||||
"Hold": {
|
||||
"Pid": {
|
||||
"kp": 0.8,
|
||||
"ki": 0.008,
|
||||
"kp": 0.5,
|
||||
"ki": 0.005,
|
||||
"kd": 0.0,
|
||||
"rho": 1.0
|
||||
}
|
||||
},
|
||||
"Heat": {
|
||||
"Pid": {
|
||||
"kp": 0.002,
|
||||
"ki": 0.0002,
|
||||
"kp": 0.1,
|
||||
"ki": 0.01,
|
||||
"kd": 0.0,
|
||||
"rho": 1.0
|
||||
}
|
||||
@@ -80,19 +119,28 @@ if __name__ == '__main__':
|
||||
"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)
|
||||
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}]
|
||||
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:
|
||||
@@ -100,6 +148,7 @@ if __name__ == '__main__':
|
||||
hold_counter = temp['Duration']
|
||||
hold = False
|
||||
ctrl.set_theta_soll(temp_soll)
|
||||
ctrl.set_heatrate_soll(2.0)
|
||||
|
||||
while True:
|
||||
if hold:
|
||||
@@ -108,11 +157,13 @@ if __name__ == '__main__':
|
||||
hold_counter -= 1
|
||||
ctrl.process()
|
||||
plant.process()
|
||||
y = max(0, 3500*ctrl.get_power_hold())
|
||||
plant.setPower(y)
|
||||
temp_ist = round(plant.getTemperature(), 1)
|
||||
fb = plant.getPower()
|
||||
temp_ist = plant.getTemperature() + 0.0*np.random.randn()
|
||||
ctrl.set_theta_ist(temp_ist)
|
||||
|
||||
y = 3500*ctrl.get_power()
|
||||
power = max(0, 0+y)
|
||||
plant.setPower(power)
|
||||
fb = plant.getPower()
|
||||
if abs(temp_ist - temp_soll) < 0.1:
|
||||
hold = True
|
||||
|
||||
@@ -122,14 +173,22 @@ if __name__ == '__main__':
|
||||
_y = np.append(_y, y)
|
||||
_fb = np.append(_fb, fb)
|
||||
_t = np.append(_t, t)
|
||||
_heatrate_ist_kalman = np.append(_heatrate_ist_kalman, min(3000, ctrl.heatrate_ist))
|
||||
_temp_ist_kalman = np.append(_temp_ist, ctrl.theta_ist)
|
||||
t += 1
|
||||
|
||||
figure(1)
|
||||
subplot(2, 1, 1)
|
||||
subplot(3, 1, 1)
|
||||
plot(_t, _temp_ist, _t, _temp_soll, 'r-', linewidth=1)
|
||||
legend(["ist", "soll"])
|
||||
grid(True)
|
||||
subplot(2, 1, 2)
|
||||
plot(_t, _y, 'bx', _t, _fb, '-r', linewidth=1)
|
||||
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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user