diff --git a/siriuspy/siriuspy/VERSION b/siriuspy/siriuspy/VERSION index 5245cdbd1..05c57ca73 100644 --- a/siriuspy/siriuspy/VERSION +++ b/siriuspy/siriuspy/VERSION @@ -1 +1 @@ -2.104.0 +2.104.1 diff --git a/siriuspy/siriuspy/devices/tune.py b/siriuspy/siriuspy/devices/tune.py index 46829b2dd..225943ea9 100644 --- a/siriuspy/siriuspy/devices/tune.py +++ b/siriuspy/siriuspy/devices/tune.py @@ -89,8 +89,8 @@ def center_frequency(self, value): self['FreqOff-SP'] = value @property - def aquisition_enabled(self): - """Aquisition enabled state.""" + def acquisition_enabled(self): + """Acquisition enabled state.""" return self['SpecAnaGetSpec-Sts'] @property @@ -410,12 +410,12 @@ def tuney_wfm(self): return self.dev_tune_proc_v.tune_wfm @property - def aquisition_enabledx(self): + def acquisition_enabledx(self): """Tune X acquisition enabled status.""" return self.dev_tune_frac_h.acquisition_enabled @property - def aquisition_enabledy(self): + def acquisition_enabledy(self): """Tune Y acquisition enabled status.""" return self.dev_tune_frac_v.acquisition_enabled diff --git a/siriuspy/siriuspy/opticscorr/csdev.py b/siriuspy/siriuspy/opticscorr/csdev.py index e41683189..dea6dc7bc 100644 --- a/siriuspy/siriuspy/opticscorr/csdev.py +++ b/siriuspy/siriuspy/opticscorr/csdev.py @@ -402,24 +402,88 @@ def get_tune_database(acc): 'lolim': 0.0001, 'hilim': 0.4999, } - pvs_database['MaxTuneErr-SP'] = { + pvs_database['MaxTuneXErr-SP'] = { 'type': 'float', 'value': _ct.DEF_MAX_TUNE_ERR, 'unit': 'Tune', 'prec': 6, - 'lolim': 0.001, - 'hilim': 0.4999, + 'lolim': 0.000001, + 'hilim': 0.499999, } - pvs_database['MaxTuneErr-RB'] = { + pvs_database['MaxTuneXErr-RB'] = { 'type': 'float', 'value': _ct.DEF_MAX_TUNE_ERR, 'unit': 'Tune', 'prec': 6, - 'lolim': 0.001, - 'hilim': 0.4999, + 'lolim': 0.000001, + 'hilim': 0.499999, + } + pvs_database['MaxTuneYErr-SP'] = { + 'type': 'float', + 'value': _ct.DEF_MAX_TUNE_ERR, + 'unit': 'Tune', + 'prec': 6, + 'lolim': 0.000001, + 'hilim': 0.499999, + } + pvs_database['MaxTuneYErr-RB'] = { + 'type': 'float', + 'value': _ct.DEF_MAX_TUNE_ERR, + 'unit': 'Tune', + 'prec': 6, + 'lolim': 0.000001, + 'hilim': 0.499999, } # SI Tune FeedBack: PID PVs - pvs_database['LoopPIDKp-SP'] = { + pvs_database['LoopPIDKpX-SP'] = { + 'type': 'float', + 'value': _ct.DEF_PID_KP, + 'unit': 'frac', + 'prec': 4, + 'lolim': -100, + 'hilim': 100, + } + pvs_database['LoopPIDKpX-RB'] = { + 'type': 'float', + 'value': _ct.DEF_PID_KP, + 'unit': 'frac', + 'prec': 4, + 'lolim': -100, + 'hilim': 100, + } + pvs_database['LoopPIDKiX-SP'] = { + 'type': 'float', + 'value': _ct.DEF_PID_KI, + 'unit': 'frac.Hz', + 'prec': 4, + 'lolim': -100, + 'hilim': 100, + } + pvs_database['LoopPIDKiX-RB'] = { + 'type': 'float', + 'value': _ct.DEF_PID_KI, + 'unit': 'frac.Hz', + 'prec': 4, + 'lolim': -100, + 'hilim': 100, + } + pvs_database['LoopPIDKdX-SP'] = { + 'type': 'float', + 'value': _ct.DEF_PID_KD, + 'unit': 'frac.s', + 'prec': 4, + 'lolim': -100, + 'hilim': 100, + } + pvs_database['LoopPIDKdX-RB'] = { + 'type': 'float', + 'value': _ct.DEF_PID_KD, + 'unit': 'frac.s', + 'prec': 4, + 'lolim': -100, + 'hilim': 100, + } + pvs_database['LoopPIDKpY-SP'] = { 'type': 'float', 'value': _ct.DEF_PID_KP, 'unit': 'frac', @@ -427,7 +491,7 @@ def get_tune_database(acc): 'lolim': -100, 'hilim': 100, } - pvs_database['LoopPIDKp-RB'] = { + pvs_database['LoopPIDKpY-RB'] = { 'type': 'float', 'value': _ct.DEF_PID_KP, 'unit': 'frac', @@ -435,7 +499,7 @@ def get_tune_database(acc): 'lolim': -100, 'hilim': 100, } - pvs_database['LoopPIDKi-SP'] = { + pvs_database['LoopPIDKiY-SP'] = { 'type': 'float', 'value': _ct.DEF_PID_KI, 'unit': 'frac.Hz', @@ -443,7 +507,7 @@ def get_tune_database(acc): 'lolim': -100, 'hilim': 100, } - pvs_database['LoopPIDKi-RB'] = { + pvs_database['LoopPIDKiY-RB'] = { 'type': 'float', 'value': _ct.DEF_PID_KI, 'unit': 'frac.Hz', @@ -451,7 +515,7 @@ def get_tune_database(acc): 'lolim': -100, 'hilim': 100, } - pvs_database['LoopPIDKd-SP'] = { + pvs_database['LoopPIDKdY-SP'] = { 'type': 'float', 'value': _ct.DEF_PID_KD, 'unit': 'frac.s', @@ -459,7 +523,7 @@ def get_tune_database(acc): 'lolim': -100, 'hilim': 100, } - pvs_database['LoopPIDKd-RB'] = { + pvs_database['LoopPIDKdY-RB'] = { 'type': 'float', 'value': _ct.DEF_PID_KD, 'unit': 'frac.s', @@ -469,12 +533,22 @@ def get_tune_database(acc): } # SI Tune FeedBack: Tune measurement PV selection - pvs_database['TuneSrc-Sel'] = { + pvs_database['TuneXSrc-Sel'] = { + 'type': 'enum', + 'enums': _ct.TuneSrc._fields, + 'value': _ct.DEF_TUNESRC, + } + pvs_database['TuneXSrc-Sts'] = { + 'type': 'enum', + 'enums': _ct.TuneSrc._fields, + 'value': _ct.DEF_TUNESRC, + } + pvs_database['TuneYSrc-Sel'] = { 'type': 'enum', 'enums': _ct.TuneSrc._fields, 'value': _ct.DEF_TUNESRC, } - pvs_database['TuneSrc-Sts'] = { + pvs_database['TuneYSrc-Sts'] = { 'type': 'enum', 'enums': _ct.TuneSrc._fields, 'value': _ct.DEF_TUNESRC, diff --git a/siriuspy/siriuspy/opticscorr/tune.py b/siriuspy/siriuspy/opticscorr/tune.py index 779db7ab5..3234a70af 100644 --- a/siriuspy/siriuspy/opticscorr/tune.py +++ b/siriuspy/siriuspy/opticscorr/tune.py @@ -258,30 +258,46 @@ def __init__(self): self._loop_state = _Const.DEF_LOOPSTATE self._loop_freq = _Const.DEF_LOOPFREQ - self._tune_source = _Const.DEF_TUNESRC - self._max_tune_err = _Const.DEF_MAX_TUNE_ERR + self._tunex_source = _Const.DEF_TUNESRC + self._tuney_source = _Const.DEF_TUNESRC + + self._max_tunex_err = _Const.DEF_MAX_TUNE_ERR + self._max_tuney_err = _Const.DEF_MAX_TUNE_ERR + self._ref_tunex = _Const.DEF_REF_TUNEX self._ref_tuney = _Const.DEF_REF_TUNEY self._pid_errs = None # created when feedback thread starts self._pid_gains = dict( - kp=_Const.DEF_PID_KP, - ki=_Const.DEF_PID_KI, - kd=_Const.DEF_PID_KD, + x=dict( + kp=_Const.DEF_PID_KP, + ki=_Const.DEF_PID_KI, + kd=_Const.DEF_PID_KD, + ), + y=dict( + kp=_Const.DEF_PID_KP, + ki=_Const.DEF_PID_KI, + kd=_Const.DEF_PID_KD, + ), ) self._thread_fb = None self.map_pv2write.update({ 'LoopState-Sel': self.set_loop_state, 'LoopFreq-SP': self.set_loop_freq, - 'TuneSrc-Sel': self.set_tune_source, + 'TuneXSrc-Sel': _part(self.set_tune_source, "x"), + 'TuneYSrc-Sel': _part(self.set_tune_source, "y"), 'RefTuneX-SP': _part(self.set_ref_tune, "x"), 'RefTuneY-SP': _part(self.set_ref_tune, "y"), - 'MaxTuneErr-SP': self.set_max_tune_err, - 'LoopPIDKp-SP': _part(self.set_pid_gain, "kp"), - 'LoopPIDKi-SP': _part(self.set_pid_gain, "ki"), - 'LoopPIDKd-SP': _part(self.set_pid_gain, "kd"), + 'MaxTuneXErr-SP': _part(self.set_max_tune_err, "x"), + 'MaxTuneYErr-SP': _part(self.set_max_tune_err, "y"), + 'LoopPIDKpX-SP': _part(self.set_pid_gain, "x", "kp"), + 'LoopPIDKiX-SP': _part(self.set_pid_gain, "x", "ki"), + 'LoopPIDKdX-SP': _part(self.set_pid_gain, "x", "kd"), + 'LoopPIDKpY-SP': _part(self.set_pid_gain, "y", "kp"), + 'LoopPIDKiY-SP': _part(self.set_pid_gain, "y", "ki"), + 'LoopPIDKdY-SP': _part(self.set_pid_gain, "y", "kd"), }) self._tune_x_pv.add_callback(_part(self._callback_update_tunes, 'x')) @@ -324,7 +340,7 @@ def set_loop_freq(self, value): self.run_callbacks('LoopFreq-RB', float(value)) return True - def set_tune_source(self, value): + def set_tune_source(self, plane, value): """Set tune source.""" if self._loop_state == _Const.LoopState.Closed: msg = "ERR: Can\'t change tune source while the feedback is on." @@ -334,25 +350,39 @@ def set_tune_source(self, value): msg = "ERR: Invalid tune source." self._update_log(msg) return False - self._tune_source = value - pvnames = _ETypes.TUNE_SRC_PVS[self._tune_source] - pvx, pvy = _SiriusPVName(pvnames[0]), _SiriusPVName(pvnames[1]) - self._tune_x_pv.clear_callbacks() - self._tune_y_pv.clear_callbacks() - self._tune_x_pv = _PV( - pvx.substitute(prefix=_vaca_prefix), - connection_timeout=SITuneCorrApp._DEF_CONN_TIMEOUT_TUNE, - auto_monitor=True, - callback=_part(self._callback_update_tunes, 'x') - ) - self._tune_y_pv = _PV( - pvy.substitute(prefix=_vaca_prefix), - connection_timeout=SITuneCorrApp._DEF_CONN_TIMEOUT_TUNE, - auto_monitor=True, - callback=_part(self._callback_update_tunes, 'y') - ) - self.run_callbacks('TuneSrcPVList-Mon', (pvx, pvy)) - self.run_callbacks('TuneSrc-Sts', value) + plane = plane.upper() + pln_idx = None + if plane == 'X': + self._tunex_source = value + pln_idx = 0 + elif plane == 'Y': + self._tuney_source = value + pln_idx = 1 + else: + self._update_log("ERR: Invalid plane.") + return False + pv = _SiriusPVName(_ETypes.TUNE_SRC_PVS[value][pln_idx]) + if plane == 'X': + self._tune_x_pv.clear_callbacks() + self._tune_x_pv = _PV( + pv.substitute(prefix=_vaca_prefix), + connection_timeout=SITuneCorrApp._DEF_CONN_TIMEOUT_TUNE, + auto_monitor=True, + callback=_part(self._callback_update_tunes, 'x') + ) + elif plane == 'Y': + self._tune_y_pv.clear_callbacks() + self._tune_y_pv = _PV( + pv.substitute(prefix=_vaca_prefix), + connection_timeout=SITuneCorrApp._DEF_CONN_TIMEOUT_TUNE, + auto_monitor=True, + callback=_part(self._callback_update_tunes, 'y') + ) + self.run_callbacks('TuneSrcPVList-Mon', ( + self._tune_x_pv.pvname.substitute(prefix=''), + self._tune_y_pv.pvname.substitute(prefix='') + )) + self.run_callbacks('Tune' + plane + 'Src-Sts', value) return True def set_ref_tune(self, plane, value): @@ -367,17 +397,25 @@ def set_ref_tune(self, plane, value): self.run_callbacks('RefTune'+plane+'-RB', float(value)) return True - def set_max_tune_err(self, value): + def set_max_tune_err(self, plane, value): """Set max tune error.""" - self._max_tune_err = float(value) - self.run_callbacks('MaxTuneErr-RB', float(value)) + plane = plane.upper() + if plane == 'X': + self._max_tunex_err = float(value) + self.run_callbacks('MaxTuneXErr-RB', float(value)) + elif plane == 'Y': + self._max_tuney_err = float(value) + self.run_callbacks('MaxTuneYErr-RB', float(value)) return True - def set_pid_gain(self, kparam, value): + def set_pid_gain(self, plane, kparam, value): """.""" + plane = plane.lower() kparam = kparam.lower() - self._pid_gains[kparam] = float(value) - self.run_callbacks("LoopPID" + kparam.title() + "-RB", float(value)) + self._pid_gains[plane][kparam] = float(value) + self.run_callbacks( + "LoopPID" + kparam.title() + plane.upper() + "-RB", float(value) + ) return True # --- pv initialization --- @@ -391,12 +429,19 @@ def update_corrparams_pvs(self): self.run_callbacks('LoopFreq-SP', self._loop_freq) self.run_callbacks('LoopFreq-RB', self._loop_freq) - self.run_callbacks('LoopPIDKp-SP', self._pid_gains['kp']) - self.run_callbacks('LoopPIDKp-RB', self._pid_gains['kp']) - self.run_callbacks('LoopPIDKi-SP', self._pid_gains['ki']) - self.run_callbacks('LoopPIDKi-RB', self._pid_gains['ki']) - self.run_callbacks('LoopPIDKd-SP', self._pid_gains['kd']) - self.run_callbacks('LoopPIDKd-RB', self._pid_gains['kd']) + self.run_callbacks('LoopPIDKpX-SP', self._pid_gains['x']['kp']) + self.run_callbacks('LoopPIDKpX-RB', self._pid_gains['x']['kp']) + self.run_callbacks('LoopPIDKiX-SP', self._pid_gains['x']['ki']) + self.run_callbacks('LoopPIDKiX-RB', self._pid_gains['x']['ki']) + self.run_callbacks('LoopPIDKdX-SP', self._pid_gains['x']['kd']) + self.run_callbacks('LoopPIDKdX-RB', self._pid_gains['x']['kd']) + + self.run_callbacks('LoopPIDKpY-SP', self._pid_gains['y']['kp']) + self.run_callbacks('LoopPIDKpY-RB', self._pid_gains['y']['kp']) + self.run_callbacks('LoopPIDKiY-SP', self._pid_gains['y']['ki']) + self.run_callbacks('LoopPIDKiY-RB', self._pid_gains['y']['ki']) + self.run_callbacks('LoopPIDKdY-SP', self._pid_gains['y']['kd']) + self.run_callbacks('LoopPIDKdY-RB', self._pid_gains['y']['kd']) self.run_callbacks('RefTuneX-SP', self._ref_tunex) self.run_callbacks('RefTuneX-RB', self._ref_tunex) @@ -404,14 +449,19 @@ def update_corrparams_pvs(self): self.run_callbacks('RefTuneY-SP', self._ref_tuney) self.run_callbacks('RefTuneY-RB', self._ref_tuney) - self.run_callbacks('MaxTuneErr-SP', self._max_tune_err) - self.run_callbacks('MaxTuneErr-RB', self._max_tune_err) + self.run_callbacks('MaxTuneXErr-SP', self._max_tunex_err) + self.run_callbacks('MaxTuneXErr-RB', self._max_tunex_err) + self.run_callbacks('MaxTuneYErr-SP', self._max_tuney_err) + self.run_callbacks('MaxTuneYErr-RB', self._max_tuney_err) - self.run_callbacks('TuneSrc-Sel', self._tune_source) - self.run_callbacks('TuneSrc-Sts', self._tune_source) + self.run_callbacks('TuneXSrc-Sel', self._tunex_source) + self.run_callbacks('TuneXSrc-Sts', self._tunex_source) + self.run_callbacks('TuneYSrc-Sel', self._tuney_source) + self.run_callbacks('TuneYSrc-Sts', self._tuney_source) self.run_callbacks( 'TuneSrcPVList-Mon', - _ETypes.TUNE_SRC_PVS[self._tune_source] + (_ETypes.TUNE_SRC_PVS[self._tunex_source][0], + _ETypes.TUNE_SRC_PVS[self._tuney_source][1]) ) self.run_callbacks('CorrGroup-Sts', self._corr_group) # ? needed? @@ -422,11 +472,11 @@ def update_corrparams_pvs(self): # --- feedback methods --- def _do_auto_corr(self): """.""" + self._update_ref() self.run_callbacks("LoopState-Sts", _Const.LoopState.Closed) msg = "Loop closed!" self._update_log(msg) - self._update_ref() - zer = _np.zeros(len(self._psfams), dtype=float) + zer = _np.zeros(2, dtype=float) self._pid_errs = [zer, zer.copy(), zer.copy()] while self._loop_state == _Const.LoopState.Closed: @@ -462,32 +512,32 @@ def _do_auto_corr(self): self.run_callbacks("LoopState-Sts", _Const.LoopState.Open) def _process_pid(self, tunex, tuney): - self._delta_tunex = self._ref_tunex - tunex - self._delta_tuney = self._ref_tuney - tuney - - delta_kl_prev = _np.array([ - self._lastcalc_deltakl[fam] for fam in self._psfams - ]) - - self._calc_intstrength() - - e0 = _np.array([self._lastcalc_deltakl[fam] for fam in self._psfams]) + e0 = _np.array([self._ref_tunex - tunex, self._ref_tuney - tuney]) e1 = self._pid_errs[-1] e2 = self._pid_errs[-2] interval = 1.0 / self._loop_freq - kp = self._pid_gains['kp'] - ki = self._pid_gains['ki'] * interval - kd = self._pid_gains['kd'] / interval + kpx = self._pid_gains['x']['kp'] + kix = self._pid_gains['x']['ki'] * interval + kdx = self._pid_gains['x']['kd'] / interval + + kpy = self._pid_gains['y']['kp'] + kiy = self._pid_gains['y']['ki'] * interval + kdy = self._pid_gains['y']['kd'] / interval - a0 = kp + ki + kd - a1 = -kp - 2*kd - a2 = kd + a0x = kpx + kix + kdx + a1x = -kpx - 2*kdx + a2x = kdx - delta_kl = delta_kl_prev + a0*e0 + a1*e1 + a2*e2 - for i, fam in enumerate(self._psfams): - self._lastcalc_deltakl[fam] = delta_kl[i] + a0y = kpy + kiy + kdy + a1y = -kpy - 2*kdy + a2y = kdy + + self._delta_tunex += a0x*e0[0] + a1x*e1[0] + a2x*e2[0] + self._delta_tuney += a0y*e0[1] + a1y*e1[1] + a2y*e2[1] + + self._calc_intstrength() self._pid_errs.append(e0) del self._pid_errs[0] @@ -536,10 +586,10 @@ def _check_tunes_reliability(self, tunex, tuney): return True def _check_tunes_distortion(self, tunex, tuney): - stsx_ok = abs(tunex - self._ref_tunex) <= self._max_tune_err + stsx_ok = abs(tunex - self._ref_tunex) <= self._max_tunex_err if not stsx_ok: self._update_log('WARN: Tune X is out of range.') - stsy_ok = abs(tuney - self._ref_tuney) <= self._max_tune_err + stsy_ok = abs(tuney - self._ref_tuney) <= self._max_tuney_err if not stsy_ok: self._update_log('WARN: Tune Y is out of range.') return stsx_ok and stsy_ok