import ch.psi.pshell.serial.TcpDevice as TcpDevice class LEEM2000(TcpDevice): def __init__(self, name,host="pc14062.psi.ch", port=5566): TcpDevice.__init__(self, name, host, port) self.NUMBER_MNEMONICS = 100 self._mnemonics = None self._names = None try: self.high_voltage = Channel("X11MA-ES1-PEEM:UMON", alias = "PEEM high voltage", monitored=True) except: self.high_voltage = None self.debug = False self.retries = 1 self.timeout = 1000 self.move_timeout = 600000 #5min self.homing_timeout = 600000 #5min def doInitialize(self): super(LEEM2000, self).doInitialize() def doUpdate(self): try: hv = self.get_high_voltage() except: hv = "" try: pl = self.get_preset_label() except: pl = "unknown" if self.client.isConnected() else "offline" value = "%1.3f | %s" % (hv,pl) if hv!="" or pl!="" else None self.setCache(value, None) def send_receive(self, tx, timeout = None, retries = None): if retries is None: retries = self.retries if timeout is None: timeout = self.timeout trailer = chr(0) #print "TX: ", tx, ret = self.sendReceive(tx+trailer, None,trailer, 0, timeout, retries) #print " RX: ", ret return str(ret[0:-1]).strip() def get_value(self, name, timeout = None, retries = None): cmd = "get " + name ret = self.send_receive(cmd, timeout, retries) try: value = float(ret) return value except: if self.debug: self.getLogger().info("Received invalid value for %s: %s" % (name, ret)) return None def set_value(self, name, value, timeout = None, retries = None): cmd = "set " + name + "=" + str(value) ret = self.send_receive(cmd, timeout, retries) if ret != '0': raise Exception("Error writing %s to %s: %s" % (str(value), name, ret)) def get_mnemonic(self, index, timeout = None, retries = None): cmd = "mne " + str(index) return self.send_receive(cmd, timeout, retries) def _get_mnemonics(self, timeout = None, retries = None): ret = [] for i in range(self.NUMBER_MNEMONICS): mne = self.get_mnemonic(i, timeout, retries) if mne not in [None, '', 'disabled', 'invalid']: ret.append(mne) return ret def get_mnemonics(self, timeout = None, retries = None): if self._mnemonics is None: try: self._mnemonics = self._get_mnemonics(timeout, retries) except: self.getLogger().warning("Error retrieving microscope mnemonics") return [] return self._mnemonics def get_mnemonic_values(self, timeout = None, retries = None): ret = {} for mnemonic in self.get_mnemonics(timeout, retries): ret[mnemonic] = self.get_value(mnemonic, timeout, retries) return ret def get_name(self, index, timeout = None, retries = None): cmd = "nam " + str(index) return self.send_receive(cmd, timeout, retries) def _get_names(self, timeout = None, retries = None): ret = [] for i in range(self.NUMBER_MNEMONICS): mne = self.get_name(i, timeout, retries) if mne not in [None, '', 'disabled', 'invalid', 'Manip. X', 'Manip. Y']: ret.append(mne) return ret def get_names(self, timeout = None, retries = None): if self._names is None: try: self._names = self._get_names(timeout = timeout, retries = retries) except: self.getLogger().warning("Error retrieving microscope mnemonics") return [] return self._names def get_values(self, timeout=None, retries=None): ret = {} for name in self.get_names(): ret[name] = self.get_value(name, timeout, retries) return ret def get_preset_label(self, timeout=None, retries=None): cmd = "prl" return self.send_receive(cmd, timeout, retries) def get_high_voltage(self): return self.high_voltage.get(False) def get_child(self, var, name=None, scale=None): if name is None: name=var ret = LEEM2000Child(name, var, self, scale) ret.initialize() return ret def get_positioner(self, var, name=None): if name is None: name=var ret = LEEM2000Positioner(name, var, self) ret.initialize() return ret def get_manip_motor(self, motor_id, encoder_index, name=None): if name is None: name=str(motor_id) ret = LEEM2000ManipMotor(name, motor_id, encoder_index, self) ret.initialize() return ret def get_slit_motor(self, motor_id, encoder_index, name=None): if name is None: name=str(motor_id) ret = LEEM2000SlitMotor(name, motor_id, encoder_index, self) ret.initialize() return ret def get_tilt(self, motor_id_pos, motor_id_neg, name=None): if name is None: name=str(motor_id_pos) + "_" + str(motor_id_neg) ret = LEEM2000Tilt(name, motor_id_pos, motor_id_neg, self) ret.initialize() return ret def get_motor(self, motor_id, name=None): if name is None: name=str(motor_id) ret = LEEM2000Motor(name, motor_id, self) ret.initialize() return ret def get_manip_readback(self, timeout = None, retries = None): ret = microscope.send_receive("gmv", timeout, retries) tokens = ret.split(",") return float(tokens[0]), float(tokens[1]) #motor_id = U, D, L or R def move_tilt(self, motor_id, dist_us, timeout = None, retries = None): if timeout is None: timeout = self.move_timeout cmd = "tlt " + str(motor_id) + " " + str(dist_us) ret = self.send_receive(cmd, timeout, retries) if ret != '0': raise Exception("Error moving tilt %s to %s: %s" % (str(cmd), dist_us, ret)) #Direction H or V def home_tilt(self, direction, timeout = None, retries = None): if timeout is None: timeout = self.homing_timeout cmd = "tlt " + str(direction) ret = self.send_receive(cmd, timeout, retries) if ret != '0': raise Exception("Error homing tilt %s: %s" % (str(cmd), ret)) #motor_id = 11 (X) or 10(Y) def move_motor_rel(self, motor_id, dist_us, timeout = None, retries = None): if timeout is None: timeout = self.move_timeout cmd = "mmd " + str(motor_id) + " " + str(dist_us) ret = self.send_receive(cmd, timeout, retries) if ret != '0': raise Exception("Error relative moving motor %s to %s: %s" % (str(motor_id), dist_us, ret)) def stop_motor(self, motor_id, timeout = None, retries = None): self.move_motor_rel( motor_id, 0.0, timeout = None, retries = None) def is_motor_moving(self, motor_id, timeout = None, retries = None): cmd = "mmd " + str(motor_id) + " 888888.0" if ret == '0': return False if ret == '1': return True raise Exception("Error reading motor %s state: %s" % (str(motor_id), ret)) #motor_id = 11 (X) or 10(Y) def move_motor(self, motor_id, pos_us, timeout = None, retries = None): if timeout is None: timeout = self.move_timeout cmd = "mmp " + str(motor_id) + " " + str(pos_us) ret = self.send_receive(cmd, timeout, retries) if ret != '0': raise Exception("Error moving motor %s to %s: %s" % (str(motor_id), pos_us, ret)) class LEEM2000Child(RegisterBase): def __init__(self,name, var, microscope, scale=None): RegisterBase.__init__(self,name) self.var = var self.scale = scale self.microscope = microscope def doRead(self): ret = self.microscope.get_value(self.var) if ret is not None: if self.scale is not None: ret = float(ret)*self.scale return ret def doWrite(self, val): if val is not None: if self.scale is not None: val = float(val)/self.scale self.microscope.set_value(self.var, val) class LEEM2000Positioner (PositionerBase): def __init__(self, name, var, microscope): PositionerBase.__init__(self, name, PositionerConfig()) self.var = var self.microscope = microscope self.setpoint = None def doRead(self): if self.setpoint is None: self.setpoint = self.doReadReadback() return self.setpoint def doWrite(self, val): self.microscope.set_value(self.var, val) self.setpoint = val def doReadReadback(self): return self.microscope.get_value(self.var) class LEEM2000ManipMotor(PositionerBase): def __init__(self,name, motor_id, encoder_index, microscope): PositionerBase.__init__(self,name, PositionerConfig()) self.motor_id = motor_id self.encoder_index = encoder_index self.microscope = microscope self.pos = None def doRead(self): if self.pos is None: self.pos = self.doReadReadback() return self.pos def doWrite(self, val): self.microscope.move_motor(self.motor_id, val) self.pos = None def doReadReadback(self): pos_mm= self.microscope.get_manip_readback()[self.encoder_index] return pos_mm*1000.0 class LEEM2000SlitMotor(PositionerBase): def __init__(self, name, motor_id, encoder_index, microscope): PositionerBase.__init__(self, name, PositionerConfig()) self.motor_id = motor_id self.encoder_index = encoder_index self.microscope = microscope self.pos = None def doRead(self): if self.pos is None: self.pos = float(self.doReadReadback()) return self.pos def doWrite(self, val): self.microscope.move_motor(self.motor_id, val) self.pos = None def doReadReadback(self): pos_step = self.microscope.get_value(str(self.encoder_index)) #pos_mm= self.microscope.get_manip_readback()[self.encoder_index] return pos_step*0.700 class LEEM2000Motor(PositionerBase): def __init__(self,name, motor_id, microscope): PositionerBase.__init__(self,name, PositionerConfig()) self.motor_id = motor_id self.microscope = microscope self.pos = None def doRead(self): #self.microscope.get_value(str(self.motor_id)) return self.pos def doWrite(self, val): self.microscope.move_motor(self.motor_id, val) self.pos = val class LEEM2000Tilt(RegisterBase): def __init__(self,name, motor_id_pos, motor_id_neg, microscope): RegisterBase.__init__(self,name) self.motor_id_pos = motor_id_pos self.motor_id_neg = motor_id_neg self.microscope = microscope self.pos = None def doRead(self): return self.pos def doWrite(self, val): if (val>0): print "SET TILT ", self.motor_id_pos, " -> ", val self.microscope.move_tilt(self.motor_id_pos, val) elif (val<0): print "SET TILT ", self.motor_id_neg, " -> ", -val self.microscope.move_tilt(self.motor_id_neg, -val) self.pos = val add_device (LEEM2000("microscope"), True) add_device (microscope.get_manip_motor(11, 0, "manip_x"), True) add_device (microscope.get_manip_motor(10, 1, "manip_y"), True) add_device (microscope.get_tilt('L','R', "tilt_h"), True) add_device (microscope.get_tilt('D','U', "tilt_v"), True) add_device (microscope.get_child("MOBJ","objective"), True) add_device (microscope.get_child("OSTIGA","obj_stig_a"), True) add_device (microscope.get_child("OSTIGB","obj_stig_b"), True) add_device (microscope.get_child("MDRIVE","azimuth_rot", 0.01794), True) add_device (microscope.get_child("BOMBV","bv"), True) add_device (microscope.get_child("FIL","fil"), True) add_device (microscope.get_child("STV","start_voltage"), True) add_device (microscope.get_child("OBJDX","obj_align_x"), True) add_device (microscope.get_child("OBJDY","obj_align_y"), True) add_device (microscope.get_child("HMOTSLIT","slit_motion_pos"), True) #add_device (microscope.get_child("76","slit_motion_pos"), True) #add_device (microscope.get_child("HMOTCAX","ca_motion_pos"), True) #add_device (microscope.get_child("HMOTCAY","ca_correction_pos"), True) add_device (microscope.get_motor(1, "ca_correction"), True) add_device (microscope.get_motor(2, "ca_motion"), True) add_device (microscope.get_slit_motor(7, 76, "slit_motion"), True) microscope.setPolling(5000) class TiltMotor(RegisterBase): def __init__(self, name, tilt_motor): RegisterBase.__init__(self, name) self.position = 0 self.tilt_motor = tilt_motor def doInitialize(self): self.position = 0 def doRead(self): return self.position def doWrite(self, pos): if abs(pos)>10000: raise Exception("Exceeded device range") offset = pos -self.position self.tilt_motor.write(offset) self.position = pos class Fov(ReadonlyRegisterBase): def __init__(self, name, mic): ReadonlyRegisterBase.__init__(self, name) self.mic=mic def doInitialize(self): self.position = 0 def doRead(self): ret = self.mic.get_preset_label() if ret is not None: if ":" in ret: ret = ret[0:ret.rindex(":")] return ret def init_tilt(): tilt_vertical.initialize() tilt_horizontal.initialize() add_device(TiltMotor("tilt_vertical", tilt_v), True) add_device(TiltMotor("tilt_horizontal", tilt_h), True) add_device(Fov("fov", microscope), True) tilt_vertical.polling=500 tilt_horizontal.polling=500 manip_x.polling=500 manip_y.polling=500 fov.polling=5000 azimuth_rot.precision=1 azimuth_rot.polling=5000 bv.polling=1000 fil.polling=1000 slit_motion.polling=1000 #Create a listener to the sensor, verifying the readback values. class ListenerAzimuth (DeviceListener): def onCacheChanged(self, device, value, former, timestamp,value_changed): if (device is azimuth_rot) and (value is not None): if value_changed: if self.debug: print "Azimuth angle changed: " + str(value) try: set_azimuth_rot(value) except: if self.debug: log(str(sys.exc_info()[1])) listenerAzimuth = ListenerAzimuth() listenerAzimuth.debug=True azimuth_rot.addListener(listenerAzimuth)