def set_velocity(self, axis, new_velocity): _new_vel = new_velocity / 1000.0 # "VEL <vel>" command sets velocity in V/ms self.send_no_ans(axis, "VEL %f 0" % _new_vel) elog.debug("velocity set : %g" % _new_vel)
def read_velocity(self, axis): """ Args: - <axis> : Emotion axis object. Returns: - <velocity> : float """ _ans = self.send(axis, "?VEL") # _ans should looks like '0.2 0.1' (yes with single quotes arround...) # First field is velocity (in V/ms) # Second field is "line waiting" (hummmm second field is not always present ???) _ans = _ans[1:][:-1] # (_vel, _line_waiting) = map(float, _ans.split()) _float_ans = map(float, _ans.split()) if len(_float_ans) == 1: _vel = _float_ans[0] elif len(_float_ans) == 2: (_vel, _line_waiting) = _float_ans else: print "WHAT THE F.... ?VEL answer is there ???" # V/s = V/ms * 1000 _velocity = _vel * 1000 elog.debug("read_velocity : %g " % _velocity) return _velocity
def prepare_move(self, motion): _velocity = float(motion.axis.config.get("velocity")) if _velocity == 0: elog.debug("immediate move") else: elog.debug("scan move") if motion.axis.chan_letter == "X": scan_val1 = motion.delta scan_val2 = 0 elif motion.axis.chan_letter == "Y": scan_val1 = 0 scan_val2 = motion.delta else: print "ERRORR" number_of_pixel = 1 line_mode = "C" # mode continuous (S for stepping) _cmd = "LINE %g %g %d %s" % (scan_val1, scan_val2, number_of_pixel, line_mode) elog.debug("_cmd_LINE=%s" % _cmd) self.send_no_ans(motion.axis, _cmd) _cmd = "SCAN 0 0 1 U" elog.debug("_cmd_SCAN=%s" % _cmd) self.send_no_ans(motion.axis, _cmd) _cmd = "PSHAPE ALL" elog.debug("_cmd_PSHAPE=%s" % _cmd) self.send_no_ans(motion.axis, _cmd)
def start_one(self, motion): """ - Sends 'MOV' or 'SVA' depending on closed loop mode. Args: - <motion> : Emotion motion object. Returns: - None """ ### ### hummm a bit dangerous to mix voltage and microns for the same command isnt'it ? ### if motion.axis.closed_loop: # Command in position. self.send_no_ans(motion.axis, "MOV %s %g" % (motion.axis.channel, motion.target_pos)) elog.debug("Command to piezo MOV %s %g"% (motion.axis.channel, motion.target_pos)) else: # Command in voltage. self.send_no_ans(motion.axis, "SVA %s %g" % (motion.axis.channel, motion.target_pos)) elog.debug("Command to piezo SVA %s %g"% (motion.axis.channel, motion.target_pos))
def read_acceleration(self, axis): """ returns acceleration read from flexdc controller in steps/s2 """ _acc_spss = float(self._flexdc_query("%sAC" % axis.channel)) elog.debug("read Acceleration : _acc_spss=%g " % _acc_spss) return _acc_spss
def _set_closed_loop(self, axis, onoff = True): """ Sets Closed loop status (Servo state) (SVO command) """ axis.closed_loop = onoff self.send_no_ans(axis, "SVO %s %d" % (axis.channel, onoff)) elog.debug("Piezo Servo %r" % onoff)
def prepare_move(self, motion): """ - TODO for multiple move... Args: - <motion> : Emotion motion object. Returns: - Raises: - RuntimeError('The capacitive sensor is not in its right area of function') """ self.sync(self.piezo) self.sync(self.icepap) if self.piezo.controller.name.startswith("mockup"): self.piezo.custom_get_chapi("titi") return # check for power cut self.piezo.CheckPowerCut() tad = self.piezo.Get_TAD() elog.debug("TAD : %s, %s, %s" % (tad, self.TADmax, self.TADmin)) if self.TADmax < tad or tad < self.TADmin: # raise RuntimeError("The capacitive sensor is not in its area of linear function") elog.info(""" ########################################################################## ##### The capacitive sensor is not in its area of linear function ##### ########################################################################## TAD is %s""" % tad)
def set_gate(self, axis, state): """ CTO [<TrigOutID> <CTOPam> <Value>]+ - <TrigOutID> : {1, 2, 3} - <CTOPam> : - 3: trigger mode - <Value> : {0, 2, 3, 4} - 0 : position distance - 2 : OnTarget - 3 : MinMaxThreshold <---- - 4 : Wave Generator - 5: min threshold <--- must be greater than low limit - 6: max threshold <--- must be lower than high limit - 7: polarity : 0 / 1 ex : ID trigmod min/max ID min ID max ID pol + CTO 1 3 3 1 5 0 1 6 100 1 7 1 Args: - <state> : True / False Returns: - Raises: ? """ _ch = axis.channel if state: _cmd = "CTO %d 3 3 %d 5 %g %d 6 %g %d 7 1" % (_ch, _ch, self.low_limit, _ch, self.high_limit, _ch) else: _cmd = "CTO %d 3 3 %d 5 %g %d 6 %g %d 7 0" % (_ch, _ch, self.low_limit, _ch, self.high_limit, _ch) elog.debug("set_gate : _cmd = %s" % _cmd) self.send_no_ans(axis, _cmd)
def _set_closed_loop(self, axis, onoff = True): """ Sets Closed loop status (Servo state) (SVO command) """ axis.closed_loop = onoff self.send_no_ans(axis, "SVO %s %d" % (axis.channel, onoff)) elog.debug("Piezo Servo %r" % onoff) # Only when closing loop: waits to be ON-Target. if onoff: _t0 = time.time() cl_timeout = 2 _ont_state = self._get_on_target_status(axis) elog.info(u'axis {0:s} waiting to be ONTARGET'.format(axis.name)) while((not _ont_state) or (time.time() - _t0) > cl_timeout): time.sleep(0.01) print ".", _ont_state = self._get_on_target_status(axis) if not _ont_state: elog.error('axis {0:s} NOT on-target'.format(axis.name)) raise RuntimeError("Unable to close the loop : not ON-TARGET after %gs :( " % cl_timeout) else: elog.info('axis {0:s} ONT ok after {1:g} s'.format(axis.name, time.time() - _t0)) # Updates emotion setting (internal cached) position. axis._position() # "POS?"
def start_all(self, *motion_list): """ Called once per controller with all the axis to move returns immediately, positions in motor units """ elog.debug("start_all() called")
def read_encoder(self, encoder): _ans = self.send(encoder, "MP?") _pos = hex_to_int(_ans[8:]) elog.debug( "PMD206 position measured (encoder counts) read : %d (_ans=%s)" % (_pos, _ans)) return _pos
def move_done_event_received(self, state): if self.external_gating: if state: elog.debug("movement is finished %f" % time.time()) self.gating_ds.SetGate(False) else: elog.debug("movement is starting %f" % time.time()) self.gating_ds.SetGate(True)
def test_debug(self): log.level(log.DEBUG) with wrapped_stdout() as stdout: log.debug("debugging test") output = stdout.getvalue() self.assertEquals( output, "DEBUG: test_debug ('TestLogging.py`, line 49): debugging test\n")
def stop(self, axis): """ * HLT -> stop smoothly * STP -> stop asap * 24 -> stop asap """ elog.debug("Stopping Piezo by opening loop") self._set_closed_loop(self, axis, False)
def initialize_axis(self, axis): attr_pos_name = axis.config.get("attribute_position", str) attr_vel_name = axis.config.get("attribute_velocity", str) attr_acc_name = axis.config.get("attribute_acceleration", str) self.axis_info[axis] = {"attr_pos_name": attr_pos_name, "attr_vel_name": attr_vel_name, "attr_acc_name": attr_acc_name} elog.debug("axis initilized--------------------------")
def check_power_cut(self, axis): """ checks if command level is on 1, if 0 means power has been cut in that case, set command level to 1 """ _ans = self.send(None, "CCL?") # get command level elog.debug("command_level was : %d " % int(_ans)) if _ans is "0": self.send_no_ans(None, "CCL 1 advanced")
def set_velocity(self, axis, new_velocity): """ <new_velocity> is in motor units. (encoder steps) Returns velocity in motor units. """ _nv = new_velocity elog.debug("velocity NOT wrotten : %d " % _nv) return self.read_velocity(axis)
def __init__(self, name, config, axes, encoders): Controller.__init__(self, name, config, axes, encoders) self.axis_info = dict() try: self.ds_name = self.config.get("ds_name") except: elog.debug("no 'ds_name' defined in config for %s" % name)
def set_acceleration(self, axis, new_acc): """ Writes acceleration. <new_acc> is in steps/s2 Flexdc works in steps/s2 """ self._flexdc_query("%sAC=%d" % (axis.channel, new_acc)) elog.debug("write Acceleration : new_acc=%g" % new_acc) return axis.settings.get("acceleration")
def move_done_event_received(self, state): if self.auto_gate_enabled: if state is True: elog.info("PI_E517.py : movement is finished") self._set_gate(0) elog.debug("mvt finished, gate set to 0") else: elog.info("PI_E517.py : movement is starting") self._set_gate(1) elog.debug("mvt started, gate set to 1")
def read_velocity(self, axis): """ """ _ans = self.send(axis, "VEL? %s" % axis.channel) # _ans should look like "A=+0012.0000" # removes 'X=' prefix _velocity = float(_ans[2:]) elog.debug("read_velocity : %g " % _velocity) return _velocity
def state(self, axis): # if self._get_closed_loop_status(axis): if self.closed_loop: # elog.debug("CLOSED-LOOP is active") if self._get_on_target_status(axis): return AxisState("READY") else: return AxisState("MOVING") else: elog.debug("CLOSED-LOOP is not active") return AxisState("READY")
def read_position(self, axis): """ Returns position's setpoint or measured position (in steps). """ """ DP : Desired Position When an axis is in motion, DP holds the real time servo loop control reference position """ _pos = int(self._flexdc_query("%sDP" % axis.channel)) elog.debug("FLEXDC *setpoint* position (in steps) : %d" % _pos) return _pos
def _get_tns(self, axis): """Get Normalized Input Signal Value. Loop 10 times to straighten out noise""" accu = 0 for _ in range(10): _ans = self.send(axis, "TNS? %s" % axis.channel) #elog.debug("TNS? %d : %r" % (axis.channel, _ans)) if _ans != '0': accu += float(_ans[2:]) accu /= 2 elog.debug("TNS? %r" % accu) return accu
def read_velocity(self, axis): """ Args: - <axis> : Emotion axis object. Returns: - <velocity> : float : velocity in motor-units """ _velocity = 1 elog.debug("read_velocity : %d" % _velocity) return _velocity
def send_no_ans(self, axis, cmd): """ - Adds the 'newline' terminator character : "\\\\r\\\\n" - Sends command <cmd> to the VSCANNER. - Channel is defined in <cmd>. - <axis> is passed for debugging purposes. - Used for answer-less commands, then returns nothing. """ elog.debug("cmd=\"%s\" " % cmd) _cmd = cmd + "\r\n" self.serial.write(_cmd)
def _flexdc_query(self, cmd): # Adds "\r" at end of command. # TODO : test if already present ? elog.debug("SENDING : %s" % cmd) _cmd = cmd + "\r" # Adds ACK character: _cmd = _cmd + "Z" _ans = self.sock.write_readline(_cmd, eol=">Z") return _ans
def state(self, axis): elog.debug("axis.closed_loop for axis %s is %s" % (axis.name, axis.closed_loop)) if axis.closed_loop: if self._get_on_target_status(axis): return AxisState("READY") else: return AxisState("MOVING") else: elog.debug("CLOSED-LOOP is False") # ok for open loop mode... return AxisState("READY")
def move_done_event_received(self, state, sender=None): # <sender> is the axis. elog.info("move_done_event_received(state=%s axis.sender=%s)"%(state, sender.name)) if self.auto_gate_enabled: if state is True: elog.info("PI_E517.py : movement is finished") self.set_gate(sender, 0) elog.debug("mvt finished, gate set to 0") else: elog.info("PI_E517.py : movement is starting") self.set_gate(sender, 1) elog.debug("mvt started, gate set to 1")
def initialize_axis(self, axis): """ - Reads specific config - Adds specific methods - Switches piezo to ONLINE mode so that axis motion can be caused by move commands. Args: - <axis> Returns: - None """ elog.info("initialize_axis() called for axis %r" % axis.name) self._hw_status = AxisState("READY") """ Documentation uses the word AxisID instead of channel Note: any function used as axis method must accept axis as an argument! Otherwise you will see: TypeError: check_power_cut() takes exactly 1 argument (2 given) """ axis.channel = axis.config.get("channel", int) add_axis_method(axis, self.raw_com, name = "RawCom", types_info = (str, str)) add_axis_method(axis, self.check_power_cut, name = "CheckPowerCut", types_info = (None, None)) add_axis_method(axis, self._get_tns, name = "Get_TNS", types_info = (None, float)) add_axis_method(axis, self._get_tsp, name = "Get_TSP", types_info = (None, float)) add_axis_method(axis, self._get_sva, name = "Get_SVA", types_info = (None, float)) add_axis_method(axis, self._get_vol, name = "Get_VOL", types_info = (None, float)) add_axis_method(axis, self._get_mov, name = "Get_MOV", types_info = (None, float)) add_axis_method(axis, self._get_offset, name = "Get_Offset", types_info = (None, float)) add_axis_method(axis, self._put_offset, name = "Put_Offset", types_info = (float, None)) add_axis_method(axis, self._get_tad, name = "Get_TAD", types_info = (None, float)) add_axis_method(axis, self._get_closed_loop_status, name = "Get_Closed_Loop_Status", types_info = (None, bool)) add_axis_method(axis, self._set_closed_loop, name = "Set_Closed_Loop", types_info = (bool, None)) #add_axis_method(axis, self._get_on_target_status, name = "Get_On_Target_Status", types_info = (None, bool)) add_axis_method(axis, self._get_pos, name = "Get_Pos", types_info = (None, float)) try: axis.paranoia_mode = axis.config.get("paranoia_mode") # check error after each command except KeyError : axis.paranoia_mode = False self._gate_enabled = False # Updates cached value of closed loop status. axis.closed_loop = self._get_closed_loop_status(axis) self.check_power_cut(axis) elog.debug("axis = %r" % axis.name)