- added Temp controller
- use AttributeChange for Processing objects
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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,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,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
|
||||||
|
|||||||
@@ -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__':
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user