From b94035b1b0c99e11cb367b2ad7a72917c662e3c9 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Sun, 20 Nov 2022 19:45:52 +0000 Subject: [PATCH 01/16] Add initial implementation --- galil_seci_checker/galil_check.py | 294 ++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 galil_seci_checker/galil_check.py diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py new file mode 100644 index 00000000..70a6bba0 --- /dev/null +++ b/galil_seci_checker/galil_check.py @@ -0,0 +1,294 @@ +# +# parse a Galil.ini from SECI and check it against PVs from galil IOC on instrument +# +# You need to have the NDX c$ mapped (i.e. \\ndxYYYY\c$) so it is readable by script +# +import configparser +import argparse +from genie_python import genie as g + +INST = "" + +PVPREFIX = "" + +CONFIGFILE = "" + +MOTOR_TYPES = { 0 : "Servo", 1 : "Rev Servo", 2 : "HA Stepper", 3 : "LA Stepper", 4 : "Rev HA Stepper", 5 : "Rev LA Stepper" } + +# seci defines an encoder type for analogue feedback, but epics does not. galil manual is unclear - it suggests you should use +# the normal types here and AF parameter to say if these types receive digital or analogue signals +ENCODER_TYPES = { 0 : "Normal Quadrature", 1 : "Pulse and Dir", 2 : "Reverse Quadrature", 3 : "Rev Pulse and Dir", 4 : "Analogue??" } + +HOME_METHODS = { 0 : "none", 1 : "signal", 2 : "reverse limit", 3 : "forward limit" } + +SHOW_VALUE_OK = False + +def main(): + global INST, PVPREFIX, CONFIGFILE, SHOW_VALUE_OK + try: + parser = argparse.ArgumentParser() + parser.add_argument('--inst', help='instrument', required=True) + parser.add_argument('--verbose', help='verbose', action='count', default=0) + args = parser.parse_args() + INST = args.inst.upper() + PVPREFIX = f"IN:{INST}:MOT:" + CONFIGFILE = r"\\NDX{}\c$\LABVIEW MODULES\Drivers\Galil DMC2280\Galil.ini".format(INST) + if args.verbose > 0: + SHOW_VALUE_OK = True + config = configparser.ConfigParser() + config.read(CONFIGFILE) + for g in config.keys(): + if g == "DEFAULT": + if len(config[g]) > 0: + raise Exception("error - non empty DEFAULT") + continue + doController(config[g], g) + except Exception as ex: + print(ex) + +# note key names are lowercased by the parser e.g. use "motor steps per unit", "kp" +# however section names and values preserve case +def doAxis(config, galil, axis): + mn = motorNumber(galil, axis) + msteps_per_unit = config.getfloat(axisItem(axis, 'motor steps per unit')) + esteps_per_unit = config.getfloat(axisItem(axis, 'encoder steps per unit')) + eres = 1.0 / esteps_per_unit if esteps_per_unit != 0.0 else 0.0 + mres = 1.0 / msteps_per_unit if msteps_per_unit != 0.0 else 0.0 + speed = config.getfloat(axisItem(axis, 'speed')) + velo = speed * mres + accl = config.getfloat(axisItem(axis, 'acceleration')) + dccl = config.getfloat(axisItem(axis, 'deceleration')) + edel_multiplier = 2 # encoder steps for edel + epics_accl = speed / accl if accl != 0.0 else 0.0 # epics acceleration is time to reach velocity + motor_used = config.getboolean(axisItem(axis, "used")) + + if not motor_used: + print(f"INFO: Skipping {mn} as not used in seci") + return + + for item in ['initialisation', 'before move', 'after move', 'move call', 'home call']: # , 'set points' + value = config.get(axisItem(axis, item)) + if value is not None and value != '""': + print(f"WARNING: {mn} {item} in seci {galil} axis {axis} is {value}") + + # normally like ITA=1\0AKSA=1.313 + init_bits = config.get(axisItem(axis, 'initialisation')).replace('"','').split(r'\0A') + for init in init_bits: + if len(init) > 0: + (name, value) = init.split('=') + init_axis = name[2].lower() + init_mn = motorNumber(galil, init_axis) + item = name[:2] + if init_axis != axis: + print(f"WARNING: initialisation string {name} does not refer to current axis") + if item == 'IT': + doValue(f"{init_mn}_ITCSMOOTH_SP", value, f"{init_mn}_ITCSMOOTH_MON") + elif item == 'PL': + doValue(f"{init_mn}_POLE_SP", value, f"{init_mn}_POLE_MON") + elif item == 'KS': + doValue(f"{init_mn}_STEPSMOOTH_SP", value, f"{init_mn}_STEPSMOOTH_MON") + elif item == 'OF': + doValue(f"{init_mn}_BIASVOLTAGE_SP", value, f"{init_mn}_BIASVOLTAGE_MON") + elif item == 'OE': + doValue(f"{init_mn}_OFFONERR_CMD", value, f"{init_mn}_OFFONERR_STATUS") + elif item == 'ER': + doValue(f"{init_mn}_ERRLIMIT_SP", value, f"{init_mn}_ERRLIMIT_MON") + else: + doValue(f"{init_mn}_{item}_SP", value, f"{init_mn}_{item}_MONITOR") + for item in ['PREM', 'POST', 'INIT']: + value = g.get_pv(f"{PVPREFIX}{mn}.{item}") + if value is not None and value != "": + print(f"INFO: {PVPREFIX}{mn}.{item} is \"{value}\"") + + doValue(f"{mn}.EGU", config.get(axisItem(axis, 'unit label'))) + doValue(f"{mn}.DESC", config.get(axisItem(axis, 'motor name'))) + ueip = config.getboolean(axisItem(axis, 'encoder present')) + doValue(f"{mn}.UEIP", 'Yes' if ueip else 'No') + for item in ['k1', 'k2', 'k3', 'zp', 'zn', 'tl', 'ct']: + uitem = item.upper() + doValue(f"{mn}_{uitem}_SP", config.getfloat(axisItem(axis, item)), f"{mn}_{uitem}_MONITOR") + doValue(f"{mn}.PCOF", config.getfloat(axisItem(axis, "kp")) / 1023.875) + doValue(f"{mn}.ICOF", config.getfloat(axisItem(axis, "ki")) / 2047.875) # note: different scaling would be needed for galil 4000 + doValue(f"{mn}.DCOF", config.getfloat(axisItem(axis, "kd")) / 4095.875) + doValue(f"{mn}.MRES", mres) + doValue(f"{mn}.ERES", eres) + doValue(f"{mn}_EDEL_SP", edel_multiplier * eres, f"{mn}_EDEL_MON") # old galil + doValue(f"{mn}_ENC_TOLERANCE_SP", edel_multiplier, f"{mn}_ENC_TOLERANCE_MON") # new galil + doValue(f"{mn}.VELO", velo) + doValue(f"{mn}.VMAX", velo) + doValue(f"{mn}.JVEL", velo) + hspeed = config.getfloat(axisItem(axis, "home speed")) + doValue(f"{mn}.HVEL", hspeed * mres) + doValue(f"{mn}.RDBD", config.getfloat(axisItem(axis, "positional accuracy"))) + doValue(f"{mn}.SPDB", config.getfloat(axisItem(axis, "set-point deadband"))) + + doValue(f"{mn}.DIR", "Neg" if config.getboolean(axisItem(axis, "negate motor direction")) else "Pos") + + doValue(f"{mn}.ACCL", epics_accl) + doValue(f"{mn}.JAR", epics_accl) + doValue(f"{mn}.BVEL", velo / 10.0) + doValue(f"{mn}.BACC", epics_accl / 10.0) + + doValue(f"{mn}.RMOD", "Default") + #doValue(f"{mn}_HOMEVAL_SP", 0) + doValue(f"{mn}_WLP_CMD", "Off") + doValue(f"{mn}_OFFDELAY_SP", 2) + doValue(f"{mn}_ONDELAY_SP", 0) + doValue(f"{mn}_JAH_CMD", "No") + + doValue(f"{mn}_MTRTYPE_CMD", MOTOR_TYPES[config.getint(axisItem(axis, "motor type"))], f"{mn}_MTRTYPE_STATUS") + doValue(f"{mn}_MENCTYPE_CMD", ENCODER_TYPES[config.getint(axisItem(axis, "encoder type"))], f"{mn}_MENCTYPE_STATUS") + + de_energise = config.getboolean(axisItem(axis, "de-energise")) + doValue(f"{mn}_AUTOONOFF_CMD", "On" if de_energise else "Off", f"{mn}_AUTOONOFF_STATUS") + doValue(f"{mn}_ON_CMD", "Off" if de_energise else "On") + + af = config.getboolean(axisItem(axis, "analog feedback")) + doValue(f"{mn}_AF_SP", af, f"{mn}_AF_MONITOR") + + doValue(f"{mn}.RTRY", 10 if ueip and config.getboolean(axisItem(axis, "correct motion")) else 0) + + doValue(f"{mn}_able", "Enable" if motor_used else "Disable") + + print(f"INFO: {mn} seci home method: ", HOME_METHODS[config.getint(axisItem(axis, "home method"))]) + + apply_home = config.getboolean(axisItem(axis, "apply home position")) + seci_home_pos = config.getfloat(axisItem(axis, "home position"), 0.0) + seci_offset = config.getfloat(axisItem(axis, "offset"), 0.0) + seci_user_offset = config.getfloat(axisItem(axis, "user offset"), 0.0) + if apply_home: + doValue(f"{mn}.OFF", seci_home_pos - seci_offset - seci_user_offset) + else: + doValue(f"{mn}.OFF", - seci_offset - seci_user_offset) + + eguaft = hspeed * hspeed / dccl / 2.0 / msteps_per_unit + doValue(f"{mn}_EGUAFTLIMIT_SP", eguaft, f"{mn}_EGUAFTLIMIT_MON") + + cp = config.getint(axisItem(axis, "CP")) + if de_energise: + cp = 0 if cp > 0 else -1 + else: + cp = -1 + doValue(f"{mn}_CP_SP", cp, f"{mn}_CP_MONITOR") + + fbl = config.getfloat(axisItem(axis, "forward backlash")) + bbl = config.getfloat(axisItem(axis, "backward backlash")) + stall_error = config.getfloat(axisItem(axis, "stall allowed error")) + if config.getboolean(axisItem(axis, "stall enable")): + stall_error = config.getfloat(axisItem(axis, "stall allowed error")) + else: + stall_error = max(abs(fbl), abs(bbl)) + stall_time = msteps_per_unit * abs(stall_error) / speed + doValue(f"{mn}_ESTALLTIME_SP", stall_time if stall_time > 1.2 else 1.2, f"{mn}_ESTALLTIME_MON") + + if config.getboolean(axisItem(axis, "rerun home")): + print(f"INFO: {mn} rerun home enabled in seci") + + backlash = 0 + if (fbl > 0 and bbl < 0): + print(f"ERROR: {mn} seci backlash problem - forward > 0 and back < 0") + if fbl > 0: + backlash = fbl + else: + if bbl <= 0: + backlash = bbl + else: + print(f"ERROR: {mn} seci backlash problem") + + doValue(f"{mn}.BDST", -backlash) + + smax = config.getfloat(axisItem(axis, "soft max")) + smax = smax if smax != float('inf') else 0 + smin = config.getfloat(axisItem(axis, "soft min")) + smin = smin if smin != float('-inf') else 0 + umax = config.getfloat(axisItem(axis, "user max")) + umin = config.getfloat(axisItem(axis, "user min")) + if umax is not None and umax != float('inf'): + print(f"umax defined {umax}") + if umin is not None and umin != float('-inf'): + print(f"umin defined {umin}") + doValue(f"{mn}.HLM", smax) + doValue(f"{mn}.LLM", smin) + +# soft min soft max home offset position ref position + # User Offset user max user min + # Home - Move Pos Home - Move After Axis A Set Points = "" Axis A Coerce Set Point = FALSE Exclude Global Move Stall Enable Stall Allowed Error +def axisItem(axis, name): + return f'axis {axis} {name}' + +def doValue(set_pv, value, read_pv=None): + prefixed_read_pv = "{}{}".format(PVPREFIX, read_pv) + prefixed_set_pv = "{}{}".format(PVPREFIX, set_pv) + current_sp = g.get_pv(prefixed_set_pv) + sp_ok = True + if isinstance(value, str): + value = value.replace('"', '') + if not compareValues(current_sp, value): + print("{} SP differs: current \"{}\" != expected \"{}\"".format(prefixed_set_pv, current_sp, value)) + sp_ok = False + elif SHOW_VALUE_OK: + print("{} SP OK \"{}\"".format(prefixed_set_pv, current_sp)) + if read_pv is not None: + current_rbv = g.get_pv(prefixed_read_pv) + if not compareValues(current_rbv, value): + if sp_ok: + print("{} RBV differs (but SP was OK): currrent \"{}\" != expected \"{}\"".format(prefixed_read_pv, current_rbv, value)) + else: + print("{} RBV differs: currrent \"{}\" != expected \"{}\"".format(prefixed_read_pv, current_rbv, value)) + elif SHOW_VALUE_OK or not sp_ok: + print("{} RBV OK: \"{}\"".format(prefixed_read_pv, current_rbv)) + + +def doController(config, galil): + cn = controllerNumber(galil) + enable = config.getboolean("enable") + if enable: + print(f"INFO: Seci Controller {galil} -> EPICS DMC{cn} MTR{cn}xx") + ip = config["ip address"] + com = config["com port"] + address_pv = "{}{}{}".format(PVPREFIX, dmc(galil), ":ADDRESS_MON") + address = g.get_pv(address_pv) + print(f"INFO: SECI ip {ip} COM {com} - current EPICS address {address}") + if (config.get("galil init", '""') != '""'): + print("WARNING: seci galil init is {}, inhibit {}, in {}".format(config["galil init"], config["galil init inhibit"], galil)) + if (config.get("program", '""') != '""'): + print("WARNING: seci program is {} in {}".format(config["program"], galil)) + for axis_no in range(8): + axis = chr(ord('a') + axis_no) + if config.get(f"axis {axis} motor name") is not None: + doAxis(config, galil, axis) + else: + print(f"INFO: Skipping Controller {galil} (DMC{cn} MTR{cn}xx) as not enabled in seci") + +# G0 -> 01 etc. +def controllerNumber(galil): + if galil[0] == 'G': + return "{:02d}".format(int(galil[1]) + 1) + +# construct MTRxxyy, axis 'a' -> 01 +def motorNumber(galil, axis): + return "MTR" + controllerNumber(galil) + "{:02d}".format(ord(axis) - ord('a') + 1) + +def dmc(galil): + return "DMC" + controllerNumber(galil) + +# return True is same else false +def compareValues(val1, val2): + tolerance = 0.003 + try: + v1 = float(val1) + v2 = float(val2) + if v1 == v2: + return True + if v1 != 0: + if abs((v1 - v2) / v1) < tolerance: + return True + return False + + except: + if val1 == val2: + return True + else: + return False + +main() From f14ee7f0dd558cfb9dec618979970d62993317ed Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Sun, 20 Nov 2022 23:29:17 +0000 Subject: [PATCH 02/16] Generate settings file --- galil_seci_checker/galil_check.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 70a6bba0..282d6873 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -13,6 +13,10 @@ CONFIGFILE = "" +SETFILE = None + +SHOW_VALUE_OK = False + MOTOR_TYPES = { 0 : "Servo", 1 : "Rev Servo", 2 : "HA Stepper", 3 : "LA Stepper", 4 : "Rev HA Stepper", 5 : "Rev LA Stepper" } # seci defines an encoder type for analogue feedback, but epics does not. galil manual is unclear - it suggests you should use @@ -21,18 +25,19 @@ HOME_METHODS = { 0 : "none", 1 : "signal", 2 : "reverse limit", 3 : "forward limit" } -SHOW_VALUE_OK = False - def main(): - global INST, PVPREFIX, CONFIGFILE, SHOW_VALUE_OK + global INST, PVPREFIX, CONFIGFILE, SHOW_VALUE_OK, SETFILE try: parser = argparse.ArgumentParser() - parser.add_argument('--inst', help='instrument', required=True) + parser.add_argument('--inst', help='instrument to check', required=True) parser.add_argument('--verbose', help='verbose', action='count', default=0) + parser.add_argument('--setfile', help='generate command file to correct values', default=None) args = parser.parse_args() INST = args.inst.upper() PVPREFIX = f"IN:{INST}:MOT:" CONFIGFILE = r"\\NDX{}\c$\LABVIEW MODULES\Drivers\Galil DMC2280\Galil.ini".format(INST) + if args.setfile: + SETFILE = open(args.setfile, 'w') if args.verbose > 0: SHOW_VALUE_OK = True config = configparser.ConfigParser() @@ -45,6 +50,8 @@ def main(): doController(config[g], g) except Exception as ex: print(ex) + if SETFILE is not None: + SETFILE.close() # note key names are lowercased by the parser e.g. use "motor steps per unit", "kp" # however section names and values preserve case @@ -141,7 +148,7 @@ def doAxis(config, galil, axis): de_energise = config.getboolean(axisItem(axis, "de-energise")) doValue(f"{mn}_AUTOONOFF_CMD", "On" if de_energise else "Off", f"{mn}_AUTOONOFF_STATUS") - doValue(f"{mn}_ON_CMD", "Off" if de_energise else "On") + doValue(f"{mn}_ON_CMD", "Off" if de_energise else "On", f"{mn}_ON_STATUS") af = config.getboolean(axisItem(axis, "analog feedback")) doValue(f"{mn}_AF_SP", af, f"{mn}_AF_MONITOR") @@ -226,6 +233,9 @@ def doValue(set_pv, value, read_pv=None): if not compareValues(current_sp, value): print("{} SP differs: current \"{}\" != expected \"{}\"".format(prefixed_set_pv, current_sp, value)) sp_ok = False + if SETFILE is not None: + SETFILE.write(f"caput {prefixed_set_pv} {value}\n") + SETFILE.flush() elif SHOW_VALUE_OK: print("{} SP OK \"{}\"".format(prefixed_set_pv, current_sp)) if read_pv is not None: From db77728c49fda054eae89effa81bae77e157c601 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Mon, 21 Nov 2022 11:55:24 +0000 Subject: [PATCH 03/16] Add option to skip sections --- galil_seci_checker/galil_check.py | 86 ++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 30 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 282d6873..936b80cd 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -36,6 +36,19 @@ def main(): INST = args.inst.upper() PVPREFIX = f"IN:{INST}:MOT:" CONFIGFILE = r"\\NDX{}\c$\LABVIEW MODULES\Drivers\Galil DMC2280\Galil.ini".format(INST) + skips = {} + skips["velocity"] = True + skips["direction"] = False + skips["offset"] = True + skips["backlash"] = True + skips["limits"] = True + skips["acceleration"] = True + skips["onoff"] = False + skips["enable"] = False + skips["ueip"] = False + skips["edel"] = True + skips["eguaftlimit"] = True + skips["spdb"] = True if args.setfile: SETFILE = open(args.setfile, 'w') if args.verbose > 0: @@ -47,7 +60,7 @@ def main(): if len(config[g]) > 0: raise Exception("error - non empty DEFAULT") continue - doController(config[g], g) + doController(config[g], g, skips) except Exception as ex: print(ex) if SETFILE is not None: @@ -55,7 +68,7 @@ def main(): # note key names are lowercased by the parser e.g. use "motor steps per unit", "kp" # however section names and values preserve case -def doAxis(config, galil, axis): +def doAxis(config, galil, axis, skips): mn = motorNumber(galil, axis) msteps_per_unit = config.getfloat(axisItem(axis, 'motor steps per unit')) esteps_per_unit = config.getfloat(axisItem(axis, 'encoder steps per unit')) @@ -110,7 +123,8 @@ def doAxis(config, galil, axis): doValue(f"{mn}.EGU", config.get(axisItem(axis, 'unit label'))) doValue(f"{mn}.DESC", config.get(axisItem(axis, 'motor name'))) ueip = config.getboolean(axisItem(axis, 'encoder present')) - doValue(f"{mn}.UEIP", 'Yes' if ueip else 'No') + if not skips['ueip']: + doValue(f"{mn}.UEIP", 'Yes' if ueip else 'No') for item in ['k1', 'k2', 'k3', 'zp', 'zn', 'tl', 'ct']: uitem = item.upper() doValue(f"{mn}_{uitem}_SP", config.getfloat(axisItem(axis, item)), f"{mn}_{uitem}_MONITOR") @@ -119,43 +133,49 @@ def doAxis(config, galil, axis): doValue(f"{mn}.DCOF", config.getfloat(axisItem(axis, "kd")) / 4095.875) doValue(f"{mn}.MRES", mres) doValue(f"{mn}.ERES", eres) - doValue(f"{mn}_EDEL_SP", edel_multiplier * eres, f"{mn}_EDEL_MON") # old galil - doValue(f"{mn}_ENC_TOLERANCE_SP", edel_multiplier, f"{mn}_ENC_TOLERANCE_MON") # new galil - doValue(f"{mn}.VELO", velo) - doValue(f"{mn}.VMAX", velo) - doValue(f"{mn}.JVEL", velo) + if not skips["edel"]: + doValue(f"{mn}_EDEL_SP", edel_multiplier * eres, f"{mn}_EDEL_MON") # old galil + doValue(f"{mn}_ENC_TOLERANCE_SP", edel_multiplier, f"{mn}_ENC_TOLERANCE_MON") # new galil hspeed = config.getfloat(axisItem(axis, "home speed")) - doValue(f"{mn}.HVEL", hspeed * mres) + if not skips['velocity']: + doValue(f"{mn}.VELO", velo) + doValue(f"{mn}.VMAX", velo) + doValue(f"{mn}.JVEL", velo) + doValue(f"{mn}.HVEL", hspeed * mres) doValue(f"{mn}.RDBD", config.getfloat(axisItem(axis, "positional accuracy"))) - doValue(f"{mn}.SPDB", config.getfloat(axisItem(axis, "set-point deadband"))) + if not skips["spdb"]: + doValue(f"{mn}.SPDB", config.getfloat(axisItem(axis, "set-point deadband"))) - doValue(f"{mn}.DIR", "Neg" if config.getboolean(axisItem(axis, "negate motor direction")) else "Pos") + if not skips['direction']: + doValue(f"{mn}.DIR", "Neg" if config.getboolean(axisItem(axis, "negate motor direction")) else "Pos") - doValue(f"{mn}.ACCL", epics_accl) - doValue(f"{mn}.JAR", epics_accl) - doValue(f"{mn}.BVEL", velo / 10.0) - doValue(f"{mn}.BACC", epics_accl / 10.0) + if not skips['acceleration']: + doValue(f"{mn}.ACCL", epics_accl) + doValue(f"{mn}.JAR", epics_accl) doValue(f"{mn}.RMOD", "Default") #doValue(f"{mn}_HOMEVAL_SP", 0) doValue(f"{mn}_WLP_CMD", "Off") - doValue(f"{mn}_OFFDELAY_SP", 2) - doValue(f"{mn}_ONDELAY_SP", 0) + if not skips['onoff']: + doValue(f"{mn}_OFFDELAY_SP", 2) + doValue(f"{mn}_ONDELAY_SP", 0) doValue(f"{mn}_JAH_CMD", "No") doValue(f"{mn}_MTRTYPE_CMD", MOTOR_TYPES[config.getint(axisItem(axis, "motor type"))], f"{mn}_MTRTYPE_STATUS") doValue(f"{mn}_MENCTYPE_CMD", ENCODER_TYPES[config.getint(axisItem(axis, "encoder type"))], f"{mn}_MENCTYPE_STATUS") de_energise = config.getboolean(axisItem(axis, "de-energise")) - doValue(f"{mn}_AUTOONOFF_CMD", "On" if de_energise else "Off", f"{mn}_AUTOONOFF_STATUS") - doValue(f"{mn}_ON_CMD", "Off" if de_energise else "On", f"{mn}_ON_STATUS") + if not skips['onoff']: + doValue(f"{mn}_AUTOONOFF_CMD", "On" if de_energise else "Off", f"{mn}_AUTOONOFF_STATUS") + doValue(f"{mn}_ON_CMD", "Off" if de_energise else "On", f"{mn}_ON_STATUS") af = config.getboolean(axisItem(axis, "analog feedback")) doValue(f"{mn}_AF_SP", af, f"{mn}_AF_MONITOR") doValue(f"{mn}.RTRY", 10 if ueip and config.getboolean(axisItem(axis, "correct motion")) else 0) - doValue(f"{mn}_able", "Enable" if motor_used else "Disable") + if not skips['enable']: + doValue(f"{mn}_able", "Enable" if motor_used else "Disable") print(f"INFO: {mn} seci home method: ", HOME_METHODS[config.getint(axisItem(axis, "home method"))]) @@ -163,13 +183,15 @@ def doAxis(config, galil, axis): seci_home_pos = config.getfloat(axisItem(axis, "home position"), 0.0) seci_offset = config.getfloat(axisItem(axis, "offset"), 0.0) seci_user_offset = config.getfloat(axisItem(axis, "user offset"), 0.0) - if apply_home: - doValue(f"{mn}.OFF", seci_home_pos - seci_offset - seci_user_offset) - else: - doValue(f"{mn}.OFF", - seci_offset - seci_user_offset) + if not skips['offset']: + if apply_home: + doValue(f"{mn}.OFF", seci_home_pos - seci_offset - seci_user_offset) + else: + doValue(f"{mn}.OFF", - seci_offset - seci_user_offset) eguaft = hspeed * hspeed / dccl / 2.0 / msteps_per_unit - doValue(f"{mn}_EGUAFTLIMIT_SP", eguaft, f"{mn}_EGUAFTLIMIT_MON") + if not skips["eguaftlimit"]: + doValue(f"{mn}_EGUAFTLIMIT_SP", eguaft, f"{mn}_EGUAFTLIMIT_MON") cp = config.getint(axisItem(axis, "CP")) if de_energise: @@ -202,7 +224,10 @@ def doAxis(config, galil, axis): else: print(f"ERROR: {mn} seci backlash problem") - doValue(f"{mn}.BDST", -backlash) + if not skips["backlash"]: + doValue(f"{mn}.BVEL", velo / 10.0) + doValue(f"{mn}.BACC", epics_accl / 10.0) + doValue(f"{mn}.BDST", -backlash) smax = config.getfloat(axisItem(axis, "soft max")) smax = smax if smax != float('inf') else 0 @@ -214,8 +239,9 @@ def doAxis(config, galil, axis): print(f"umax defined {umax}") if umin is not None and umin != float('-inf'): print(f"umin defined {umin}") - doValue(f"{mn}.HLM", smax) - doValue(f"{mn}.LLM", smin) + if not skips["limits"]: + doValue(f"{mn}.HLM", smax) + doValue(f"{mn}.LLM", smin) # soft min soft max home offset position ref position # User Offset user max user min @@ -249,7 +275,7 @@ def doValue(set_pv, value, read_pv=None): print("{} RBV OK: \"{}\"".format(prefixed_read_pv, current_rbv)) -def doController(config, galil): +def doController(config, galil, skips): cn = controllerNumber(galil) enable = config.getboolean("enable") if enable: @@ -266,7 +292,7 @@ def doController(config, galil): for axis_no in range(8): axis = chr(ord('a') + axis_no) if config.get(f"axis {axis} motor name") is not None: - doAxis(config, galil, axis) + doAxis(config, galil, axis, skips) else: print(f"INFO: Skipping Controller {galil} (DMC{cn} MTR{cn}xx) as not enabled in seci") From 1c7d55bce6050d9ee4d0fc4f976dfa022ec69c23 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Tue, 22 Nov 2022 23:54:17 +0000 Subject: [PATCH 04/16] Add user limits to check --- galil_seci_checker/galil_check.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 936b80cd..3c64e5d9 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -37,18 +37,18 @@ def main(): PVPREFIX = f"IN:{INST}:MOT:" CONFIGFILE = r"\\NDX{}\c$\LABVIEW MODULES\Drivers\Galil DMC2280\Galil.ini".format(INST) skips = {} - skips["velocity"] = True + skips["velocity"] = False skips["direction"] = False - skips["offset"] = True - skips["backlash"] = True - skips["limits"] = True - skips["acceleration"] = True + skips["offset"] = False + skips["backlash"] = False + skips["limits"] = False + skips["acceleration"] = False skips["onoff"] = False skips["enable"] = False skips["ueip"] = False - skips["edel"] = True - skips["eguaftlimit"] = True - skips["spdb"] = True + skips["edel"] = False + skips["eguaftlimit"] = False + skips["spdb"] = False if args.setfile: SETFILE = open(args.setfile, 'w') if args.verbose > 0: @@ -236,10 +236,14 @@ def doAxis(config, galil, axis, skips): umax = config.getfloat(axisItem(axis, "user max")) umin = config.getfloat(axisItem(axis, "user min")) if umax is not None and umax != float('inf'): - print(f"umax defined {umax}") + print(f"user max defined as {umax} with soft max as {smax}, will use lower value, check that is correct") + smax = min(smax, umax) if umin is not None and umin != float('-inf'): - print(f"umin defined {umin}") - if not skips["limits"]: + print(f"user min defined as {umin} with soft min as {smin}, will use higher value, check that is correct") + smin = max(smin, umin) + if (smin > smax): + print(f"ERROR: SECI min limit {smin} > SECI max limit {smax}, will not adjust limits") + elif not skips["limits"]: doValue(f"{mn}.HLM", smax) doValue(f"{mn}.LLM", smin) From a15d06d63afb751843d5864f03ee6d0ab4eb1309 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Wed, 23 Nov 2022 00:23:34 +0000 Subject: [PATCH 05/16] Print homing details --- galil_seci_checker/galil_check.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 3c64e5d9..72aece73 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -181,8 +181,10 @@ def doAxis(config, galil, axis, skips): apply_home = config.getboolean(axisItem(axis, "apply home position")) seci_home_pos = config.getfloat(axisItem(axis, "home position"), 0.0) + seci_home_offset = config.getfloat(axisItem(axis, "home offset"), 0.0) seci_offset = config.getfloat(axisItem(axis, "offset"), 0.0) seci_user_offset = config.getfloat(axisItem(axis, "user offset"), 0.0) + print(f"INFO: {mn} seci home position {seci_home_pos} (apply: {apply_home}) home offset {seci_home_offset} offset {seci_offset} user offset {seci_user_offset}") if not skips['offset']: if apply_home: doValue(f"{mn}.OFF", seci_home_pos - seci_offset - seci_user_offset) From 9680788f0975d7a9091b0af0735fe5d3d7b26d27 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Wed, 23 Nov 2022 00:49:19 +0000 Subject: [PATCH 06/16] Print negated direction info --- galil_seci_checker/galil_check.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 72aece73..a4237957 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -81,6 +81,7 @@ def doAxis(config, galil, axis, skips): edel_multiplier = 2 # encoder steps for edel epics_accl = speed / accl if accl != 0.0 else 0.0 # epics acceleration is time to reach velocity motor_used = config.getboolean(axisItem(axis, "used")) + negate_direction = config.getboolean(axisItem(axis, "negate motor direction")) if not motor_used: print(f"INFO: Skipping {mn} as not used in seci") @@ -145,9 +146,10 @@ def doAxis(config, galil, axis, skips): doValue(f"{mn}.RDBD", config.getfloat(axisItem(axis, "positional accuracy"))) if not skips["spdb"]: doValue(f"{mn}.SPDB", config.getfloat(axisItem(axis, "set-point deadband"))) - + if negate_direction: + print(f"INFO: {mn} has seci negated direction") if not skips['direction']: - doValue(f"{mn}.DIR", "Neg" if config.getboolean(axisItem(axis, "negate motor direction")) else "Pos") + doValue(f"{mn}.DIR", "Neg" if negate_direction else "Pos") if not skips['acceleration']: doValue(f"{mn}.ACCL", epics_accl) From 4ca5c957c6be34280644314b8ee1f7efcc480d58 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Tue, 24 Sep 2024 10:59:51 +0100 Subject: [PATCH 07/16] Add --nocheck option --- galil_seci_checker/galil_check.py | 68 ++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index a4237957..ac639f59 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -5,6 +5,7 @@ # import configparser import argparse +import os from genie_python import genie as g INST = "" @@ -15,8 +16,12 @@ SETFILE = None +CHANGEFILE = None + SHOW_VALUE_OK = False +NOCHECK = False + MOTOR_TYPES = { 0 : "Servo", 1 : "Rev Servo", 2 : "HA Stepper", 3 : "LA Stepper", 4 : "Rev HA Stepper", 5 : "Rev LA Stepper" } # seci defines an encoder type for analogue feedback, but epics does not. galil manual is unclear - it suggests you should use @@ -26,16 +31,25 @@ HOME_METHODS = { 0 : "none", 1 : "signal", 2 : "reverse limit", 3 : "forward limit" } def main(): - global INST, PVPREFIX, CONFIGFILE, SHOW_VALUE_OK, SETFILE + global INST, PVPREFIX, CONFIGFILE, SHOW_VALUE_OK, SETFILE, CHANGEFILE, NOCHECK try: parser = argparse.ArgumentParser() - parser.add_argument('--inst', help='instrument to check', required=True) + parser.add_argument('--inst', help='instrument to check e.g. CRISP (default: local system)', default=None) parser.add_argument('--verbose', help='verbose', action='count', default=0) - parser.add_argument('--setfile', help='generate command file to correct values', default=None) + parser.add_argument('--setfile', help='name of command file to generate with all values to set', default=None) + parser.add_argument('--changefile', help='name of command file to generate with changes to values', default=None) + parser.add_argument('--nocheck', help='do not try and connect to PVs', action='store_true') args = parser.parse_args() - INST = args.inst.upper() - PVPREFIX = f"IN:{INST}:MOT:" - CONFIGFILE = r"\\NDX{}\c$\LABVIEW MODULES\Drivers\Galil DMC2280\Galil.ini".format(INST) + if args.inst is not None: + INST = args.inst.upper() + PVPREFIX = f"IN:{INST}:MOT:" + CONFIGFILE = r"\\NDX{}\c$\LABVIEW MODULES\Drivers\Galil DMC2280\Galil.ini".format(INST) + else: + PVPREFIX = os.getenv("MYPVPREFIX") + "MOT:" + CONFIGFILE = r"c:\LABVIEW MODULES\Drivers\Galil DMC2280\Galil.ini" + + if args.nocheck: + NOCHECK = args.nocheck skips = {} skips["velocity"] = False skips["direction"] = False @@ -51,9 +65,11 @@ def main(): skips["spdb"] = False if args.setfile: SETFILE = open(args.setfile, 'w') + if args.changefile: + CHANGEFILE = open(args.changefile, 'w') if args.verbose > 0: SHOW_VALUE_OK = True - config = configparser.ConfigParser() + config = configparser.ConfigParser(interpolation=None) config.read(CONFIGFILE) for g in config.keys(): if g == "DEFAULT": @@ -65,6 +81,8 @@ def main(): print(ex) if SETFILE is not None: SETFILE.close() + if CHANGEFILE is not None: + CHANGEFILE.close() # note key names are lowercased by the parser e.g. use "motor steps per unit", "kp" # however section names and values preserve case @@ -95,7 +113,7 @@ def doAxis(config, galil, axis, skips): # normally like ITA=1\0AKSA=1.313 init_bits = config.get(axisItem(axis, 'initialisation')).replace('"','').split(r'\0A') for init in init_bits: - if len(init) > 0: + if len(init) > 0 and '=' in init: (name, value) = init.split('=') init_axis = name[2].lower() init_mn = motorNumber(galil, init_axis) @@ -116,10 +134,11 @@ def doAxis(config, galil, axis, skips): doValue(f"{init_mn}_ERRLIMIT_SP", value, f"{init_mn}_ERRLIMIT_MON") else: doValue(f"{init_mn}_{item}_SP", value, f"{init_mn}_{item}_MONITOR") - for item in ['PREM', 'POST', 'INIT']: - value = g.get_pv(f"{PVPREFIX}{mn}.{item}") - if value is not None and value != "": - print(f"INFO: {PVPREFIX}{mn}.{item} is \"{value}\"") + if not NOCHECK: + for item in ['PREM', 'POST', 'INIT']: + value = g.get_pv(f"{PVPREFIX}{mn}.{item}") + if value is not None and value != "": + print(f"INFO: {PVPREFIX}{mn}.{item} is \"{value}\"") doValue(f"{mn}.EGU", config.get(axisItem(axis, 'unit label'))) doValue(f"{mn}.DESC", config.get(axisItem(axis, 'motor name'))) @@ -228,6 +247,8 @@ def doAxis(config, galil, axis, skips): else: print(f"ERROR: {mn} seci backlash problem") + if backlash == 0: + print(f"INFO: {mn} no backlash defined in SECI, if this is correct then BVEL or BACC mismatches are not critical") if not skips["backlash"]: doValue(f"{mn}.BVEL", velo / 10.0) doValue(f"{mn}.BACC", epics_accl / 10.0) @@ -260,16 +281,21 @@ def axisItem(axis, name): def doValue(set_pv, value, read_pv=None): prefixed_read_pv = "{}{}".format(PVPREFIX, read_pv) prefixed_set_pv = "{}{}".format(PVPREFIX, set_pv) - current_sp = g.get_pv(prefixed_set_pv) - sp_ok = True if isinstance(value, str): value = value.replace('"', '') + if SETFILE is not None: + SETFILE.write(f"caput {prefixed_set_pv} {value}\n") + SETFILE.flush() + if NOCHECK: + return + current_sp = g.get_pv(prefixed_set_pv) + sp_ok = True if not compareValues(current_sp, value): print("{} SP differs: current \"{}\" != expected \"{}\"".format(prefixed_set_pv, current_sp, value)) sp_ok = False - if SETFILE is not None: - SETFILE.write(f"caput {prefixed_set_pv} {value}\n") - SETFILE.flush() + if CHANGEFILE is not None: + CHANGEFILE.write(f"caput {prefixed_set_pv} {value}\n") + CHANGEFILE.flush() elif SHOW_VALUE_OK: print("{} SP OK \"{}\"".format(prefixed_set_pv, current_sp)) if read_pv is not None: @@ -286,12 +312,14 @@ def doValue(set_pv, value, read_pv=None): def doController(config, galil, skips): cn = controllerNumber(galil) enable = config.getboolean("enable") + address = "" if enable: print(f"INFO: Seci Controller {galil} -> EPICS DMC{cn} MTR{cn}xx") ip = config["ip address"] com = config["com port"] - address_pv = "{}{}{}".format(PVPREFIX, dmc(galil), ":ADDRESS_MON") - address = g.get_pv(address_pv) + if not NOCHECK: + address_pv = "{}{}{}".format(PVPREFIX, dmc(galil), ":ADDRESS_MON") + address = g.get_pv(address_pv) print(f"INFO: SECI ip {ip} COM {com} - current EPICS address {address}") if (config.get("galil init", '""') != '""'): print("WARNING: seci galil init is {}, inhibit {}, in {}".format(config["galil init"], config["galil init inhibit"], galil)) @@ -307,7 +335,7 @@ def doController(config, galil, skips): # G0 -> 01 etc. def controllerNumber(galil): if galil[0] == 'G': - return "{:02d}".format(int(galil[1]) + 1) + return "{:02d}".format(int(galil[1]) + 1 + 2) # construct MTRxxyy, axis 'a' -> 01 def motorNumber(galil, axis): From 00fa33c563a452efc5309c2b1bd34c63e7f018e7 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Tue, 24 Sep 2024 12:04:04 +0100 Subject: [PATCH 08/16] Remove +2 to controller from testing --- galil_seci_checker/galil_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index ac639f59..e404f4ec 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -335,7 +335,7 @@ def doController(config, galil, skips): # G0 -> 01 etc. def controllerNumber(galil): if galil[0] == 'G': - return "{:02d}".format(int(galil[1]) + 1 + 2) + return "{:02d}".format(int(galil[1]) + 1) # construct MTRxxyy, axis 'a' -> 01 def motorNumber(galil, axis): From 7598abad7ec2c7b121c73f1be150f08cec9bc4d8 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Tue, 24 Sep 2024 12:26:47 +0100 Subject: [PATCH 09/16] Ruff --- galil_seci_checker/galil_check.py | 331 +++++++++++++++++++----------- 1 file changed, 208 insertions(+), 123 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index e404f4ec..ea0c8abb 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -1,11 +1,12 @@ # # parse a Galil.ini from SECI and check it against PVs from galil IOC on instrument # -# You need to have the NDX c$ mapped (i.e. \\ndxYYYY\c$) so it is readable by script +# You need to have the NDX c$ mapped (i.e. \\ndxYYYY\c$) so it is readable by script # -import configparser import argparse +import configparser import os + from genie_python import genie as g INST = "" @@ -22,23 +23,49 @@ NOCHECK = False -MOTOR_TYPES = { 0 : "Servo", 1 : "Rev Servo", 2 : "HA Stepper", 3 : "LA Stepper", 4 : "Rev HA Stepper", 5 : "Rev LA Stepper" } +MOTOR_TYPES = { + 0: "Servo", + 1: "Rev Servo", + 2: "HA Stepper", + 3: "LA Stepper", + 4: "Rev HA Stepper", + 5: "Rev LA Stepper", +} + +# seci defines an encoder type for analogue feedback, but epics does not. +# galil manual is unclear - it suggests you should use +# the normal types here and AF parameter to say if these types +# receive digital or analogue signals +ENCODER_TYPES = { + 0: "Normal Quadrature", + 1: "Pulse and Dir", + 2: "Reverse Quadrature", + 3: "Rev Pulse and Dir", + 4: "Analogue??", +} -# seci defines an encoder type for analogue feedback, but epics does not. galil manual is unclear - it suggests you should use -# the normal types here and AF parameter to say if these types receive digital or analogue signals -ENCODER_TYPES = { 0 : "Normal Quadrature", 1 : "Pulse and Dir", 2 : "Reverse Quadrature", 3 : "Rev Pulse and Dir", 4 : "Analogue??" } +HOME_METHODS = {0: "none", 1: "signal", 2: "reverse limit", 3: "forward limit"} -HOME_METHODS = { 0 : "none", 1 : "signal", 2 : "reverse limit", 3 : "forward limit" } -def main(): +def main() -> None: global INST, PVPREFIX, CONFIGFILE, SHOW_VALUE_OK, SETFILE, CHANGEFILE, NOCHECK try: parser = argparse.ArgumentParser() - parser.add_argument('--inst', help='instrument to check e.g. CRISP (default: local system)', default=None) - parser.add_argument('--verbose', help='verbose', action='count', default=0) - parser.add_argument('--setfile', help='name of command file to generate with all values to set', default=None) - parser.add_argument('--changefile', help='name of command file to generate with changes to values', default=None) - parser.add_argument('--nocheck', help='do not try and connect to PVs', action='store_true') + parser.add_argument( + "--inst", help="instrument to check e.g. CRISP (default: local system)", default=None + ) + parser.add_argument("--verbose", help="verbose", action="count", default=0) + parser.add_argument( + "--setfile", + help="name of command file to generate with all values to set", + default=None, + ) + parser.add_argument( + "--changefile", + help="name of command file to generate with changes to values", + default=None, + ) + parser.add_argument("--nocheck", help="do not try and connect to PVs", action="store_true") args = parser.parse_args() if args.inst is not None: INST = args.inst.upper() @@ -64,9 +91,9 @@ def main(): skips["eguaftlimit"] = False skips["spdb"] = False if args.setfile: - SETFILE = open(args.setfile, 'w') + SETFILE = open(args.setfile, "w") if args.changefile: - CHANGEFILE = open(args.changefile, 'w') + CHANGEFILE = open(args.changefile, "w") if args.verbose > 0: SHOW_VALUE_OK = True config = configparser.ConfigParser(interpolation=None) @@ -84,80 +111,91 @@ def main(): if CHANGEFILE is not None: CHANGEFILE.close() + # note key names are lowercased by the parser e.g. use "motor steps per unit", "kp" # however section names and values preserve case -def doAxis(config, galil, axis, skips): - mn = motorNumber(galil, axis) - msteps_per_unit = config.getfloat(axisItem(axis, 'motor steps per unit')) - esteps_per_unit = config.getfloat(axisItem(axis, 'encoder steps per unit')) +def doAxis(config: configparser.ConfigParser, galil: str, axis: str, skips: dict) -> None: + mn = motorNumber(galil, axis) + msteps_per_unit = config.getfloat(axisItem(axis, "motor steps per unit")) + esteps_per_unit = config.getfloat(axisItem(axis, "encoder steps per unit")) eres = 1.0 / esteps_per_unit if esteps_per_unit != 0.0 else 0.0 mres = 1.0 / msteps_per_unit if msteps_per_unit != 0.0 else 0.0 - speed = config.getfloat(axisItem(axis, 'speed')) + speed = config.getfloat(axisItem(axis, "speed")) velo = speed * mres - accl = config.getfloat(axisItem(axis, 'acceleration')) - dccl = config.getfloat(axisItem(axis, 'deceleration')) - edel_multiplier = 2 # encoder steps for edel - epics_accl = speed / accl if accl != 0.0 else 0.0 # epics acceleration is time to reach velocity + accl = config.getfloat(axisItem(axis, "acceleration")) + dccl = config.getfloat(axisItem(axis, "deceleration")) + edel_multiplier = 2 # encoder steps for edel + epics_accl = ( + speed / accl if accl != 0.0 else 0.0 + ) # epics acceleration is time to reach velocity motor_used = config.getboolean(axisItem(axis, "used")) negate_direction = config.getboolean(axisItem(axis, "negate motor direction")) - + if not motor_used: print(f"INFO: Skipping {mn} as not used in seci") return - - for item in ['initialisation', 'before move', 'after move', 'move call', 'home call']: # , 'set points' + + for item in [ + "initialisation", + "before move", + "after move", + "move call", + "home call", + ]: # , 'set points' value = config.get(axisItem(axis, item)) if value is not None and value != '""': print(f"WARNING: {mn} {item} in seci {galil} axis {axis} is {value}") - + # normally like ITA=1\0AKSA=1.313 - init_bits = config.get(axisItem(axis, 'initialisation')).replace('"','').split(r'\0A') + init_bits = config.get(axisItem(axis, "initialisation")).replace('"', "").split(r"\0A") for init in init_bits: - if len(init) > 0 and '=' in init: - (name, value) = init.split('=') - init_axis = name[2].lower() - init_mn = motorNumber(galil, init_axis) + if len(init) > 0 and "=" in init: + (name, value) = init.split("=") + init_axis = name[2].lower() + init_mn = motorNumber(galil, init_axis) item = name[:2] if init_axis != axis: - print(f"WARNING: initialisation string {name} does not refer to current axis") - if item == 'IT': - doValue(f"{init_mn}_ITCSMOOTH_SP", value, f"{init_mn}_ITCSMOOTH_MON") - elif item == 'PL': - doValue(f"{init_mn}_POLE_SP", value, f"{init_mn}_POLE_MON") - elif item == 'KS': - doValue(f"{init_mn}_STEPSMOOTH_SP", value, f"{init_mn}_STEPSMOOTH_MON") - elif item == 'OF': - doValue(f"{init_mn}_BIASVOLTAGE_SP", value, f"{init_mn}_BIASVOLTAGE_MON") - elif item == 'OE': - doValue(f"{init_mn}_OFFONERR_CMD", value, f"{init_mn}_OFFONERR_STATUS") - elif item == 'ER': - doValue(f"{init_mn}_ERRLIMIT_SP", value, f"{init_mn}_ERRLIMIT_MON") + print(f"WARNING: initialisation string {name} does not refer to current axis") + if item == "IT": + doValue(f"{init_mn}_ITCSMOOTH_SP", value, f"{init_mn}_ITCSMOOTH_MON") + elif item == "PL": + doValue(f"{init_mn}_POLE_SP", value, f"{init_mn}_POLE_MON") + elif item == "KS": + doValue(f"{init_mn}_STEPSMOOTH_SP", value, f"{init_mn}_STEPSMOOTH_MON") + elif item == "OF": + doValue(f"{init_mn}_BIASVOLTAGE_SP", value, f"{init_mn}_BIASVOLTAGE_MON") + elif item == "OE": + doValue(f"{init_mn}_OFFONERR_CMD", value, f"{init_mn}_OFFONERR_STATUS") + elif item == "ER": + doValue(f"{init_mn}_ERRLIMIT_SP", value, f"{init_mn}_ERRLIMIT_MON") else: doValue(f"{init_mn}_{item}_SP", value, f"{init_mn}_{item}_MONITOR") if not NOCHECK: - for item in ['PREM', 'POST', 'INIT']: + for item in ["PREM", "POST", "INIT"]: value = g.get_pv(f"{PVPREFIX}{mn}.{item}") if value is not None and value != "": - print(f"INFO: {PVPREFIX}{mn}.{item} is \"{value}\"") - - doValue(f"{mn}.EGU", config.get(axisItem(axis, 'unit label'))) - doValue(f"{mn}.DESC", config.get(axisItem(axis, 'motor name'))) - ueip = config.getboolean(axisItem(axis, 'encoder present')) - if not skips['ueip']: - doValue(f"{mn}.UEIP", 'Yes' if ueip else 'No') - for item in ['k1', 'k2', 'k3', 'zp', 'zn', 'tl', 'ct']: + print(f'INFO: {PVPREFIX}{mn}.{item} is "{value}"') + + doValue(f"{mn}.EGU", config.get(axisItem(axis, "unit label"))) + doValue(f"{mn}.DESC", config.get(axisItem(axis, "motor name"))) + ueip = config.getboolean(axisItem(axis, "encoder present")) + if not skips["ueip"]: + doValue(f"{mn}.UEIP", "Yes" if ueip else "No") + for item in ["k1", "k2", "k3", "zp", "zn", "tl", "ct"]: uitem = item.upper() doValue(f"{mn}_{uitem}_SP", config.getfloat(axisItem(axis, item)), f"{mn}_{uitem}_MONITOR") doValue(f"{mn}.PCOF", config.getfloat(axisItem(axis, "kp")) / 1023.875) - doValue(f"{mn}.ICOF", config.getfloat(axisItem(axis, "ki")) / 2047.875) # note: different scaling would be needed for galil 4000 + doValue( + f"{mn}.ICOF", config.getfloat(axisItem(axis, "ki")) / 2047.875 + ) # note: different scaling would be needed for galil 4000 doValue(f"{mn}.DCOF", config.getfloat(axisItem(axis, "kd")) / 4095.875) doValue(f"{mn}.MRES", mres) doValue(f"{mn}.ERES", eres) if not skips["edel"]: - doValue(f"{mn}_EDEL_SP", edel_multiplier * eres, f"{mn}_EDEL_MON") # old galil - doValue(f"{mn}_ENC_TOLERANCE_SP", edel_multiplier, f"{mn}_ENC_TOLERANCE_MON") # new galil + doValue(f"{mn}_EDEL_SP", edel_multiplier * eres, f"{mn}_EDEL_MON") # old galil + doValue(f"{mn}_ENC_TOLERANCE_SP", edel_multiplier, f"{mn}_ENC_TOLERANCE_MON") # new galil hspeed = config.getfloat(axisItem(axis, "home speed")) - if not skips['velocity']: + if not skips["velocity"]: doValue(f"{mn}.VELO", velo) doValue(f"{mn}.VMAX", velo) doValue(f"{mn}.JVEL", velo) @@ -167,62 +205,75 @@ def doAxis(config, galil, axis, skips): doValue(f"{mn}.SPDB", config.getfloat(axisItem(axis, "set-point deadband"))) if negate_direction: print(f"INFO: {mn} has seci negated direction") - if not skips['direction']: + if not skips["direction"]: doValue(f"{mn}.DIR", "Neg" if negate_direction else "Pos") - if not skips['acceleration']: + if not skips["acceleration"]: doValue(f"{mn}.ACCL", epics_accl) doValue(f"{mn}.JAR", epics_accl) doValue(f"{mn}.RMOD", "Default") - #doValue(f"{mn}_HOMEVAL_SP", 0) + # doValue(f"{mn}_HOMEVAL_SP", 0) doValue(f"{mn}_WLP_CMD", "Off") - if not skips['onoff']: + if not skips["onoff"]: doValue(f"{mn}_OFFDELAY_SP", 2) doValue(f"{mn}_ONDELAY_SP", 0) doValue(f"{mn}_JAH_CMD", "No") - - doValue(f"{mn}_MTRTYPE_CMD", MOTOR_TYPES[config.getint(axisItem(axis, "motor type"))], f"{mn}_MTRTYPE_STATUS") - doValue(f"{mn}_MENCTYPE_CMD", ENCODER_TYPES[config.getint(axisItem(axis, "encoder type"))], f"{mn}_MENCTYPE_STATUS") - + + doValue( + f"{mn}_MTRTYPE_CMD", + MOTOR_TYPES[config.getint(axisItem(axis, "motor type"))], + f"{mn}_MTRTYPE_STATUS", + ) + doValue( + f"{mn}_MENCTYPE_CMD", + ENCODER_TYPES[config.getint(axisItem(axis, "encoder type"))], + f"{mn}_MENCTYPE_STATUS", + ) + de_energise = config.getboolean(axisItem(axis, "de-energise")) - if not skips['onoff']: + if not skips["onoff"]: doValue(f"{mn}_AUTOONOFF_CMD", "On" if de_energise else "Off", f"{mn}_AUTOONOFF_STATUS") doValue(f"{mn}_ON_CMD", "Off" if de_energise else "On", f"{mn}_ON_STATUS") - + af = config.getboolean(axisItem(axis, "analog feedback")) - doValue(f"{mn}_AF_SP", af, f"{mn}_AF_MONITOR") + doValue(f"{mn}_AF_SP", af, f"{mn}_AF_MONITOR") doValue(f"{mn}.RTRY", 10 if ueip and config.getboolean(axisItem(axis, "correct motion")) else 0) - - if not skips['enable']: + + if not skips["enable"]: doValue(f"{mn}_able", "Enable" if motor_used else "Disable") - print(f"INFO: {mn} seci home method: ", HOME_METHODS[config.getint(axisItem(axis, "home method"))]) + print( + f"INFO: {mn} seci home method: ", HOME_METHODS[config.getint(axisItem(axis, "home method"))] + ) apply_home = config.getboolean(axisItem(axis, "apply home position")) seci_home_pos = config.getfloat(axisItem(axis, "home position"), 0.0) seci_home_offset = config.getfloat(axisItem(axis, "home offset"), 0.0) seci_offset = config.getfloat(axisItem(axis, "offset"), 0.0) seci_user_offset = config.getfloat(axisItem(axis, "user offset"), 0.0) - print(f"INFO: {mn} seci home position {seci_home_pos} (apply: {apply_home}) home offset {seci_home_offset} offset {seci_offset} user offset {seci_user_offset}") - if not skips['offset']: + print( + f"INFO: {mn} seci home position {seci_home_pos} (apply: {apply_home}) " + "home offset {seci_home_offset} offset {seci_offset} user offset {seci_user_offset}" + ) + if not skips["offset"]: if apply_home: doValue(f"{mn}.OFF", seci_home_pos - seci_offset - seci_user_offset) else: - doValue(f"{mn}.OFF", - seci_offset - seci_user_offset) - + doValue(f"{mn}.OFF", -seci_offset - seci_user_offset) + eguaft = hspeed * hspeed / dccl / 2.0 / msteps_per_unit if not skips["eguaftlimit"]: doValue(f"{mn}_EGUAFTLIMIT_SP", eguaft, f"{mn}_EGUAFTLIMIT_MON") - + cp = config.getint(axisItem(axis, "CP")) if de_energise: cp = 0 if cp > 0 else -1 else: cp = -1 doValue(f"{mn}_CP_SP", cp, f"{mn}_CP_MONITOR") - + fbl = config.getfloat(axisItem(axis, "forward backlash")) bbl = config.getfloat(axisItem(axis, "backward backlash")) stall_error = config.getfloat(axisItem(axis, "stall allowed error")) @@ -235,9 +286,9 @@ def doAxis(config, galil, axis, skips): if config.getboolean(axisItem(axis, "rerun home")): print(f"INFO: {mn} rerun home enabled in seci") - - backlash = 0 - if (fbl > 0 and bbl < 0): + + backlash = 0 + if fbl > 0 and bbl < 0: print(f"ERROR: {mn} seci backlash problem - forward > 0 and back < 0") if fbl > 0: backlash = fbl @@ -248,41 +299,54 @@ def doAxis(config, galil, axis, skips): print(f"ERROR: {mn} seci backlash problem") if backlash == 0: - print(f"INFO: {mn} no backlash defined in SECI, if this is correct then BVEL or BACC mismatches are not critical") + print( + f"INFO: {mn} no backlash defined in SECI, if this is correct " + "then BVEL or BACC mismatches are not critical" + ) if not skips["backlash"]: doValue(f"{mn}.BVEL", velo / 10.0) doValue(f"{mn}.BACC", epics_accl / 10.0) doValue(f"{mn}.BDST", -backlash) - + smax = config.getfloat(axisItem(axis, "soft max")) - smax = smax if smax != float('inf') else 0 + smax = smax if smax != float("inf") else 0 smin = config.getfloat(axisItem(axis, "soft min")) - smin = smin if smin != float('-inf') else 0 + smin = smin if smin != float("-inf") else 0 umax = config.getfloat(axisItem(axis, "user max")) umin = config.getfloat(axisItem(axis, "user min")) - if umax is not None and umax != float('inf'): - print(f"user max defined as {umax} with soft max as {smax}, will use lower value, check that is correct") + if umax is not None and umax != float("inf"): + print( + f"user max defined as {umax} with soft max as {smax}, " + "will use lower value, check that is correct" + ) smax = min(smax, umax) - if umin is not None and umin != float('-inf'): - print(f"user min defined as {umin} with soft min as {smin}, will use higher value, check that is correct") + if umin is not None and umin != float("-inf"): + print( + f"user min defined as {umin} with soft min as {smin}, " + "will use higher value, check that is correct" + ) smin = max(smin, umin) - if (smin > smax): - print(f"ERROR: SECI min limit {smin} > SECI max limit {smax}, will not adjust limits") + if smin > smax: + print(f"ERROR: SECI min limit {smin} > SECI max limit {smax}, will not adjust limits") elif not skips["limits"]: doValue(f"{mn}.HLM", smax) doValue(f"{mn}.LLM", smin) - -# soft min soft max home offset position ref position - # User Offset user max user min - # Home - Move Pos Home - Move After Axis A Set Points = "" Axis A Coerce Set Point = FALSE Exclude Global Move Stall Enable Stall Allowed Error -def axisItem(axis, name): - return f'axis {axis} {name}' - -def doValue(set_pv, value, read_pv=None): + + +# soft min soft max home offset position ref position +# User Offset user max user min +# Home - Move Pos Home - Move After Axis A Set Points = "" +# Axis A Coerce Set Point = FALSE Exclude Global Move Stall Enable +# Stall Allowed Error +def axisItem(axis: str, name: str) -> str: + return f"axis {axis} {name}" + + +def doValue(set_pv: str, value: str, read_pv: str | type.NoneType = None) -> None: prefixed_read_pv = "{}{}".format(PVPREFIX, read_pv) prefixed_set_pv = "{}{}".format(PVPREFIX, set_pv) if isinstance(value, str): - value = value.replace('"', '') + value = value.replace('"', "") if SETFILE is not None: SETFILE.write(f"caput {prefixed_set_pv} {value}\n") SETFILE.flush() @@ -291,25 +355,37 @@ def doValue(set_pv, value, read_pv=None): current_sp = g.get_pv(prefixed_set_pv) sp_ok = True if not compareValues(current_sp, value): - print("{} SP differs: current \"{}\" != expected \"{}\"".format(prefixed_set_pv, current_sp, value)) + print( + '{} SP differs: current "{}" != expected "{}"'.format( + prefixed_set_pv, current_sp, value + ) + ) sp_ok = False if CHANGEFILE is not None: CHANGEFILE.write(f"caput {prefixed_set_pv} {value}\n") CHANGEFILE.flush() elif SHOW_VALUE_OK: - print("{} SP OK \"{}\"".format(prefixed_set_pv, current_sp)) + print('{} SP OK "{}"'.format(prefixed_set_pv, current_sp)) if read_pv is not None: current_rbv = g.get_pv(prefixed_read_pv) if not compareValues(current_rbv, value): if sp_ok: - print("{} RBV differs (but SP was OK): currrent \"{}\" != expected \"{}\"".format(prefixed_read_pv, current_rbv, value)) + print( + '{} RBV differs (but SP was OK): currrent "{}" != expected "{}"'.format( + prefixed_read_pv, current_rbv, value + ) + ) else: - print("{} RBV differs: currrent \"{}\" != expected \"{}\"".format(prefixed_read_pv, current_rbv, value)) + print( + '{} RBV differs: currrent "{}" != expected "{}"'.format( + prefixed_read_pv, current_rbv, value + ) + ) elif SHOW_VALUE_OK or not sp_ok: - print("{} RBV OK: \"{}\"".format(prefixed_read_pv, current_rbv)) - + print('{} RBV OK: "{}"'.format(prefixed_read_pv, current_rbv)) -def doController(config, galil, skips): + +def doController(config, galil: str, skips: dict) -> None: cn = controllerNumber(galil) enable = config.getboolean("enable") address = "" @@ -320,32 +396,40 @@ def doController(config, galil, skips): if not NOCHECK: address_pv = "{}{}{}".format(PVPREFIX, dmc(galil), ":ADDRESS_MON") address = g.get_pv(address_pv) - print(f"INFO: SECI ip {ip} COM {com} - current EPICS address {address}") - if (config.get("galil init", '""') != '""'): - print("WARNING: seci galil init is {}, inhibit {}, in {}".format(config["galil init"], config["galil init inhibit"], galil)) - if (config.get("program", '""') != '""'): + print(f"INFO: SECI ip {ip} COM {com} - current EPICS address {address}") + if config.get("galil init", '""') != '""': + print( + "WARNING: seci galil init is {}, inhibit {}, in {}".format( + config["galil init"], config["galil init inhibit"], galil + ) + ) + if config.get("program", '""') != '""': print("WARNING: seci program is {} in {}".format(config["program"], galil)) for axis_no in range(8): - axis = chr(ord('a') + axis_no) + axis = chr(ord("a") + axis_no) if config.get(f"axis {axis} motor name") is not None: - doAxis(config, galil, axis, skips) + doAxis(config, galil, axis, skips) else: print(f"INFO: Skipping Controller {galil} (DMC{cn} MTR{cn}xx) as not enabled in seci") + # G0 -> 01 etc. -def controllerNumber(galil): - if galil[0] == 'G': +def controllerNumber(galil: str) -> str: + if galil[0] == "G": return "{:02d}".format(int(galil[1]) + 1) -# construct MTRxxyy, axis 'a' -> 01 -def motorNumber(galil, axis): - return "MTR" + controllerNumber(galil) + "{:02d}".format(ord(axis) - ord('a') + 1) - -def dmc(galil): + +# construct MTRxxyy, axis 'a' -> 01 +def motorNumber(galil: str, axis: str) -> str: + return "MTR" + controllerNumber(galil) + "{:02d}".format(ord(axis) - ord("a") + 1) + + +def dmc(galil: str) -> str: return "DMC" + controllerNumber(galil) + # return True is same else false -def compareValues(val1, val2): +def compareValues(val1: float | int, val2: float | int) -> bool: tolerance = 0.003 try: v1 = float(val1) @@ -357,10 +441,11 @@ def compareValues(val1, val2): return True return False - except: + except Exception: if val1 == val2: return True else: return False + main() From 8cdd88919b99e74f9594b10ee633e37dddfb099b Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Tue, 24 Sep 2024 13:03:43 +0100 Subject: [PATCH 10/16] Ruff --- galil_seci_checker/galil_check.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index ea0c8abb..55e7f1c6 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -255,7 +255,7 @@ def doAxis(config: configparser.ConfigParser, galil: str, axis: str, skips: dict seci_user_offset = config.getfloat(axisItem(axis, "user offset"), 0.0) print( f"INFO: {mn} seci home position {seci_home_pos} (apply: {apply_home}) " - "home offset {seci_home_offset} offset {seci_offset} user offset {seci_user_offset}" + f"home offset {seci_home_offset} offset {seci_offset} user offset {seci_user_offset}" ) if not skips["offset"]: if apply_home: @@ -317,13 +317,13 @@ def doAxis(config: configparser.ConfigParser, galil: str, axis: str, skips: dict if umax is not None and umax != float("inf"): print( f"user max defined as {umax} with soft max as {smax}, " - "will use lower value, check that is correct" + f"will use lower value, check that is correct" ) smax = min(smax, umax) if umin is not None and umin != float("-inf"): print( f"user min defined as {umin} with soft min as {smin}, " - "will use higher value, check that is correct" + f"will use higher value, check that is correct" ) smin = max(smin, umin) if smin > smax: From 7f1b81bcc8afb84b2a97ba4319f762aea3d32269 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Tue, 24 Sep 2024 17:13:32 +0100 Subject: [PATCH 11/16] pyright --- galil_seci_checker/galil_check.py | 211 ++++++++++++++++-------------- 1 file changed, 111 insertions(+), 100 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 55e7f1c6..68861f41 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -6,8 +6,10 @@ import argparse import configparser import os +import types from genie_python import genie as g +from genie_python.genie import PVBaseValue, PVValue INST = "" @@ -72,7 +74,7 @@ def main() -> None: PVPREFIX = f"IN:{INST}:MOT:" CONFIGFILE = r"\\NDX{}\c$\LABVIEW MODULES\Drivers\Galil DMC2280\Galil.ini".format(INST) else: - PVPREFIX = os.getenv("MYPVPREFIX") + "MOT:" + PVPREFIX = os.getenv("MYPVPREFIX", default="") + "MOT:" CONFIGFILE = r"c:\LABVIEW MODULES\Drivers\Galil DMC2280\Galil.ini" if args.nocheck: @@ -103,7 +105,7 @@ def main() -> None: if len(config[g]) > 0: raise Exception("error - non empty DEFAULT") continue - doController(config[g], g, skips) + do_controller(config[g], g, skips) except Exception as ex: print(ex) if SETFILE is not None: @@ -114,22 +116,22 @@ def main() -> None: # note key names are lowercased by the parser e.g. use "motor steps per unit", "kp" # however section names and values preserve case -def doAxis(config: configparser.ConfigParser, galil: str, axis: str, skips: dict) -> None: - mn = motorNumber(galil, axis) - msteps_per_unit = config.getfloat(axisItem(axis, "motor steps per unit")) - esteps_per_unit = config.getfloat(axisItem(axis, "encoder steps per unit")) +def do_axis(config: configparser.SectionProxy, galil: str, axis: str, skips: dict) -> None: + mn = motor_number(galil, axis) + msteps_per_unit = config.getfloat(axis_item(axis, "motor steps per unit")) + esteps_per_unit = config.getfloat(axis_item(axis, "encoder steps per unit")) eres = 1.0 / esteps_per_unit if esteps_per_unit != 0.0 else 0.0 mres = 1.0 / msteps_per_unit if msteps_per_unit != 0.0 else 0.0 - speed = config.getfloat(axisItem(axis, "speed")) + speed = config.getfloat(axis_item(axis, "speed")) velo = speed * mres - accl = config.getfloat(axisItem(axis, "acceleration")) - dccl = config.getfloat(axisItem(axis, "deceleration")) + accl = config.getfloat(axis_item(axis, "acceleration")) + dccl = config.getfloat(axis_item(axis, "deceleration")) edel_multiplier = 2 # encoder steps for edel epics_accl = ( speed / accl if accl != 0.0 else 0.0 ) # epics acceleration is time to reach velocity - motor_used = config.getboolean(axisItem(axis, "used")) - negate_direction = config.getboolean(axisItem(axis, "negate motor direction")) + motor_used = config.getboolean(axis_item(axis, "used")) + negate_direction = config.getboolean(axis_item(axis, "negate motor direction")) if not motor_used: print(f"INFO: Skipping {mn} as not used in seci") @@ -142,149 +144,154 @@ def doAxis(config: configparser.ConfigParser, galil: str, axis: str, skips: dict "move call", "home call", ]: # , 'set points' - value = config.get(axisItem(axis, item)) + value = config.get(axis_item(axis, item)) if value is not None and value != '""': print(f"WARNING: {mn} {item} in seci {galil} axis {axis} is {value}") # normally like ITA=1\0AKSA=1.313 - init_bits = config.get(axisItem(axis, "initialisation")).replace('"', "").split(r"\0A") + init_bits = config.get(axis_item(axis, "initialisation")).replace('"', "").split(r"\0A") for init in init_bits: if len(init) > 0 and "=" in init: (name, value) = init.split("=") init_axis = name[2].lower() - init_mn = motorNumber(galil, init_axis) + init_mn = motor_number(galil, init_axis) item = name[:2] if init_axis != axis: print(f"WARNING: initialisation string {name} does not refer to current axis") if item == "IT": - doValue(f"{init_mn}_ITCSMOOTH_SP", value, f"{init_mn}_ITCSMOOTH_MON") + do_value(f"{init_mn}_ITCSMOOTH_SP", value, f"{init_mn}_ITCSMOOTH_MON") elif item == "PL": - doValue(f"{init_mn}_POLE_SP", value, f"{init_mn}_POLE_MON") + do_value(f"{init_mn}_POLE_SP", value, f"{init_mn}_POLE_MON") elif item == "KS": - doValue(f"{init_mn}_STEPSMOOTH_SP", value, f"{init_mn}_STEPSMOOTH_MON") + do_value(f"{init_mn}_STEPSMOOTH_SP", value, f"{init_mn}_STEPSMOOTH_MON") elif item == "OF": - doValue(f"{init_mn}_BIASVOLTAGE_SP", value, f"{init_mn}_BIASVOLTAGE_MON") + do_value(f"{init_mn}_BIASVOLTAGE_SP", value, f"{init_mn}_BIASVOLTAGE_MON") elif item == "OE": - doValue(f"{init_mn}_OFFONERR_CMD", value, f"{init_mn}_OFFONERR_STATUS") + do_value(f"{init_mn}_OFFONERR_CMD", value, f"{init_mn}_OFFONERR_STATUS") elif item == "ER": - doValue(f"{init_mn}_ERRLIMIT_SP", value, f"{init_mn}_ERRLIMIT_MON") + do_value(f"{init_mn}_ERRLIMIT_SP", value, f"{init_mn}_ERRLIMIT_MON") else: - doValue(f"{init_mn}_{item}_SP", value, f"{init_mn}_{item}_MONITOR") + do_value(f"{init_mn}_{item}_SP", value, f"{init_mn}_{item}_MONITOR") if not NOCHECK: for item in ["PREM", "POST", "INIT"]: value = g.get_pv(f"{PVPREFIX}{mn}.{item}") if value is not None and value != "": print(f'INFO: {PVPREFIX}{mn}.{item} is "{value}"') - doValue(f"{mn}.EGU", config.get(axisItem(axis, "unit label"))) - doValue(f"{mn}.DESC", config.get(axisItem(axis, "motor name"))) - ueip = config.getboolean(axisItem(axis, "encoder present")) + do_value(f"{mn}.EGU", config.get(axis_item(axis, "unit label"))) + do_value(f"{mn}.DESC", config.get(axis_item(axis, "motor name"))) + ueip = config.getboolean(axis_item(axis, "encoder present")) if not skips["ueip"]: - doValue(f"{mn}.UEIP", "Yes" if ueip else "No") + do_value(f"{mn}.UEIP", "Yes" if ueip else "No") for item in ["k1", "k2", "k3", "zp", "zn", "tl", "ct"]: uitem = item.upper() - doValue(f"{mn}_{uitem}_SP", config.getfloat(axisItem(axis, item)), f"{mn}_{uitem}_MONITOR") - doValue(f"{mn}.PCOF", config.getfloat(axisItem(axis, "kp")) / 1023.875) - doValue( - f"{mn}.ICOF", config.getfloat(axisItem(axis, "ki")) / 2047.875 + do_value( + f"{mn}_{uitem}_SP", config.getfloat(axis_item(axis, item)), f"{mn}_{uitem}_MONITOR" + ) + do_value(f"{mn}.PCOF", config.getfloat(axis_item(axis, "kp")) / 1023.875) + do_value( + f"{mn}.ICOF", config.getfloat(axis_item(axis, "ki")) / 2047.875 ) # note: different scaling would be needed for galil 4000 - doValue(f"{mn}.DCOF", config.getfloat(axisItem(axis, "kd")) / 4095.875) - doValue(f"{mn}.MRES", mres) - doValue(f"{mn}.ERES", eres) + do_value(f"{mn}.DCOF", config.getfloat(axis_item(axis, "kd")) / 4095.875) + do_value(f"{mn}.MRES", mres) + do_value(f"{mn}.ERES", eres) if not skips["edel"]: - doValue(f"{mn}_EDEL_SP", edel_multiplier * eres, f"{mn}_EDEL_MON") # old galil - doValue(f"{mn}_ENC_TOLERANCE_SP", edel_multiplier, f"{mn}_ENC_TOLERANCE_MON") # new galil - hspeed = config.getfloat(axisItem(axis, "home speed")) + do_value(f"{mn}_EDEL_SP", edel_multiplier * eres, f"{mn}_EDEL_MON") # old galil + do_value(f"{mn}_ENC_TOLERANCE_SP", edel_multiplier, f"{mn}_ENC_TOLERANCE_MON") # new galil + hspeed = config.getfloat(axis_item(axis, "home speed")) if not skips["velocity"]: - doValue(f"{mn}.VELO", velo) - doValue(f"{mn}.VMAX", velo) - doValue(f"{mn}.JVEL", velo) - doValue(f"{mn}.HVEL", hspeed * mres) - doValue(f"{mn}.RDBD", config.getfloat(axisItem(axis, "positional accuracy"))) + do_value(f"{mn}.VELO", velo) + do_value(f"{mn}.VMAX", velo) + do_value(f"{mn}.JVEL", velo) + do_value(f"{mn}.HVEL", hspeed * mres) + do_value(f"{mn}.RDBD", config.getfloat(axis_item(axis, "positional accuracy"))) if not skips["spdb"]: - doValue(f"{mn}.SPDB", config.getfloat(axisItem(axis, "set-point deadband"))) + do_value(f"{mn}.SPDB", config.getfloat(axis_item(axis, "set-point deadband"))) if negate_direction: print(f"INFO: {mn} has seci negated direction") if not skips["direction"]: - doValue(f"{mn}.DIR", "Neg" if negate_direction else "Pos") + do_value(f"{mn}.DIR", "Neg" if negate_direction else "Pos") if not skips["acceleration"]: - doValue(f"{mn}.ACCL", epics_accl) - doValue(f"{mn}.JAR", epics_accl) + do_value(f"{mn}.ACCL", epics_accl) + do_value(f"{mn}.JAR", epics_accl) - doValue(f"{mn}.RMOD", "Default") - # doValue(f"{mn}_HOMEVAL_SP", 0) - doValue(f"{mn}_WLP_CMD", "Off") + do_value(f"{mn}.RMOD", "Default") + # do_value(f"{mn}_HOMEVAL_SP", 0) + do_value(f"{mn}_WLP_CMD", "Off") if not skips["onoff"]: - doValue(f"{mn}_OFFDELAY_SP", 2) - doValue(f"{mn}_ONDELAY_SP", 0) - doValue(f"{mn}_JAH_CMD", "No") + do_value(f"{mn}_OFFDELAY_SP", 2) + do_value(f"{mn}_ONDELAY_SP", 0) + do_value(f"{mn}_JAH_CMD", "No") - doValue( + do_value( f"{mn}_MTRTYPE_CMD", - MOTOR_TYPES[config.getint(axisItem(axis, "motor type"))], + MOTOR_TYPES[config.getint(axis_item(axis, "motor type"))], f"{mn}_MTRTYPE_STATUS", ) - doValue( + do_value( f"{mn}_MENCTYPE_CMD", - ENCODER_TYPES[config.getint(axisItem(axis, "encoder type"))], + ENCODER_TYPES[config.getint(axis_item(axis, "encoder type"))], f"{mn}_MENCTYPE_STATUS", ) - de_energise = config.getboolean(axisItem(axis, "de-energise")) + de_energise = config.getboolean(axis_item(axis, "de-energise")) if not skips["onoff"]: - doValue(f"{mn}_AUTOONOFF_CMD", "On" if de_energise else "Off", f"{mn}_AUTOONOFF_STATUS") - doValue(f"{mn}_ON_CMD", "Off" if de_energise else "On", f"{mn}_ON_STATUS") + do_value(f"{mn}_AUTOONOFF_CMD", "On" if de_energise else "Off", f"{mn}_AUTOONOFF_STATUS") + do_value(f"{mn}_ON_CMD", "Off" if de_energise else "On", f"{mn}_ON_STATUS") - af = config.getboolean(axisItem(axis, "analog feedback")) - doValue(f"{mn}_AF_SP", af, f"{mn}_AF_MONITOR") + af = config.getboolean(axis_item(axis, "analog feedback")) + do_value(f"{mn}_AF_SP", af, f"{mn}_AF_MONITOR") - doValue(f"{mn}.RTRY", 10 if ueip and config.getboolean(axisItem(axis, "correct motion")) else 0) + do_value( + f"{mn}.RTRY", 10 if ueip and config.getboolean(axis_item(axis, "correct motion")) else 0 + ) if not skips["enable"]: - doValue(f"{mn}_able", "Enable" if motor_used else "Disable") + do_value(f"{mn}_able", "Enable" if motor_used else "Disable") print( - f"INFO: {mn} seci home method: ", HOME_METHODS[config.getint(axisItem(axis, "home method"))] + f"INFO: {mn} seci home method: ", + HOME_METHODS[config.getint(axis_item(axis, "home method"))], ) - apply_home = config.getboolean(axisItem(axis, "apply home position")) - seci_home_pos = config.getfloat(axisItem(axis, "home position"), 0.0) - seci_home_offset = config.getfloat(axisItem(axis, "home offset"), 0.0) - seci_offset = config.getfloat(axisItem(axis, "offset"), 0.0) - seci_user_offset = config.getfloat(axisItem(axis, "user offset"), 0.0) + apply_home = config.getboolean(axis_item(axis, "apply home position")) + seci_home_pos = config.getfloat(axis_item(axis, "home position"), 0.0) + seci_home_offset = config.getfloat(axis_item(axis, "home offset"), 0.0) + seci_offset = config.getfloat(axis_item(axis, "offset"), 0.0) + seci_user_offset = config.getfloat(axis_item(axis, "user offset"), 0.0) print( f"INFO: {mn} seci home position {seci_home_pos} (apply: {apply_home}) " f"home offset {seci_home_offset} offset {seci_offset} user offset {seci_user_offset}" ) if not skips["offset"]: if apply_home: - doValue(f"{mn}.OFF", seci_home_pos - seci_offset - seci_user_offset) + do_value(f"{mn}.OFF", seci_home_pos - seci_offset - seci_user_offset) else: - doValue(f"{mn}.OFF", -seci_offset - seci_user_offset) + do_value(f"{mn}.OFF", -seci_offset - seci_user_offset) eguaft = hspeed * hspeed / dccl / 2.0 / msteps_per_unit if not skips["eguaftlimit"]: - doValue(f"{mn}_EGUAFTLIMIT_SP", eguaft, f"{mn}_EGUAFTLIMIT_MON") + do_value(f"{mn}_EGUAFTLIMIT_SP", eguaft, f"{mn}_EGUAFTLIMIT_MON") - cp = config.getint(axisItem(axis, "CP")) + cp = config.getint(axis_item(axis, "CP")) if de_energise: cp = 0 if cp > 0 else -1 else: cp = -1 - doValue(f"{mn}_CP_SP", cp, f"{mn}_CP_MONITOR") + do_value(f"{mn}_CP_SP", cp, f"{mn}_CP_MONITOR") - fbl = config.getfloat(axisItem(axis, "forward backlash")) - bbl = config.getfloat(axisItem(axis, "backward backlash")) - stall_error = config.getfloat(axisItem(axis, "stall allowed error")) - if config.getboolean(axisItem(axis, "stall enable")): - stall_error = config.getfloat(axisItem(axis, "stall allowed error")) + fbl = config.getfloat(axis_item(axis, "forward backlash")) + bbl = config.getfloat(axis_item(axis, "backward backlash")) + stall_error = config.getfloat(axis_item(axis, "stall allowed error")) + if config.getboolean(axis_item(axis, "stall enable")): + stall_error = config.getfloat(axis_item(axis, "stall allowed error")) else: stall_error = max(abs(fbl), abs(bbl)) stall_time = msteps_per_unit * abs(stall_error) / speed - doValue(f"{mn}_ESTALLTIME_SP", stall_time if stall_time > 1.2 else 1.2, f"{mn}_ESTALLTIME_MON") + do_value(f"{mn}_ESTALLTIME_SP", stall_time if stall_time > 1.2 else 1.2, f"{mn}_ESTALLTIME_MON") - if config.getboolean(axisItem(axis, "rerun home")): + if config.getboolean(axis_item(axis, "rerun home")): print(f"INFO: {mn} rerun home enabled in seci") backlash = 0 @@ -304,16 +311,16 @@ def doAxis(config: configparser.ConfigParser, galil: str, axis: str, skips: dict "then BVEL or BACC mismatches are not critical" ) if not skips["backlash"]: - doValue(f"{mn}.BVEL", velo / 10.0) - doValue(f"{mn}.BACC", epics_accl / 10.0) - doValue(f"{mn}.BDST", -backlash) + do_value(f"{mn}.BVEL", velo / 10.0) + do_value(f"{mn}.BACC", epics_accl / 10.0) + do_value(f"{mn}.BDST", -backlash) - smax = config.getfloat(axisItem(axis, "soft max")) + smax = config.getfloat(axis_item(axis, "soft max")) smax = smax if smax != float("inf") else 0 - smin = config.getfloat(axisItem(axis, "soft min")) + smin = config.getfloat(axis_item(axis, "soft min")) smin = smin if smin != float("-inf") else 0 - umax = config.getfloat(axisItem(axis, "user max")) - umin = config.getfloat(axisItem(axis, "user min")) + umax = config.getfloat(axis_item(axis, "user max")) + umin = config.getfloat(axis_item(axis, "user min")) if umax is not None and umax != float("inf"): print( f"user max defined as {umax} with soft max as {smax}, " @@ -329,8 +336,8 @@ def doAxis(config: configparser.ConfigParser, galil: str, axis: str, skips: dict if smin > smax: print(f"ERROR: SECI min limit {smin} > SECI max limit {smax}, will not adjust limits") elif not skips["limits"]: - doValue(f"{mn}.HLM", smax) - doValue(f"{mn}.LLM", smin) + do_value(f"{mn}.HLM", smax) + do_value(f"{mn}.LLM", smin) # soft min soft max home offset position ref position @@ -338,11 +345,11 @@ def doAxis(config: configparser.ConfigParser, galil: str, axis: str, skips: dict # Home - Move Pos Home - Move After Axis A Set Points = "" # Axis A Coerce Set Point = FALSE Exclude Global Move Stall Enable # Stall Allowed Error -def axisItem(axis: str, name: str) -> str: +def axis_item(axis: str, name: str) -> str: return f"axis {axis} {name}" -def doValue(set_pv: str, value: str, read_pv: str | type.NoneType = None) -> None: +def do_value(set_pv: str, value: str | float, read_pv: str | types.NoneType = None) -> None: prefixed_read_pv = "{}{}".format(PVPREFIX, read_pv) prefixed_set_pv = "{}{}".format(PVPREFIX, set_pv) if isinstance(value, str): @@ -354,7 +361,7 @@ def doValue(set_pv: str, value: str, read_pv: str | type.NoneType = None) -> Non return current_sp = g.get_pv(prefixed_set_pv) sp_ok = True - if not compareValues(current_sp, value): + if not compare_values(current_sp, value): print( '{} SP differs: current "{}" != expected "{}"'.format( prefixed_set_pv, current_sp, value @@ -368,7 +375,7 @@ def doValue(set_pv: str, value: str, read_pv: str | type.NoneType = None) -> Non print('{} SP OK "{}"'.format(prefixed_set_pv, current_sp)) if read_pv is not None: current_rbv = g.get_pv(prefixed_read_pv) - if not compareValues(current_rbv, value): + if not compare_values(current_rbv, value): if sp_ok: print( '{} RBV differs (but SP was OK): currrent "{}" != expected "{}"'.format( @@ -385,8 +392,8 @@ def doValue(set_pv: str, value: str, read_pv: str | type.NoneType = None) -> Non print('{} RBV OK: "{}"'.format(prefixed_read_pv, current_rbv)) -def doController(config, galil: str, skips: dict) -> None: - cn = controllerNumber(galil) +def do_controller(config: configparser.SectionProxy, galil: str, skips: dict) -> None: + cn = controller_number(galil) enable = config.getboolean("enable") address = "" if enable: @@ -408,28 +415,32 @@ def doController(config, galil: str, skips: dict) -> None: for axis_no in range(8): axis = chr(ord("a") + axis_no) if config.get(f"axis {axis} motor name") is not None: - doAxis(config, galil, axis, skips) + do_axis(config, galil, axis, skips) else: print(f"INFO: Skipping Controller {galil} (DMC{cn} MTR{cn}xx) as not enabled in seci") # G0 -> 01 etc. -def controllerNumber(galil: str) -> str: +def controller_number(galil: str) -> str: if galil[0] == "G": return "{:02d}".format(int(galil[1]) + 1) + else: + return "00" # construct MTRxxyy, axis 'a' -> 01 -def motorNumber(galil: str, axis: str) -> str: - return "MTR" + controllerNumber(galil) + "{:02d}".format(ord(axis) - ord("a") + 1) +def motor_number(galil: str, axis: str) -> str: + return "MTR" + controller_number(galil) + "{:02d}".format(ord(axis) - ord("a") + 1) def dmc(galil: str) -> str: - return "DMC" + controllerNumber(galil) + return "DMC" + controller_number(galil) # return True is same else false -def compareValues(val1: float | int, val2: float | int) -> bool: +def compare_values(val1: PVValue | str, val2: PVValue | str) -> bool: + assert isinstance(val1, PVBaseValue) + assert isinstance(val2, PVBaseValue) tolerance = 0.003 try: v1 = float(val1) From f94bd2fa7edc84db65082e09f2ec4def72a7d21d Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Wed, 25 Sep 2024 00:43:01 +0100 Subject: [PATCH 12/16] pyright --- galil_seci_checker/galil_check.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 68861f41..84f4eac3 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -8,8 +8,8 @@ import os import types -from genie_python import genie as g -from genie_python.genie import PVBaseValue, PVValue +from genie_python import genie as g # pyright: ignore +from genie_python.genie import PVBaseValue, PVValue # pyright: ignore INST = "" @@ -148,6 +148,9 @@ def do_axis(config: configparser.SectionProxy, galil: str, axis: str, skips: dic if value is not None and value != '""': print(f"WARNING: {mn} {item} in seci {galil} axis {axis} is {value}") + value = config.get(axis_item(axis, "dual position stage")) + if value is not None and value != "FALSE": + print(f"INFO: dual position stage is {value} - not sure if this is important") # normally like ITA=1\0AKSA=1.313 init_bits = config.get(axis_item(axis, "initialisation")).replace('"', "").split(r"\0A") for init in init_bits: @@ -412,6 +415,15 @@ def do_controller(config: configparser.SectionProxy, galil: str, skips: dict) -> ) if config.get("program", '""') != '""': print("WARNING: seci program is {} in {}".format(config["program"], galil)) + if SETFILE is not None: + print( + f"INFO: Setting LIMIT and HOME switch type to NO (CN-1,-1) on {dmc(galil)}. " + f"This is ususal ISIS default" + ) + SETFILE.write(f"caput {PVPREFIX}{dmc(galil)}:HOMETYPE_CMD NO\n") + SETFILE.write(f"caput {PVPREFIX}{dmc(galil)}:LIMITTYPE_CMD NO\n") + SETFILE.write(f"caput {PVPREFIX}{dmc(galil)}:SEND_CMD_STR CN-1,-1\n") + SETFILE.flush() for axis_no in range(8): axis = chr(ord("a") + axis_no) if config.get(f"axis {axis} motor name") is not None: From 1435b31a7d49f6567b6fc5ab46cc35c693b806f3 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Wed, 25 Sep 2024 13:52:37 +0100 Subject: [PATCH 13/16] Swap VELO/VMAX order --- galil_seci_checker/galil_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 84f4eac3..16c6690f 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -203,8 +203,8 @@ def do_axis(config: configparser.SectionProxy, galil: str, axis: str, skips: dic do_value(f"{mn}_ENC_TOLERANCE_SP", edel_multiplier, f"{mn}_ENC_TOLERANCE_MON") # new galil hspeed = config.getfloat(axis_item(axis, "home speed")) if not skips["velocity"]: - do_value(f"{mn}.VELO", velo) do_value(f"{mn}.VMAX", velo) + do_value(f"{mn}.VELO", velo) do_value(f"{mn}.JVEL", velo) do_value(f"{mn}.HVEL", hspeed * mres) do_value(f"{mn}.RDBD", config.getfloat(axis_item(axis, "positional accuracy"))) From 869fbc067e411ec54c1c3730dd0a4d58e2a4880e Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Sat, 28 Sep 2024 23:55:56 +0100 Subject: [PATCH 14/16] Rearrange --- galil_seci_checker/galil_check.py | 36 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 16c6690f..7225dc64 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -181,11 +181,9 @@ def do_axis(config: configparser.SectionProxy, galil: str, axis: str, skips: dic if value is not None and value != "": print(f'INFO: {PVPREFIX}{mn}.{item} is "{value}"') + do_value(f"{mn}.MRES", mres) do_value(f"{mn}.EGU", config.get(axis_item(axis, "unit label"))) do_value(f"{mn}.DESC", config.get(axis_item(axis, "motor name"))) - ueip = config.getboolean(axis_item(axis, "encoder present")) - if not skips["ueip"]: - do_value(f"{mn}.UEIP", "Yes" if ueip else "No") for item in ["k1", "k2", "k3", "zp", "zn", "tl", "ct"]: uitem = item.upper() do_value( @@ -196,11 +194,27 @@ def do_axis(config: configparser.SectionProxy, galil: str, axis: str, skips: dic f"{mn}.ICOF", config.getfloat(axis_item(axis, "ki")) / 2047.875 ) # note: different scaling would be needed for galil 4000 do_value(f"{mn}.DCOF", config.getfloat(axis_item(axis, "kd")) / 4095.875) - do_value(f"{mn}.MRES", mres) + do_value( + f"{mn}_MTRTYPE_CMD", + MOTOR_TYPES[config.getint(axis_item(axis, "motor type"))], + f"{mn}_MTRTYPE_STATUS", + ) + ueip = config.getboolean(axis_item(axis, "encoder present")) + if not skips["ueip"]: + do_value(f"{mn}.UEIP", "Yes" if ueip else "No") do_value(f"{mn}.ERES", eres) + do_value( + f"{mn}_MENCTYPE_CMD", + ENCODER_TYPES[config.getint(axis_item(axis, "encoder type"))], + f"{mn}_MENCTYPE_STATUS", + ) if not skips["edel"]: do_value(f"{mn}_EDEL_SP", edel_multiplier * eres, f"{mn}_EDEL_MON") # old galil do_value(f"{mn}_ENC_TOLERANCE_SP", edel_multiplier, f"{mn}_ENC_TOLERANCE_MON") # new galil + if negate_direction: + print(f"INFO: {mn} has seci negated direction") + if not skips["direction"]: + do_value(f"{mn}.DIR", "Neg" if negate_direction else "Pos") hspeed = config.getfloat(axis_item(axis, "home speed")) if not skips["velocity"]: do_value(f"{mn}.VMAX", velo) @@ -210,10 +224,6 @@ def do_axis(config: configparser.SectionProxy, galil: str, axis: str, skips: dic do_value(f"{mn}.RDBD", config.getfloat(axis_item(axis, "positional accuracy"))) if not skips["spdb"]: do_value(f"{mn}.SPDB", config.getfloat(axis_item(axis, "set-point deadband"))) - if negate_direction: - print(f"INFO: {mn} has seci negated direction") - if not skips["direction"]: - do_value(f"{mn}.DIR", "Neg" if negate_direction else "Pos") if not skips["acceleration"]: do_value(f"{mn}.ACCL", epics_accl) @@ -227,16 +237,6 @@ def do_axis(config: configparser.SectionProxy, galil: str, axis: str, skips: dic do_value(f"{mn}_ONDELAY_SP", 0) do_value(f"{mn}_JAH_CMD", "No") - do_value( - f"{mn}_MTRTYPE_CMD", - MOTOR_TYPES[config.getint(axis_item(axis, "motor type"))], - f"{mn}_MTRTYPE_STATUS", - ) - do_value( - f"{mn}_MENCTYPE_CMD", - ENCODER_TYPES[config.getint(axis_item(axis, "encoder type"))], - f"{mn}_MENCTYPE_STATUS", - ) de_energise = config.getboolean(axis_item(axis, "de-energise")) if not skips["onoff"]: From e1803fca56a0c9b6b2bbc60831a55dcc1f54e8b9 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Sun, 29 Sep 2024 00:10:44 +0100 Subject: [PATCH 15/16] format --- galil_seci_checker/galil_check.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index 7225dc64..cd4c64f3 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -100,12 +100,12 @@ def main() -> None: SHOW_VALUE_OK = True config = configparser.ConfigParser(interpolation=None) config.read(CONFIGFILE) - for g in config.keys(): - if g == "DEFAULT": - if len(config[g]) > 0: + for k in config.keys(): + if k == "DEFAULT": + if len(config[k]) > 0: raise Exception("error - non empty DEFAULT") continue - do_controller(config[g], g, skips) + do_controller(config[k], k, skips) except Exception as ex: print(ex) if SETFILE is not None: @@ -214,7 +214,7 @@ def do_axis(config: configparser.SectionProxy, galil: str, axis: str, skips: dic if negate_direction: print(f"INFO: {mn} has seci negated direction") if not skips["direction"]: - do_value(f"{mn}.DIR", "Neg" if negate_direction else "Pos") + do_value(f"{mn}.DIR", "Neg" if negate_direction else "Pos") hspeed = config.getfloat(axis_item(axis, "home speed")) if not skips["velocity"]: do_value(f"{mn}.VMAX", velo) @@ -237,7 +237,6 @@ def do_axis(config: configparser.SectionProxy, galil: str, axis: str, skips: dic do_value(f"{mn}_ONDELAY_SP", 0) do_value(f"{mn}_JAH_CMD", "No") - de_energise = config.getboolean(axis_item(axis, "de-energise")) if not skips["onoff"]: do_value(f"{mn}_AUTOONOFF_CMD", "On" if de_energise else "Off", f"{mn}_AUTOONOFF_STATUS") @@ -436,8 +435,7 @@ def do_controller(config: configparser.SectionProxy, galil: str, skips: dict) -> def controller_number(galil: str) -> str: if galil[0] == "G": return "{:02d}".format(int(galil[1]) + 1) - else: - return "00" + return "00" # construct MTRxxyy, axis 'a' -> 01 @@ -467,8 +465,7 @@ def compare_values(val1: PVValue | str, val2: PVValue | str) -> bool: except Exception: if val1 == val2: return True - else: - return False + return False main() From 3c1c293e5b28e704f7aa10fa2bed670114ab4064 Mon Sep 17 00:00:00 2001 From: Freddie Akeroyd Date: Sun, 29 Sep 2024 00:21:57 +0100 Subject: [PATCH 16/16] Add CAPUT_FLAGS --- galil_seci_checker/galil_check.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/galil_seci_checker/galil_check.py b/galil_seci_checker/galil_check.py index cd4c64f3..eb23b832 100644 --- a/galil_seci_checker/galil_check.py +++ b/galil_seci_checker/galil_check.py @@ -15,6 +15,8 @@ PVPREFIX = "" +CAPUT_FLAGS = "-c" + CONFIGFILE = "" SETFILE = None @@ -50,7 +52,7 @@ def main() -> None: - global INST, PVPREFIX, CONFIGFILE, SHOW_VALUE_OK, SETFILE, CHANGEFILE, NOCHECK + global INST, PVPREFIX, CONFIGFILE, SHOW_VALUE_OK, SETFILE, CHANGEFILE, NOCHECK, CAPUT_FLAGS try: parser = argparse.ArgumentParser() parser.add_argument( @@ -357,7 +359,7 @@ def do_value(set_pv: str, value: str | float, read_pv: str | types.NoneType = No if isinstance(value, str): value = value.replace('"', "") if SETFILE is not None: - SETFILE.write(f"caput {prefixed_set_pv} {value}\n") + SETFILE.write(f"caput {CAPUT_FLAGS} {prefixed_set_pv} {value}\n") SETFILE.flush() if NOCHECK: return @@ -371,7 +373,7 @@ def do_value(set_pv: str, value: str | float, read_pv: str | types.NoneType = No ) sp_ok = False if CHANGEFILE is not None: - CHANGEFILE.write(f"caput {prefixed_set_pv} {value}\n") + CHANGEFILE.write(f"caput {CAPUT_FLAGS} {prefixed_set_pv} {value}\n") CHANGEFILE.flush() elif SHOW_VALUE_OK: print('{} SP OK "{}"'.format(prefixed_set_pv, current_sp)) @@ -419,9 +421,9 @@ def do_controller(config: configparser.SectionProxy, galil: str, skips: dict) -> f"INFO: Setting LIMIT and HOME switch type to NO (CN-1,-1) on {dmc(galil)}. " f"This is ususal ISIS default" ) - SETFILE.write(f"caput {PVPREFIX}{dmc(galil)}:HOMETYPE_CMD NO\n") - SETFILE.write(f"caput {PVPREFIX}{dmc(galil)}:LIMITTYPE_CMD NO\n") - SETFILE.write(f"caput {PVPREFIX}{dmc(galil)}:SEND_CMD_STR CN-1,-1\n") + SETFILE.write(f"caput {CAPUT_FLAGS} {PVPREFIX}{dmc(galil)}:HOMETYPE_CMD NO\n") + SETFILE.write(f"caput {CAPUT_FLAGS} {PVPREFIX}{dmc(galil)}:LIMITTYPE_CMD NO\n") + SETFILE.write(f"caput {CAPUT_FLAGS} {PVPREFIX}{dmc(galil)}:SEND_CMD_STR CN-1,-1\n") SETFILE.flush() for axis_no in range(8): axis = chr(ord("a") + axis_no)