- added abstarct PID APid

- added PidFactory
- use variable args for factory
This commit is contained in:
jens
2021-10-02 11:10:43 +02:00
parent 7111bfd5e2
commit bf019733b2
15 changed files with 117 additions and 26 deletions
+3 -3
View File
@@ -5,7 +5,7 @@ from utils import ChangedFloat
from ws.message import MessageDispatcher from ws.message import MessageDispatcher
from ws.server.ws_server_multi_user import WsServerMultiUser from ws.server.ws_server_multi_user import WsServerMultiUser
from components.sensor import TempSensorFactory from components.sensor import TempSensorFactory
from components.pid import TempController from components.pid import PidFactory
from components.plant import Pot from components.plant import Pot
from components.actor import HeaterFactory, StirrerFactory from components.actor import HeaterFactory, StirrerFactory
from tasks import TaskManager, TempSensorTask, HeaterTask, PotTask, TcTask, StirrerTask, TracerTask from tasks import TaskManager, TempSensorTask, HeaterTask, PotTask, TcTask, StirrerTask, TracerTask
@@ -31,14 +31,14 @@ if __name__ == '__main__':
taskmgr.add(PotTask(pot, DT_TASK, dispatcher.msgio_get("Pot"))) taskmgr.add(PotTask(pot, DT_TASK, dispatcher.msgio_get("Pot")))
# Heater # Heater
heater = HeaterFactory.create(config['Controller']['heater_name'], DT, config['Heater']) heater = HeaterFactory.create(config['Controller']['heater_name'], config['Heater'])
heater.set_on_changed("power_eff", ChangedFloat(pot.set_power, prec=0).set) heater.set_on_changed("power_eff", ChangedFloat(pot.set_power, prec=0).set)
heater_task = HeaterTask(heater, DT_TASK, dispatcher.msgio_get("Heater")) heater_task = HeaterTask(heater, DT_TASK, dispatcher.msgio_get("Heater"))
taskmgr.add(heater_task) taskmgr.add(heater_task)
# Temperature Controller # Temperature Controller
tc_params = config['TempCtrl'] tc_params = config['TempCtrl']
tc = TempController(DT, tc_params) tc = PidFactory.create('Normal', DT, tc_params)
tc.set_on_changed("y", heater_task.actor) tc.set_on_changed("y", heater_task.actor)
tc_task = TcTask(tc, DT_TASK, dispatcher.msgio_get("TempCtrl")) tc_task = TcTask(tc, DT_TASK, dispatcher.msgio_get("TempCtrl"))
taskmgr.add(tc_task) taskmgr.add(tc_task)
+1
View File
@@ -1,3 +1,4 @@
from components.atemperatureSensor import * from components.atemperatureSensor import *
from components.astirrer import * from components.astirrer import *
from components.aheater import * from components.aheater import *
from components.apid import *
+5 -3
View File
@@ -2,10 +2,12 @@
class HeaterFactory: class HeaterFactory:
@staticmethod @staticmethod
def create(name, dt, params): def create(name, *args, **kwargs):
if "sim" in name: if "sim" in name:
from components.actor.heater_sim import HeaterSim from components.actor.heater_sim import HeaterSim
return HeaterSim() print (*args)
print (**kwargs)
return HeaterSim(*args, **kwargs)
elif "Hendi" in name: elif "Hendi" in name:
from components.actor.heater_hendi import HeaterHendi from components.actor.heater_hendi import HeaterHendi
return HeaterHendi(params) return HeaterHendi(*args, **kwargs)
+1 -1
View File
@@ -2,7 +2,7 @@ from components.aheater import AHeater
class HeaterSim(AHeater): class HeaterSim(AHeater):
def __init__(self): def __init__(self, params):
AHeater.__init__(self) AHeater.__init__(self)
self.power_set = 0 self.power_set = 0
self.power_eff = 0 self.power_eff = 0
+43
View File
@@ -0,0 +1,43 @@
import abc
from utils.value import AttributeChange
class APid(AttributeChange):
def __init__(self):
AttributeChange.__init__(self)
@abc.abstractmethod
def set_theta_soll(self, value):
return None
@abc.abstractmethod
def set_heatrate_soll(self, value):
return None
@abc.abstractmethod
def get_theta_ist(self):
return None
@abc.abstractmethod
def get_heatrate_ist(self):
return None
@abc.abstractmethod
def get_theta_soll_set(self):
return None
@abc.abstractmethod
def get_theta_soll(self):
return None
@abc.abstractmethod
def get_heatrate_soll_set(self):
return None
@abc.abstractmethod
def get_heatrate_soll(self):
return None
@abc.abstractmethod
def process(self):
pass
+1 -1
View File
@@ -1,3 +1,3 @@
from components.pid.pid import * from components.pid.pid import *
from components.pid.kalman import * from components.pid.kalman import *
from components.pid.temp_controller_smith import * from components.pid.pid_factory import PidFactory
+11
View File
@@ -0,0 +1,11 @@
class PidFactory:
@staticmethod
def create(name, *args, **kwargs):
if "Normal" in name:
from components.pid.temp_controller import TempController
return TempController(*args, **kwargs)
elif "Smith" in name:
from components.pid.temp_controller_smith import TempController
return TempController(*args, **kwargs)
+3 -3
View File
@@ -1,8 +1,8 @@
from components.plant.pot import Pot from components.plant.pot import Pot
from matplotlib.pyplot import plot, figure, subplot, grid, show, legend from matplotlib.pyplot import plot, figure, subplot, grid, show, legend
from components.pid import Pid, Kalman from components.pid import Pid, Kalman
from components import APid
import numpy as np import numpy as np
from utils.value import AttributeChange
from enum import Enum from enum import Enum
@@ -12,9 +12,9 @@ class States(Enum):
HOLD = 2 HOLD = 2
class TempController(AttributeChange): class TempController(APid):
def __init__(self, dt, params): def __init__(self, dt, params):
AttributeChange.__init__(self) APid.__init__(self)
self.pid_hold = Pid(dt) self.pid_hold = Pid(dt)
self.pid_rate = Pid(dt) self.pid_rate = Pid(dt)
self.theta_ist_set = 20 self.theta_ist_set = 20
+21 -3
View File
@@ -1,8 +1,8 @@
from components.plant.pot import Pot, Delay from components.plant.pot import Pot, Delay
from matplotlib.pyplot import plot, figure, subplot, grid, show, legend from matplotlib.pyplot import plot, figure, subplot, grid, show, legend
from components.pid import Pid, Kalman from components.pid import Pid, Kalman
from components import APid
import numpy as np import numpy as np
from utils.value import AttributeChange
from enum import Enum from enum import Enum
@@ -12,9 +12,9 @@ class States(Enum):
HOLD = 2 HOLD = 2
class TempController(AttributeChange): class TempController(APid):
def __init__(self, dt, params): def __init__(self, dt, params):
AttributeChange.__init__(self) APid.__init__(self)
self.pid_hold = Pid(dt) self.pid_hold = Pid(dt)
self.pid_rate = Pid(dt) self.pid_rate = Pid(dt)
self.theta_ist_set = 20 self.theta_ist_set = 20
@@ -41,15 +41,33 @@ class TempController(AttributeChange):
def set_theta_ist(self, value): def set_theta_ist(self, value):
self.theta_ist_set = value self.theta_ist_set = value
def get_theta_ist(self):
return self.theta_ist
def set_heatrate_ist(self, value): def set_heatrate_ist(self, value):
self.heatrate_ist_set = value self.heatrate_ist_set = value
def get_heatrate_ist(self):
return self.heatrate_ist
def set_theta_soll(self, value): def set_theta_soll(self, value):
self.theta_soll_set = value self.theta_soll_set = value
def get_theta_soll(self):
return self.theta_soll
def get_theta_soll_set(self):
return self.theta_soll_set
def set_heatrate_soll(self, value): def set_heatrate_soll(self, value):
self.heatrate_soll_set = value self.heatrate_soll_set = value
def get_heatrate_soll(self):
return self.heatrate_soll
def get_heatrate_soll_set(self):
return self.heatrate_soll_set
def process(self): def process(self):
# Process Kalman of Model # Process Kalman of Model
Z_model = self.kalman_model.process_measurement((self.model.get_temperature_intermediate(), 0), 0.0) Z_model = self.kalman_model.process_measurement((self.model.get_temperature_intermediate(), 0), 0.0)
+4 -4
View File
@@ -6,8 +6,9 @@ class TempSensorSim(ATemperatureSensor):
def name(self): def name(self):
return "FakeTemp" return "FakeTemp"
def __init__(self): def __init__(self, temp_offset=0):
ATemperatureSensor.__init__(self) ATemperatureSensor.__init__(self)
self.temp_offset = temp_offset
self.temp = 22.37 self.temp = 22.37
self.temp_set = self.temp self.temp_set = self.temp
self.k_noise = 0.01 self.k_noise = 0.01
@@ -16,8 +17,7 @@ class TempSensorSim(ATemperatureSensor):
self.temp_set = temp self.temp_set = temp
def temperature(self): def temperature(self):
return self.temp_set + self.k_noise * np.random.normal(0, 1) / np.sqrt(12.0) return self.temp_offset + self.temp
def process(self): def process(self):
temp = self.temperature() self.temp = self.temp_set + self.k_noise * np.random.normal(0, 1) / np.sqrt(12.0)
self.temp = temp
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python3 #!/usr/bin/env python3
import time import time
from components import ATemperatureSensor from components import ATemperatureSensor
import spidev import spidev
+3 -3
View File
@@ -2,10 +2,10 @@
class TempSensorFactory: class TempSensorFactory:
@staticmethod @staticmethod
def create(name): def create(name, *args, **kwargs):
if "sim" in name: if "sim" in name:
from components.sensor.tempSensorSim import TempSensorSim from components.sensor.tempSensorSim import TempSensorSim
return TempSensorSim() return TempSensorSim(*args, **kwargs)
elif "31865" in name: elif "31865" in name:
from components.sensor.tempSensor_max31865 import TempSensor_max31865 from components.sensor.tempSensor_max31865 import TempSensor_max31865
return TempSensor_max31865(temp_offset=0) return TempSensor_max31865(*args, **kwargs)
+16
View File
@@ -26,11 +26,27 @@
function retval = results() function retval = results()
load brewpi.mat load brewpi.mat
close all;
figure(1)
set(0, "defaultlinelinewidth", 1.5); set(0, "defaultlinelinewidth", 1.5);
subplot(3,1,1) subplot(3,1,1)
plot(time, tc_temp_soll, time, tc_temp_ist); grid plot(time, tc_temp_soll, time, tc_temp_ist); grid
legend("Temp_{soll}","Temp_{ist}") legend("Temp_{soll}","Temp_{ist}")
subplot(3,1,2) subplot(3,1,2)
plot(time, tc_temp_ist-tc_temp_soll, "ro"); grid
legend("Temp_{ist} - dTemp_{soll}")
subplot(3,1,3)
plot(time, heater_power); grid
legend("Power_{Heater}")
figure(2)
subplot(3,1,1)
plot(time, tc_temp_soll, time, tc_temp_ist); grid
legend("Temp_{soll}","Temp_{ist}")
subplot(3,1,2)
plot(time, tc_dtemp_soll, time, tc_dtemp_ist, time, tc_dtemp_commanded); grid plot(time, tc_dtemp_soll, time, tc_dtemp_ist, time, tc_dtemp_commanded); grid
legend("dTemp_{soll}","dTemp_{ist}","dTemp_{cmd}") legend("dTemp_{soll}","dTemp_{ist}","dTemp_{cmd}")
subplot(3,1,3) subplot(3,1,3)
+2 -2
View File
@@ -2,11 +2,11 @@ import asyncio
from tasks import ATask from tasks import ATask
from ws.message import MsgIo from ws.message import MsgIo
from utils.value import ChangedFloat from utils.value import ChangedFloat
from components.pid import TempController from components import APid
class TcTask(ATask): class TcTask(ATask):
def __init__(self, tc: TempController, interval, msg_handler: MsgIo): def __init__(self, tc: APid, interval, msg_handler: MsgIo):
ATask.__init__(self, interval) ATask.__init__(self, interval)
self.tc = tc self.tc = tc
+2 -2
View File
@@ -4,14 +4,14 @@ from tasks import ATask
from ws.message import MsgIo from ws.message import MsgIo
from components import ATemperatureSensor from components import ATemperatureSensor
from components import AHeater from components import AHeater
from components.pid import TempController from components import APid
import numpy as np import numpy as np
import scipy.io import scipy.io
class TracerTask(ATask): class TracerTask(ATask):
def __init__(self, sensor: ATemperatureSensor, heater: AHeater, temp_ctrl: TempController, interval, msg_handler: MsgIo): def __init__(self, sensor: ATemperatureSensor, heater: AHeater, temp_ctrl: APid, interval, msg_handler: MsgIo):
ATask.__init__(self, interval) ATask.__init__(self, interval)
self.msg_handler = msg_handler self.msg_handler = msg_handler