- improved logging
git-svn-id: http://moon:8086/svn/projects/HendiControl@117 fda53097-d464-4ada-af97-ba876c37ca34
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
{
|
{
|
||||||
"time" : 15,
|
"time" : 15,
|
||||||
"temp" : 50.0,
|
"temp" : 50.0,
|
||||||
"heatRate" : 0.25,
|
"heatRate" : 1.20,
|
||||||
"waitForUser" : true
|
"waitForUser" : true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import numpy as np
|
import time
|
||||||
import abc
|
import abc
|
||||||
|
|
||||||
|
|
||||||
@@ -6,6 +6,9 @@ class APlant(abc.ABC):
|
|||||||
def __init__(self, params):
|
def __init__(self, params):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def log(self, s):
|
||||||
|
print("{:.2f}: {}".format(time.time(), s))
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def process(self):
|
def process(self):
|
||||||
pass
|
pass
|
||||||
@@ -14,6 +17,10 @@ class APlant(abc.ABC):
|
|||||||
def setPower(self, power_W):
|
def setPower(self, power_W):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def getPower(self):
|
||||||
|
return None
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def getTemperature(self):
|
def getTemperature(self):
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import numpy as np
|
import time
|
||||||
import abc
|
import abc
|
||||||
|
|
||||||
|
|
||||||
@@ -6,6 +6,9 @@ class AStirrer(abc.ABC):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def log(self, s):
|
||||||
|
print("{:.2f}: {}".format(time.time(), s))
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def process(self):
|
def process(self):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from enum import Enum
|
|||||||
from pid import Pid
|
from pid import Pid
|
||||||
from matplotlib.pyplot import figure, clf, plot, xlabel, ylabel, xlim, ylim, title, grid, axes, show, subplot
|
from matplotlib.pyplot import figure, clf, plot, xlabel, ylabel, xlim, ylim, title, grid, axes, show, subplot
|
||||||
from utils import Smoother, Stable
|
from utils import Smoother, Stable
|
||||||
|
import time
|
||||||
|
|
||||||
ovenStates = Enum('ovenStates', 'NOP HEAT HOLD')
|
ovenStates = Enum('ovenStates', 'NOP HEAT HOLD')
|
||||||
controllerStates = Enum('controllerStates', 'ACQU TRACK')
|
controllerStates = Enum('controllerStates', 'ACQU TRACK')
|
||||||
@@ -20,12 +21,31 @@ class Controller():
|
|||||||
self.dt = params['dt']
|
self.dt = params['dt']
|
||||||
self.params = params
|
self.params = params
|
||||||
self.pid = Pid()
|
self.pid = Pid()
|
||||||
|
self.theta_ist = 0
|
||||||
|
self.heatrate_ist = 0
|
||||||
self.theta_v = np.empty(0)
|
self.theta_v = np.empty(0)
|
||||||
self.heatrate_v = np.empty(0)
|
self.heatrate_v = np.empty(0)
|
||||||
self.time_v = np.empty(0)
|
self.time_v = np.empty(0)
|
||||||
self.power_v = np.empty(0)
|
self.power_v = np.empty(0)
|
||||||
self.error_v = np.empty(0)
|
self.error_v = np.empty(0)
|
||||||
self.time = 0
|
self.time = 0
|
||||||
|
self.sim_warp_factor = 10
|
||||||
|
self.log_report_interval = 1.0
|
||||||
|
self.log_last_time = 0
|
||||||
|
|
||||||
|
def log(self, s):
|
||||||
|
now = time.time()
|
||||||
|
print("{:.2f}: {}".format(now, s))
|
||||||
|
|
||||||
|
def report(self):
|
||||||
|
now = time.time()
|
||||||
|
if (now - self.log_last_time) >= self.log_report_interval:
|
||||||
|
|
||||||
|
self.log("Temp IST = {:0.2f} °C".format(self.theta_ist))
|
||||||
|
self.log("Heatrate IST = {:0.2f} °C/min.".format(self.heatrate_ist))
|
||||||
|
self.log("Power = {:0.2f} W".format(self.plant.getPower()))
|
||||||
|
# self.log("theta_err = {:0.2f} °C".format(theta_err))
|
||||||
|
self.log_last_time = now
|
||||||
|
|
||||||
def start(self, recipe):
|
def start(self, recipe):
|
||||||
print(json.dumps({recipe['Name'] : recipe}, indent=4, sort_keys=True))
|
print(json.dumps({recipe['Name'] : recipe}, indent=4, sort_keys=True))
|
||||||
@@ -73,10 +93,10 @@ class Controller():
|
|||||||
self.stirrer.setCycleTime(self.stirrCycleTime)
|
self.stirrer.setCycleTime(self.stirrCycleTime)
|
||||||
|
|
||||||
# Temperature
|
# Temperature
|
||||||
theta_last = self.plant.getTemperature()
|
self.theta_ist = self.plant.getTemperature()
|
||||||
theta_soll = rast['temp']
|
theta_soll = rast['temp']
|
||||||
heatrate_soll = rast['heatRate']
|
heatrate_soll = rast['heatRate']
|
||||||
print("Target temperature {} °C".format(theta_soll))
|
self.log("Target temperature {} °C".format(theta_soll))
|
||||||
|
|
||||||
# Timer
|
# Timer
|
||||||
timer_ist = 0
|
timer_ist = 0
|
||||||
@@ -89,6 +109,8 @@ class Controller():
|
|||||||
theta_err_sm = Smoother(0.5)
|
theta_err_sm = Smoother(0.5)
|
||||||
heatrate_err_sm = Smoother(0.5)
|
heatrate_err_sm = Smoother(0.5)
|
||||||
while(doLoop):
|
while(doLoop):
|
||||||
|
time_start = time.time()
|
||||||
|
|
||||||
controllerStateNext = self.controllerState
|
controllerStateNext = self.controllerState
|
||||||
ovenStateNext = self.ovenState
|
ovenStateNext = self.ovenState
|
||||||
|
|
||||||
@@ -97,9 +119,7 @@ class Controller():
|
|||||||
self.plant.process()
|
self.plant.process()
|
||||||
theta_ist = self.plant.getTemperature()
|
theta_ist = self.plant.getTemperature()
|
||||||
|
|
||||||
heatrate_ist = 60/self.dt * (theta_ist - theta_last)
|
heatrate_ist = 60/self.dt * (theta_ist - self.theta_ist)
|
||||||
|
|
||||||
# print ("{}: Temp IST = {:0.2f} °C".format(timer_ist, temp_ist))
|
|
||||||
|
|
||||||
theta_err = theta_soll - theta_ist
|
theta_err = theta_soll - theta_ist
|
||||||
heatrate_err = heatrate_soll - heatrate_ist
|
heatrate_err = heatrate_soll - heatrate_ist
|
||||||
@@ -150,9 +170,6 @@ class Controller():
|
|||||||
power = max(self.params['P_min'], min(self.params['P_max'], self.params['P_max']*y))
|
power = max(self.params['P_min'], min(self.params['P_max'], self.params['P_max']*y))
|
||||||
self.plant.setPower(power)
|
self.plant.setPower(power)
|
||||||
|
|
||||||
self.time += self.dt
|
|
||||||
theta_last = theta_ist
|
|
||||||
|
|
||||||
self.theta_v = np.append(self.theta_v, theta_ist)
|
self.theta_v = np.append(self.theta_v, theta_ist)
|
||||||
self.heatrate_v = np.append(self.heatrate_v, heatrate_ist)
|
self.heatrate_v = np.append(self.heatrate_v, heatrate_ist)
|
||||||
self.time_v = np.append(self.time_v, self.time/60)
|
self.time_v = np.append(self.time_v, self.time/60)
|
||||||
@@ -160,12 +177,10 @@ class Controller():
|
|||||||
self.error_v = np.append(self.error_v, pid_err)
|
self.error_v = np.append(self.error_v, pid_err)
|
||||||
#self.error_v = np.append(self.error_v, self.stirrer.getRpm())
|
#self.error_v = np.append(self.error_v, self.stirrer.getRpm())
|
||||||
|
|
||||||
# print ("theta_err = {:0.2f} °C".format(theta_err))
|
|
||||||
# print ("Power = {:0.2f} W".format(power))
|
|
||||||
|
|
||||||
# -----------------------------------------
|
# -----------------------------------------
|
||||||
if ovenStateNext != self.ovenState:
|
if ovenStateNext != self.ovenState:
|
||||||
print("{} -> {}".format(self.ovenState, ovenStateNext))
|
self.log("{} -> {}".format(self.ovenState, ovenStateNext))
|
||||||
if ovenStateNext == ovenStates.HEAT:
|
if ovenStateNext == ovenStates.HEAT:
|
||||||
self.stirrer.setRpm(self.stirrRpmHeat)
|
self.stirrer.setRpm(self.stirrRpmHeat)
|
||||||
self.stirrer.setDutyCycle(1.0)
|
self.stirrer.setDutyCycle(1.0)
|
||||||
@@ -175,10 +190,23 @@ class Controller():
|
|||||||
self.stirrer.setDutyCycle(self.stirrDutyRast)
|
self.stirrer.setDutyCycle(self.stirrDutyRast)
|
||||||
|
|
||||||
if controllerStateNext != self.controllerState:
|
if controllerStateNext != self.controllerState:
|
||||||
print("{} -> {}".format(self.controllerState, controllerStateNext))
|
self.log("{} -> {}".format(self.controllerState, controllerStateNext))
|
||||||
|
|
||||||
self.ovenState = ovenStateNext
|
self.ovenState = ovenStateNext
|
||||||
self.controllerState = controllerStateNext
|
self.controllerState = controllerStateNext
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
|
time_stop = time.time()
|
||||||
|
time_to_sleep = self.dt / self.sim_warp_factor - (time_stop - time_start)
|
||||||
|
if time_to_sleep < 0:
|
||||||
|
self.log("Warning: dt is too small!")
|
||||||
|
time_to_sleep = 0
|
||||||
|
|
||||||
|
self.time += self.dt
|
||||||
|
self.theta_ist = theta_ist
|
||||||
|
self.heatrate_ist = heatrate_ist
|
||||||
|
|
||||||
|
self.report()
|
||||||
|
|
||||||
|
time.sleep(time_to_sleep)
|
||||||
|
|
||||||
self.stirrer.stop()
|
self.stirrer.stop()
|
||||||
|
|||||||
@@ -33,5 +33,8 @@ class Mass(APlant):
|
|||||||
def setPower(self, power_w):
|
def setPower(self, power_w):
|
||||||
self.P = power_w
|
self.P = power_w
|
||||||
|
|
||||||
|
def getPower(self):
|
||||||
|
return self.P
|
||||||
|
|
||||||
def getTemperature(self):
|
def getTemperature(self):
|
||||||
return self.theta + self.theta_amb
|
return self.theta + self.theta_amb
|
||||||
|
|||||||
@@ -19,23 +19,23 @@ class Stirrer(AStirrer):
|
|||||||
|
|
||||||
if self.cycleCounter <= (self.cycleTime * self.dutyCycle):
|
if self.cycleCounter <= (self.cycleTime * self.dutyCycle):
|
||||||
if not self.isOn:
|
if not self.isOn:
|
||||||
print ("Stirrer: On")
|
self.log ("Stirrer: On")
|
||||||
self.isOn = 1
|
self.isOn = 1
|
||||||
else:
|
else:
|
||||||
if self.isOn:
|
if self.isOn:
|
||||||
print ("Stirrer: Off")
|
self.log ("Stirrer: Off")
|
||||||
self.isOn = 0
|
self.isOn = 0
|
||||||
|
|
||||||
def setRpm(self, rpm):
|
def setRpm(self, rpm):
|
||||||
print ("Stirrer: Set RPM to {} rpm".format(rpm))
|
self.log ("Stirrer: Set RPM to {} rpm".format(rpm))
|
||||||
self.rpm = rpm
|
self.rpm = rpm
|
||||||
|
|
||||||
def setCycleTime(self, time):
|
def setCycleTime(self, time):
|
||||||
print ("Stirrer: Set cycle time to {} s".format(time))
|
self.log ("Stirrer: Set cycle time to {} s".format(time))
|
||||||
self.cycleTime = time
|
self.cycleTime = time
|
||||||
|
|
||||||
def setDutyCycle(self, dutyCycle):
|
def setDutyCycle(self, dutyCycle):
|
||||||
print ("Stirrer: Set duty cycle to {} %".format(100*dutyCycle))
|
self.log ("Stirrer: Set duty cycle to {} %".format(100*dutyCycle))
|
||||||
self.dutyCycle = dutyCycle
|
self.dutyCycle = dutyCycle
|
||||||
|
|
||||||
def getRpm(self):
|
def getRpm(self):
|
||||||
@@ -45,8 +45,8 @@ class Stirrer(AStirrer):
|
|||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.isMasterOn = 1
|
self.isMasterOn = 1
|
||||||
print("Stirrer: switched On")
|
self.log("Stirrer: switched On")
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.isMasterOn = 0
|
self.isMasterOn = 0
|
||||||
print("Stirrer: switched Off")
|
self.log("Stirrer: switched Off")
|
||||||
|
|||||||
Reference in New Issue
Block a user