Files
brewpi/components/pid/temp_controller.py
T

212 lines
4.9 KiB
Python

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, 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_pid, params_kalman):
AttributeChange.__init__(self)
self.pid_hold = pid.Pid(params_pid['Hold'])
self.pid_rate = pid.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.theta_ist = 0
self.heatrate_ist = 0
self.params = params_pid
self.kalman = kalman.Kalman(params_kalman)
self.y = 0
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
theta_err = self.theta_soll_set - self.theta_ist
heatrate_err = self.heatrate_soll_set - 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_hold.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()
if self.state != States.IDLE:
self.pid_hold.process(theta_err)
self.pid_rate.process(heatrate_err)
if self.state == States.HEAT:
self.y = self.pid_rate.get_y()
elif self.state == States.HOLD:
self.y = self.pid_hold.get_y()
else:
self.y = 0
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.005,
"kd": 0.0,
"rho": 1.0
},
"Heat": {
"dt": 1.0,
"kp": 0.1,
"ki": 0.01,
"kd": 0.0,
"rho": 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.0)
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, 0+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")