fixes on picontrol and tdkpower

Change-Id: Ia891e7df23d8408b857dac795ed0ad9973ccf993
This commit is contained in:
zolliker 2025-04-08 17:15:17 +02:00
parent 09dce1aabd
commit fcf867675e
3 changed files with 33 additions and 66 deletions

View File

@ -6,7 +6,7 @@ Node('fi.psi.ch',
Mod('htr_io',
'frappy_psi.tdkpower.IO',
'powersupply communicator',
uri='serial:///dev/ttyUSB0',
uri='serial:///dev/ttyUSB0?baudrate=9600',
)
Mod('htr',
@ -16,7 +16,7 @@ Mod('htr',
)
Mod('out',
'frappy_psi.bkpower.Output',
'frappy_psi.tdkpower.Output',
'heater output',
io='htr_io',
maxvolt=8,
@ -54,7 +54,7 @@ Mod('T',
'frappy_psi.furnace.PI',
'controlled Temperature',
input='T_htr',
output='out',
output='htr',
relais='relais',
p=2,
i=0.01,

View File

@ -60,7 +60,7 @@ example cfg:
import time
import math
from frappy.core import Readable, Writable, Parameter, Attached, IDLE
from frappy.core import Readable, Writable, Parameter, Attached, IDLE, Property
from frappy.lib import clamp
from frappy.datatypes import LimitsType, EnumType, BoolType, FloatRange
from frappy.mixins import HasOutputModule
@ -71,8 +71,9 @@ class PImixin(HasOutputModule, Writable):
p = Parameter('proportional term', FloatRange(0), readonly=False)
i = Parameter('integral term', FloatRange(0), readonly=False)
# output_module is inherited
output_range = Parameter('min output',
LimitsType(FloatRange()), default=(0, 0), readonly=False)
output_range = Property('legacy output range', LimitsType(FloatRange()), default=(0,0))
output_min = Parameter('min output', FloatRange(), default=0, readonly=False)
output_max = Parameter('max output', FloatRange(), default=0, readonly=False)
output_func = Parameter('output function',
EnumType(lin=0, square=1), readonly=False, default=0)
value = Parameter(unit='K')
@ -80,6 +81,11 @@ class PImixin(HasOutputModule, Writable):
_lasttime = 0
_clamp_limits = None
def initModule(self):
super().initModule()
if self.output_range != (0, 0): # legacy !
self.output_min, self.output_max = self.output_range
def doPoll(self):
super().doPoll()
if self._clamp_limits is None:
@ -93,8 +99,8 @@ class PImixin(HasOutputModule, Writable):
self._clamp_limits = lambda v, o=out: clamp(v, 0, o.read_limit())
else:
self._clamp_limits = lambda v: v
if self.output_range == (0.0, 0.0):
self.output_range = (0, self._clamp_limits(float('inf')))
if self.output_min == 0 and self.output_max == 0:
self.output_max = self._clamp_limits(float('inf'))
if not self.control_active:
return
self.status = IDLE, 'controlling'
@ -114,7 +120,7 @@ class PImixin(HasOutputModule, Writable):
if self.output_func == 'square':
output = output ** 2
output = self._clamp_limits(output)
out.update_target(self.name, clamp(output, *self.output_range))
out.update_target(self.name, clamp(output, self.output_min, self.output_max))
def write_control_active(self, value):
if not value:
@ -125,61 +131,6 @@ class PImixin(HasOutputModule, Writable):
self.activate_control()
# quick fix by Marek:
class PIobsolete(Writable):
"""temporary, but working version from Marek"""
input = Attached(Readable, 'the input module')
output = Attached(Writable, 'the output module')
output_max = Parameter('max output value', FloatRange(0), readonly=False)
p = Parameter('proportional term', FloatRange(0), readonly=False)
i = Parameter('integral term', FloatRange(0), readonly=False)
control_active = Parameter('control flag', BoolType(), readonly=False, default=False)
value = Parameter(unit='K')
tlim = Parameter('max Temperature', FloatRange(0), readonly=False)
_lastdiff = None
_lasttime = 0
_lastvalue = 0
def doPoll(self):
super().doPoll()
if not self.control_active:
return
self.value = self.input.value
self.status = IDLE, 'controlling'
now = time.time()
deltat = min(10.0, now-self._lasttime)
self._lasttime = now
if self.value != self._lastvalue:
diff = self.target - self.value # calculate the difference to target
self._lastvalue = self.value
# else ? (diff is undefined!)
if self.value > self.tlim:
self.write_control_active(False)
return
if self._lastdiff is None:
self._lastdiff = diff
deltadiff = diff - self._lastdiff # calculate the change in deltaT
self._lastdiff = diff
output = self.output.target
output += self.p * deltadiff + self.i * deltat * diff
if output > self.output_max:
output = self.output_max
elif output < 0:
output = 0
self.output.write_target(output)
def write_control_active(self, value):
if not value:
self.output.write_target(0)
def write_target(self, value):
self.control_active = True
# proposal for replacing above PI class, inheriting from PImixin
# additional features:
# - is a Drivable, using the convergence criteria from HasConvergence
# - tries to determine the output limits automatically
# unchecked!
class PI(HasConvergence, PImixin):
@ -190,3 +141,18 @@ class PI(HasConvergence, PImixin):
def read_status(self):
return self.input_module.status
class PI2(PI):
maxovershoot = Parameter('max. overshoot', FloatRange(0, 100, unit='%'), readonly=False, default=20)
def doPoll(self):
self.output_max = self.target * (1 + 0.01 * self.maxovershoot)
self.output_min = self.target * (1 - 0.01 * self.maxovershoot)
super().doPoll()
def write_target(self, target):
if not self.control_active:
self.output.write_target(target)
super().write_target(target)

View File

@ -24,10 +24,11 @@ from frappy.datatypes import BoolType, EnumType, FloatRange
class IO(StringIO):
end_of_line = ('OK\r', '\r')
end_of_line = '\r'
default_settings = {'baudrate': 9600}
identification = [('ADR 0', 'OK'), ('IDN?', r'LAMBDA,GEN8-400')]
class Power(HasIO, Readable):
value = Parameter(datatype=FloatRange(0,3300,unit='W'))