frappy_psi.picontrol: software control loop

example usage: use a temperature controller without changing
the calibration setting:
reading the raw sensor, calibrate by software and use 'manual'
heater output

Change-Id: I3dbcf37e7726b48a0516d7aa30758be52b80fe58
Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/33910
Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
zolliker 2024-06-11 17:48:46 +02:00
parent 8b27e4012c
commit f5667a9267

View File

@ -16,12 +16,14 @@
# Module authors:
# Markus Zolliker <markus.zolliker@psi.ch>
# Jael Celia Lorenzana <jael-celia.lorenzana@psi.ch>
#
# *****************************************************************************
"""soft PI control"""
import time
from frappy.core import Writable, Attached, Parameter, FloatRange, Readable, BoolType, ERROR, IDLE
import math
from frappy.core import Writable, Parameter, FloatRange, IDLE
from frappy.lib import clamp
from frappy.datatypes import LimitsType, EnumType
from frappy.mixins import HasOutputModule
@ -30,8 +32,10 @@ from frappy.mixins import HasOutputModule
class PImixin(HasOutputModule, Writable):
p = Parameter('proportional term', FloatRange(0), readonly=False)
i = Parameter('integral term', FloatRange(0), readonly=False)
output_range = Parameter('min output', LimitsType(FloatRange()), default=(0, 0), readonly=False)
output_func = Parameter('output function', EnumType(lin=0, square=1), readonly=False, default=0)
output_range = Parameter('min output',
LimitsType(FloatRange()), default=(0, 0), readonly=False)
output_func = Parameter('output function',
EnumType(lin=0, square=1), readonly=False, default=0)
value = Parameter(unit='K')
_lastdiff = None
_lasttime = 0
@ -50,10 +54,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
self.log.info('OR %r', self.output_range)
if self.output_range == (0.0, 0.0):
self.output_range = (0, self._clamp_limits(float('inf')))
self.log.info('OR %r', self.output_range)
if not self.control_active:
return
self.status = IDLE, 'controlling'
@ -68,7 +70,7 @@ class PImixin(HasOutputModule, Writable):
out = self.output_module
output = out.target
if self.output_func == 'square':
output = match.sqrt(max(0, output))
output = math.sqrt(max(0, output))
output += self.p * deltadiff + self.i * deltat * diff
if self.output_func == 'square':
output = output ** 2
@ -79,21 +81,6 @@ class PImixin(HasOutputModule, Writable):
if not value:
self.output_module.write_target(0)
def write_target(self, target):
def write_target(self, _):
if not self.control_active:
self.activate_control()
class PI(PImixin, Writable):
input = Attached(Readable, 'the input module')
relais = Attached(Writable, 'the interlock relais', mandatory=False)
def read_value(self):
return self.input.value
def write_target(self, value):
super().write_target(value)
if self.relais:
self.relais.write_target(1)