def sensorPowerGroupB(self, state): """| *UNUSED* | switches power of sensor group B. | Sensor group B contains either the sensors of axis 4-6 or 3 dependent on hardware of controller. """ ANC350lib.positionerSensorPowerGroupB(self.handle, ctypes.c_bool(state))
def quadratureOutputPeriod(self, quadratureno, period): """| *UNUSED* | selects the position difference which causes a step on the output AB-signal. | quadratureno: number of addressed quadrature unit (0-2). period: period in unit of actor * 1000. """ ANC350lib.positionerQuadratureOutputPeriod(self.handle, quadratureno, period)
def singleCircleMode(self, axis, state): """| *UNUSED* | switches single circle mode. | In case of activated single circle mode the number of rotations are ignored and the shortest way to target position is used. Only relevant for rotary actors. """ ANC350lib.positionerSingleCircleMode(self.handle, axis, ctypes.c_bool(state))
def trigger(self, triggerno, lowlevel, highlevel): """| *UNUSED* | sets the trigger thresholds for the external trigger. | triggerno is 0-5, lowlevel/highlevel in units of actor * 1000. """ ANC350lib.positionerTrigger(self.handle, triggerno, lowlevel, highlevel)
def load(self, axis): """| Loads a parameter file for actor configuration. | *note: this requires a pointer to a char datatype.* | the actor files are in this controller folder, their names are hard coded in the init. | *note: Attocube called the up-down actor file ANPz, I called that axis YPiezo.* :param axis: axis number from 0 to 2 for steppers and 3 to 5 for scanners :type axis: integer """ if axis < 3: filename = self.actor_name[axis] complete_filename = os.path.join(root_dir, 'controller', 'attocube', filename) self.logger.debug( 'loading actor file: {}'.format(complete_filename)) filestring = complete_filename.encode( 'utf8') # convert python string to bytes filestring_pointer = ctypes.c_char_p( filestring) # create c pointer to variable length char array ANC350lib.positionerLoad(self.handle, ctypes.c_int(axis), filestring_pointer) self.logger.debug( 'Loading actor file for attocube piezo appears to have succeeded' ) else: self.logger.warning( 'you are trying to load an actor file for a Scanner, that doesnt need any' )
def quadratureInputPeriod(self, quadratureno, period): """| *UNUSED* | selects the stepsize the controller executes when detecting a step on its input AB-signal. | quadratureno: number of addressed quadrature unit (0-2). period: stepsize in unit of actor * 1000. """ ANC350lib.positionerQuadratureInputPeriod(self.handle, quadratureno, period)
def stopMoving(self, axis): """| *UNUSED* | stops any positioning, DC level of affected axis is set to zero after stopping. :param axis: """ ANC350lib.positionerStopMoving(self.handle, axis)
def triggerModeOut(self, mode): """| *UNUSED* | selects the mode of the output trigger signals. | state: 0 disabled - inputs trigger nothing, | 1 position - the trigger outputs reacts to the defined position ranges with the selected polarity, | 2 quadrature - three pairs of trigger out signals are used to signal relative movement as AB-signals, 3 IcHaus - the trigger out signals are used to output the internal position signal of num-sensors. """ ANC350lib.positionerTriggerModeOut(self.handle, mode)
def externalStepBkwInput(self, axis, input_trigger): """| *UNUSED* | configures external step trigger input for selected axis. a trigger on this input results in a backwards single step. | input_trigger: 0 disabled, 1-6 input trigger. """ ANC350lib.positionerExternalStepBkwInput(self.handle, axis, input_trigger)
def getBandwidthLimitEnable(self, axis): """| *UNUSED* | determines status of bandwidth limiter of addressed axis. only applicable for scanner axes. """ self.status = ctypes.c_bool(None) ANC350lib.positionerGetBandwidthLimitEnable(self.handle, axis, ctypes.byref(self.status)) return self.status.value
def getReferenceRotCount(self, axis): """*UNUSED* determines actual position of addressed axis. """ self.rotcount = ANC350lib.Int32(0) ANC350lib.positionerGetReferenceRotCount(self.handle, axis, ctypes.byref(self.rotcount)) return self.rotcount.value
def triggerModeIn(self, mode): """| *UNUSED* | selects the mode of the input trigger signals. | state: 0 disabled - inputs trigger nothing, | 1 quadrature - three pairs of trigger in signals are used to accept AB-signals for relative positioning, | 2 coarse - trigger in signals are used to generate coarse steps. """ ANC350lib.positionerTriggerModeIn(self.handle, mode)
def getRotCount(self, axis): """*UNUSED* determines actual number of rotations in case of rotary actuator. """ self.rotcount = ANC350lib.Int32(0) ANC350lib.positionerGetRotCount(self.handle, axis, ctypes.byref(self.rotcount)) return self.rotcount.value
def resetPosition(self, axis): """| *UNUSED* | sets the origin to the actual position. :param axis: axis number from 0 to 2 for steppers :type axis: integer """ ANC350lib.positionerResetPosition(self.handle, axis)
def getDcInEnable(self, axis): """| *UNUSED* | determines status of dc input of addressed axis. only applicable for scanner/dither axes. """ self.status = ctypes.c_bool(None) ANC350lib.positionerGetDcInEnable(self.handle, axis, ctypes.byref(self.status)) return self.status.value
def setOutput(self, axis, state): """| *UNUSED* | activates/deactivates the addressed axis. | *no idea what that means, but sounds interesting.* :param axis: :param state: """ ANC350lib.positionerSetOutput(self.handle, axis, ctypes.c_bool(state))
def moveAbsoluteSync(self, bitmask_of_axes): """| *UNUSED* | Starts the synchronous approach to absolute target position for selected axis. | Previous movement will be stopped. | Target position for each axis defined by .setTargetPos() takes a *bitmask* of axes! | *Not clear what's the difference with moveAbsolute.* :param bitmask_of_axes: """ ANC350lib.positionerMoveAbsoluteSync(self.handle, bitmask_of_axes)
def updateAbsolute(self, axis, position): """| *UNUSED* | update s target position for a *running* approach. | function has lower performance impact on running approach compared to .moveAbsolute(). | position units are in 'unit of actor multiplied by 1000' (generally nanometres). :param axis: :param position: """ ANC350lib.positionerUpdateAbsolute(self.handle, axis, position)
def moveReference(self, axis): """| *UNUSED* | Starts approach to reference position. | Previous movement will be stopped. | *No idea whats the difference with moveRelative* :param axis: axis number from 0 to 2 for steppers :type axis: integer """ ANC350lib.positionerMoveReference(self.handle, axis)
def getReference(self, axis): """*UNUSED* determines distance of reference mark to origin. """ self.pos = ANC350lib.Int32(0) self.validity = ctypes.c_bool(None) ANC350lib.positionerGetReference(self.handle, axis, ctypes.byref(self.pos), ctypes.byref(self.validity)) return self.pos.value, self.validity.value
def check(self): """Determines number of connected attocube controller devices and their respective hardware IDs. """ self.posinf = ANC350lib.PositionerInfo() #create PositionerInfo Struct self.numconnected = ANC350lib.positionerCheck(ctypes.byref( self.posinf)) #look for positioners! if self.numconnected > 0: self.logger.debug(str(self.numconnected) + 'ANC350 connected') self.logger.debug('ANC350 with id:' + str(self.posinf.id) + 'has locked state:' + str(self.posinf.locked))
def moveSingleStep(self, axis, direction): """| Starts a one-step positioning, where the stepwidht is determined by the amplitude and frequency. | Previous movement will be stopped. :param axis: axis number from 0 to 2 for steppers :type axis: integer :param direction: can be 0 (forward) or 1 (backward) """ ANC350lib.positionerMoveSingleStep(self.handle, axis, direction)
def intEnable(self, axis, state): """Activates/deactivates internal signal generation of addressed axis; only applicable for scanner/dither axes. :param axis: axis number from 3 to 5 for scanners :type axis: integer :param state: True is enabled, False is disabled :type state: bool """ ANC350lib.positionerIntEnable(self.handle, axis, ctypes.c_bool(state))
def moveContinuous(self, axis, direction): """Starts continuously positioning with set parameters for ampl and speed and amp control respectively. :param axis: axis number from 0 to 2 for steppers :type axis: integer :param direction: can be 0 (forward) or 1 (backward) :type direction: integer """ ANC350lib.positionerMoveContinuous(self.handle, axis, direction)
def setStopDetectionSticky(self, axis, state): """| *UNUSED* | when enabled, an active stop detection status remains active until cleared manually by .clearStopDetection(). | *Is this what in Daisy is called hump detection? Than it might be useful.* :param axis: axis number from 0 to 2 for steppers :type axis: integer :param state: """ ANC350lib.positionerSetStopDetectionSticky(self.handle, axis, state)
def stopApproach(self, axis): """ | Stops approaching target/relative/reference position. | DC level of affected axis after stopping depends on setting by .setTargetGround(). | *Dont know for sure whats the difference with stopMoving.* :param axis: axis number from 0 to 2 for steppers :type axis: integer """ self.logger.info('Stopping the Approach of Stepper') ANC350lib.positionerStopApproach(self.handle, axis)
def getFrequency(self, axis): """Determines the frequency on the stepper. :param axis: axis number from 0 to 2 for steppers :type axis: integer :return: measured frequency in Hz """ self.freq = ANC350lib.Int32(0) ANC350lib.positionerGetFrequency(self.handle, axis, ctypes.byref(self.freq)) return self.freq.value
def getIntEnable(self, axis): """Determines status of internal signal generation of addressed axis. only applicable for scanner/dither axes. :param axis: axis number from 3 to 5 for scanners :type axis: integer :return: True if the INT mode is selected, False if not """ self.status = ctypes.c_bool(None) ANC350lib.positionerGetIntEnable(self.handle, axis, ctypes.byref(self.status)) return self.status.value
def stopDetection(self, axis, state): """| *UNUSED* | switches stop detection on/off. | *Is this what in Daisy is called hump detection? Than it might be useful.* :param axis: axis number from 0 to 2 for steppers :type axis: integer :param state: """ ANC350lib.positionerStopDetection(self.handle, axis, ctypes.c_bool(state))
def connect(self): """| Establishes connection to the first attocube device found. | **Pay attention: the 0 that you give to the ANC350lib.Int32 is the first attocube device; not the first of the 6 positioners.** """ self.handle = ANC350lib.Int32(0) try: ANC350lib.positionerConnect(0, ctypes.byref( self.handle)) #0 means "first device" self.logger.info('connected to first (and only) attocube device') except Exception as e: self.logger.error('unable to connect!') raise e