[WIP] fi furnace improvements

- still under development

Change-Id: I5fc22f041fb136b549016f510f06ea703122bee5
This commit is contained in:
2025-05-08 08:29:45 +02:00
parent e46291eef6
commit 3bae6f8d7f
4 changed files with 134 additions and 70 deletions

View File

@ -63,7 +63,7 @@ import math
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
from frappy.newmixins import HasOutputModule
from frappy_psi.convergence import HasConvergence
@ -79,7 +79,8 @@ class PImixin(HasOutputModule, Writable):
value = Parameter(unit='K')
_lastdiff = None
_lasttime = 0
_clamp_limits = None
_get_range = None # a function get output range from output_module
_overflow = 0
def initModule(self):
super().initModule()
@ -88,21 +89,9 @@ class PImixin(HasOutputModule, Writable):
def doPoll(self):
super().doPoll()
if self._clamp_limits is None:
out = self.output_module
if hasattr(out, 'max_target'):
if hasattr(self, 'min_target'):
self._clamp_limits = lambda v, o=out: clamp(v, o.read_min_target(), o.read_max_target())
else:
self._clamp_limits = lambda v, o=out: clamp(v, 0, o.read_max_target())
elif hasattr(out, 'limit'): # mercury.HeaterOutput
self._clamp_limits = lambda v, o=out: clamp(v, 0, o.read_limit())
else:
self._clamp_limits = lambda v: v
if self.output_min == 0 and self.output_max == 0:
self.output_max = self._clamp_limits(float('inf'))
if not self.control_active:
return
out = self.output_module
self.status = IDLE, 'controlling'
now = time.time()
deltat = clamp(0, now-self._lasttime, 10)
@ -112,17 +101,51 @@ class PImixin(HasOutputModule, Writable):
self._lastdiff = diff
deltadiff = diff - self._lastdiff
self._lastdiff = diff
output, omin, omax = self._cvt2int(out.target)
output += self._overflow + self.p * deltadiff + self.i * deltat * diff
if output < omin:
self._overflow = max(omin - omax, output - omin)
output = omin
elif output > omax:
self._overflow = min(omax - omin, output - omax)
output = omax
else:
self._overflow = 0
out.update_target(self.name, self._cvt2ext(output))
def cvt2int_square(self, output):
return (math.sqrt(max(0, clamp(x, *self._get_range()))) for x in (output, self.output_min, self.output_max))
def cvt2ext_square(self, output):
return output ** 2
def cvt2int_lin(self, output):
return (clamp(x, *self._get_range()) for x in (output, self.output_min, self.output_max))
def cvt2ext_lin(self, output):
return output
def write_output_func(self, value):
out = self.output_module
output = out.target
if self.output_func == 'square':
output = math.sqrt(max(0, output))
output += self.p * deltadiff + self.i * deltat * diff
if self.output_func == 'square':
output = output ** 2
output = self._clamp_limits(output)
out.update_target(self.name, clamp(output, self.output_min, self.output_max))
if hasattr(out, 'max_target'):
if hasattr(self, 'min_target'):
self._get_range = lambda o=out: (o.read_min_target(), o.read_max_target())
else:
self._get_range = lambda o=out: (0, o.read_max_target())
elif hasattr(out, 'limit'): # mercury.HeaterOutput
self._get_range = lambda o=out: (0, o.read_limit())
else:
if self.output_min == self.output_max == 0:
self.output_max = 1
self._get_range = lambda o=self: (o.output_min, o.output_max)
if self.output_min == self.output_max == 0:
self.output_min, self.output_max = self._get_range()
self.output_func = value
self._cvt2int = getattr(self, f'cvt2int_{self.output_func.name}')
self._cvt2ext = getattr(self, f'cvt2ext_{self.output_func.name}')
def write_control_active(self, value):
super().write_control_active(value)
if not value:
self.output_module.write_target(0)