- added Temp controller

- use AttributeChange for Processing objects
This commit is contained in:
jens
2020-11-29 14:35:44 +01:00
parent d16b6b272a
commit d9c587476f
7 changed files with 72 additions and 14 deletions
+44 -6
View File
@@ -46,7 +46,7 @@ class TempSensorTask(ATask):
self.kalman.initial((self.sensor.temperature(), 0)) self.kalman.initial((self.sensor.temperature(), 0))
temp = ValueChanged(self.on_temp_changed, prec=1) temp = ValueChanged(self.on_temp_changed, prec=1)
temp_kalman = ValueChanged(self.on_temp_changed_kalman, prec=1) temp_kalman = ValueChanged(self.on_temp_changed_kalman, prec=1)
self.sensor.set_on_changed("temp", temp) self.sensor.set_on_changed("temp", temp.set)
while True: while True:
self.sensor.process() self.sensor.process()
Z = self.kalman.process_measurement((self.sensor.temperature(), 0), 0) Z = self.kalman.process_measurement((self.sensor.temperature(), 0), 0)
@@ -64,6 +64,11 @@ class HeaterTask(ATask):
self.msg_handler = msg_handler self.msg_handler = msg_handler
msg_handler.set_recv_handler(self.recv) msg_handler.set_recv_handler(self.recv)
self.heater = heater self.heater = heater
self.y = 0
self.power_soll = 0
def actor(self, y):
self.y = y
async def recv(self, data): async def recv(self, data):
print(data) print(data)
@@ -82,6 +87,8 @@ class HeaterTask(ATask):
power = Value() power = Value()
while True: while True:
self.power_soll = 200 + self.heater.get_power_max()*self.y
self.heater.setPower(self.power_soll)
self.heater.process() self.heater.process()
power.set(round(self.heater.getPower())) power.set(round(self.heater.getPower()))
if power.is_changed(): if power.is_changed():
@@ -125,6 +132,31 @@ class PotTask(ATask):
await asyncio.sleep(self.interval) await asyncio.sleep(self.interval)
class TcTask(ATask):
def __init__(self, tc: temp_controller.TempController, interval, msg_handler: MsgIo):
ATask.__init__(self, interval)
self.msg_handler = msg_handler
msg_handler.set_recv_handler(self.recv)
self.tc = tc
async def recv(self, data):
print(data)
for pair in data.items():
if 'Soll' in pair[0]:
self.tc.set_theta_soll(pair[1])
async def send(self, data):
await self.msg_handler.send(data)
async def on_process(self):
print("{}: Started with interval {} s".format(self.msg_handler.get_key(), self.interval))
self.tc.set_theta_soll(20)
while True:
self.tc.process()
await asyncio.sleep(self.interval)
class TaskManager: class TaskManager:
def __init__(self): def __init__(self):
self.tasks = [] self.tasks = []
@@ -166,7 +198,7 @@ if __name__ == '__main__':
# Sensor # Sensor
sensor = TempSensorSim() sensor = TempSensorSim()
taskmgr.add(TempSensorTask(sensor, 0.2, dispatcher.msgio_get("Sensor"), kalman)) taskmgr.add(TempSensorTask(sensor, 1.0, dispatcher.msgio_get("Sensor"), kalman))
# Plant # Plant
pot_params = { pot_params = {
@@ -179,13 +211,14 @@ if __name__ == '__main__':
"kn" : 0.2 "kn" : 0.2
} }
pot = Pot(pot_params) pot = Pot(pot_params)
pot.set_on_changed("temp", ValueChanged(sensor.set_fake_temp, prec=1)) pot.set_on_changed("temp", ValueChanged(sensor.set_fake_temp, prec=1).set)
taskmgr.add(PotTask(pot, 0.1, dispatcher.msgio_get("Pot"))) taskmgr.add(PotTask(pot, 1.0, dispatcher.msgio_get("Pot")))
# Heater # Heater
heater = Heater() heater = Heater()
heater.set_on_changed("power_eff", ValueChanged(pot.setPower, prec=0)) heater.set_on_changed("power_eff", ValueChanged(pot.setPower, prec=0).set)
taskmgr.add(HeaterTask(heater, 0.02, dispatcher.msgio_get("Heater"))) heater_task = HeaterTask(heater, 1.0, dispatcher.msgio_get("Heater"))
taskmgr.add(heater_task)
# Temperature Controller # Temperature Controller
tc_params = { tc_params = {
@@ -208,7 +241,12 @@ if __name__ == '__main__':
} }
} }
tc = temp_controller.TempController(tc_params) tc = temp_controller.TempController(tc_params)
tc.set_on_changed("y_hold", heater_task.actor)
tc_task = TcTask(tc, 1.0, dispatcher.msgio_get("Tc"))
taskmgr.add(tc_task)
sensor.set_on_changed("temp", ValueChanged(tc.set_theta_ist, prec=1).set)
# Message dispatcher
h_dispatcher = taskmgr.start() h_dispatcher = taskmgr.start()
h_server = server.listen("localhost", 8765) h_server = server.listen("localhost", 8765)
asyncio.gather(h_dispatcher, h_server) asyncio.gather(h_dispatcher, h_server)
+2 -1
View File
@@ -3,12 +3,13 @@ from components.aheater import AHeater
class Heater(AHeater): class Heater(AHeater):
def __init__(self): def __init__(self):
AHeater.__init__(self)
self.power_set = self.get_power_min() self.power_set = self.get_power_min()
self.is_active = False self.is_active = False
self.power_eff = 0 self.power_eff = 0
def get_power_min(self): def get_power_min(self):
return 500 return 0
def get_power_max(self): def get_power_max(self):
return 3500 return 3500
+3
View File
@@ -3,6 +3,9 @@ from utils.value import AttributeChange
class AHeater(AttributeChange): class AHeater(AttributeChange):
def __init__(self):
AttributeChange.__init__(self)
@abc.abstractmethod @abc.abstractmethod
def get_power_min(self): def get_power_min(self):
pass pass
+3
View File
@@ -3,6 +3,9 @@ from utils.value import AttributeChange
class APlant(AttributeChange): class APlant(AttributeChange):
def __init__(self):
AttributeChange.__init__(self)
@abc.abstractmethod @abc.abstractmethod
def activate(self, enable): def activate(self, enable):
return None return None
+11 -3
View File
@@ -1,10 +1,13 @@
from components.pid.pid import Pid from components.pid.pid import Pid
from matplotlib.pyplot import plot, figure, subplot, title, xlabel, ylabel, grid, show from matplotlib.pyplot import plot, figure, subplot, title, xlabel, ylabel, grid, show
import numpy as np import numpy as np
from utils.value import AttributeChange
class TempController: class TempController(AttributeChange):
def __init__(self, params): def __init__(self, params):
AttributeChange.__init__(self)
self.dt = params['dt'] self.dt = params['dt']
self.pid_hold = Pid() self.pid_hold = Pid()
self.pid_rate = Pid() self.pid_rate = Pid()
@@ -13,6 +16,8 @@ class TempController:
self.heatrate_ist = 0 self.heatrate_ist = 0
self.heatrate_soll = 0 self.heatrate_soll = 0
self.params = params self.params = params
self.y_hold = 0
self.y_heat = 0
def set_theta_ist(self, value): def set_theta_ist(self, value):
self.theta_ist = value self.theta_ist = value
@@ -33,11 +38,14 @@ class TempController:
self.pid_hold.process(self.dt, self.params['Hold']['Pid'], theta_err) self.pid_hold.process(self.dt, self.params['Hold']['Pid'], theta_err)
self.pid_rate.process(self.dt, self.params['Heat']['Pid'], heatrate_err) self.pid_rate.process(self.dt, self.params['Heat']['Pid'], heatrate_err)
self.y_hold = self.pid_hold.get_y()
self.y_heat = self.pid_rate.get_y()
def get_power_hold(self): def get_power_hold(self):
return self.pid_hold.get_y() return self.y_hold
def get_power_heat(self): def get_power_heat(self):
return self.pid_rate.get_y() return self.y_heat
if __name__ == '__main__': if __name__ == '__main__':
+1
View File
@@ -4,6 +4,7 @@ from components.aplant import APlant
class Pot(APlant): class Pot(APlant):
def __init__(self, params): def __init__(self, params):
APlant.__init__(self)
self.dt = params['dt'] self.dt = params['dt']
self.alpha = 1.0 self.alpha = 1.0
+8 -4
View File
@@ -33,11 +33,14 @@ class ValueChanged(object):
class AttributeChange(object): class AttributeChange(object):
callbacks = {} def __init__(self):
self.callbacks = {}
def set_on_changed(self, key, on_changed: ValueChanged): def set_on_changed(self, key, on_changed):
if key not in self.callbacks: if key not in self.callbacks:
self.callbacks[key] = on_changed self.callbacks[key] = [on_changed]
else:
self.callbacks[key].append(on_changed)
def __setattr__(self, key, value): def __setattr__(self, key, value):
try: try:
@@ -48,4 +51,5 @@ class AttributeChange(object):
super().__setattr__(key, value) super().__setattr__(key, value)
if key in self.callbacks: if key in self.callbacks:
self.callbacks[key].set(value) for cb in self.callbacks[key]:
cb(value)