improve HasRamp
Change-Id: I0ddabb8b2681712637a18c392da5424d30a05b4b
This commit is contained in:
parent
459a80b4d2
commit
75f156beef
@ -33,54 +33,64 @@ class HasRamp:
|
||||
# make sure it is a drivable
|
||||
status = Parameter()
|
||||
target = Parameter()
|
||||
ramp = Parameter('ramp ratge', FloatRange(0), default=0, readonly=False)
|
||||
ramp = Parameter('ramp rate', FloatRange(0, unit='$/min'), default=0, readonly=False)
|
||||
ramp_used = Parameter('False: infinite ramp', BoolType(), default=False, readonly=False)
|
||||
setpoint = Parameter('ramping setpoint', FloatRange())
|
||||
maxlag = Parameter('max lag between setpoint and value',
|
||||
FloatRange(0, unit='s'), default=60, readonly=False)
|
||||
setpoint = Parameter('ramping setpoint', FloatRange(unit='$'), readonly=False)
|
||||
maxdif = Parameter('''max. difference between setpoint and value
|
||||
|
||||
stop ramp then value lags behind setpoint by more than maxdif
|
||||
maxdif=0: use 'ramp' value (value lags 1 minute behind setpoint)
|
||||
''',
|
||||
FloatRange(0, unit='$'), default=0, readonly=False)
|
||||
rampinterval = Parameter('interval for changing the setpoint', FloatRange(0, unit='s'),
|
||||
default=1, readonly=False)
|
||||
workingramp = Parameter('effective ramp', FloatRange(unit='$/min'))
|
||||
|
||||
_ramp_status = None
|
||||
_last_time = None
|
||||
|
||||
def checkProperties(self):
|
||||
unit = self.parameters['value'].datatype.unit
|
||||
self.parameters['setpoint'].setProperty('unit', unit)
|
||||
self.writeDict['setpoint'] = self.parameters['setpoint'].default
|
||||
super().checkProperties()
|
||||
_buffer = 0
|
||||
|
||||
def doPoll(self):
|
||||
super().doPoll() # suppose that this is reading value and status
|
||||
self.ramp_step(self.target)
|
||||
|
||||
def write_setpoint(self, value):
|
||||
# written only once at startup
|
||||
self._last_time = time.time()
|
||||
self.setpoint = self.read_value()
|
||||
|
||||
def ramp_step(self, target):
|
||||
now = time.time()
|
||||
setpoint = self.setpoint
|
||||
if self._ramp_status is not None:
|
||||
if setpoint == target:
|
||||
self._ramp_status = None # at target
|
||||
self.workingramp = 0
|
||||
else:
|
||||
sign = copysign(1, target - setpoint)
|
||||
delay = now - self._last_time
|
||||
prev_t, prev_v = self._last_point
|
||||
if self.value == prev_v:
|
||||
return # no reads happened
|
||||
delay = (now - prev_t) / 60.0 # minutes !
|
||||
slope = (self.value - prev_v) / max(1e-5, delay)
|
||||
dif = (setpoint - self.value) * sign
|
||||
ramp_sec = self.ramp / 60.0
|
||||
if dif < self.maxlag * ramp_sec:
|
||||
setpoint += delay * sign * ramp_sec
|
||||
maxdif = self.maxdif or self.ramp
|
||||
if dif < maxdif:
|
||||
# reduce ramp when slope is bigger than ramp
|
||||
ramp = max(2 * self.ramp - sign * slope, 0) + self._buffer
|
||||
if ramp > self.ramp:
|
||||
self._buffer = min(ramp - self.ramp, self.ramp)
|
||||
ramp = self.ramp
|
||||
else:
|
||||
self._buffer = 0
|
||||
setpoint += sign * delay * ramp
|
||||
if sign * (setpoint - target) >= 0:
|
||||
self.setpoint = target
|
||||
self.write_setpoint(setpoint)
|
||||
self.workingramp = 0
|
||||
self._ramp_status = None # at target
|
||||
else:
|
||||
self.setpoint = setpoint
|
||||
if ramp != self.workingramp:
|
||||
self.workingramp = sign * ramp
|
||||
self.write_setpoint(setpoint)
|
||||
self._ramp_status = 'ramping'
|
||||
super().write_target(self.setpoint)
|
||||
else:
|
||||
self._ramp_status = 'holding'
|
||||
self._last_time = now
|
||||
self._last_point = now, self.value
|
||||
self.read_status()
|
||||
|
||||
def read_status(self):
|
||||
@ -106,22 +116,24 @@ class HasRamp:
|
||||
if self._ramp_status:
|
||||
self.write_target(self.target)
|
||||
|
||||
def write_setpoint(self, setpoint):
|
||||
super().write_target(setpoint)
|
||||
return setpoint
|
||||
|
||||
def read_target(self):
|
||||
if not self._ramp_status:
|
||||
return super().read_target()
|
||||
return self.target
|
||||
|
||||
def write_target(self, target):
|
||||
if not self.ramp_used:
|
||||
self._ramp_status = None
|
||||
self.setpoint = target
|
||||
super().write_target(target)
|
||||
if self.ramp_used:
|
||||
if self.parameters['setpoint'].readerror:
|
||||
self.write_setpoint(self.read_value())
|
||||
self._ramp_status = 'changed target'
|
||||
self._last_time = time.time()
|
||||
self.setFastPoll(True, self.rampinterval)
|
||||
self.ramp_step(target)
|
||||
return target
|
||||
self._ramp_status = 'changed target'
|
||||
v = self.read_value()
|
||||
maxdif = self.maxlag * self.ramp / 60
|
||||
# setpoint must not differ too much from value
|
||||
self.setpoint = clamp(v - maxdif, self.setpoint, v + maxdif)
|
||||
self.setFastPoll(True, self.rampinterval)
|
||||
self.ramp_step(target)
|
||||
self._ramp_status = None
|
||||
self.write_setpoint(target)
|
||||
return target
|
||||
|
@ -22,13 +22,16 @@
|
||||
|
||||
"""modules to access parameters"""
|
||||
|
||||
from frappy.core import Drivable, IDLE, Attached, StringType, Property, Proxy
|
||||
from frappy.mixins import HasRamp
|
||||
from frappy.core import Drivable, IDLE, Attached, StringType, Property, \
|
||||
Parameter, FloatRange
|
||||
from frappy.errors import ConfigError
|
||||
from frappy_psi.convergence import HasConvergence
|
||||
from frappy_psi.mixins import HasRamp
|
||||
|
||||
|
||||
class Driv(Drivable):
|
||||
value = Parameter(datatype=FloatRange(unit='$'))
|
||||
target = Parameter(datatype=FloatRange(unit='$'))
|
||||
read = Attached(description='<module>.<parameter> for read')
|
||||
write = Attached(description='<module>.<parameter> for read')
|
||||
unit = Property('main unit', StringType())
|
||||
@ -40,8 +43,7 @@ class Driv(Drivable):
|
||||
super().setProperty(key, value)
|
||||
|
||||
def checkProperties(self):
|
||||
self.parameters['value'].setProperty('unit', self.unit)
|
||||
self.parameters['target'].setProperty('unit', self.unit)
|
||||
self.applyMainUnit(self.unit)
|
||||
if self.read == self.name or self.write == self.name:
|
||||
raise ConfigError('illegal recursive read/write module')
|
||||
super().checkProperties()
|
||||
|
Loading…
x
Reference in New Issue
Block a user