Source code for instruments.Motor_KST_ZST

# the Motor class

#import serial
import threading
from struct import unpack
import logging

[docs]def int2hexStr(integer, numberOfBytes): ''' Convert an integer to its corresponding bytearray :param integer: the number we want to convert :type integer: Integer :param numberOfBytes: The number of bytes :type numberOfBytes: Integer :returns: Mutable sequence of integers of type bytearray ''' bytes = [] for i in range(numberOfBytes): bytes.append(integer & 0x0FF) integer = integer >> 8 return bytearray(bytes)
[docs]def hexString(data): ''' Creates a string that is a byte sequense of the hex values input :param data: Example is '0A 23 34 56' ''' h_str = '' data = data.split(' ') for byte in data : h_str += r'\x' + byte return h_str.decode('string_escape')
# setup the Logger # -> should be done once # initialize the logger logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # create console handler and set level to debug ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) # create formatter formatter = logging.Formatter('[%(asctime)-15s] %(ClassName)s<%(com_port)s>: %(message)s') # add formatter to ch ch.setFormatter(formatter) # add ch to logger logger.addHandler(ch)
[docs]class Motor_KST_ZST(object): '''This class models a motor for stages''' def __init__(self, serial): ''' Constructor method :param serial: the serial object that that corresponds to the port the motor is conected :type serial: serial object ''' self.serial = serial # self.position = 0 # the position of the motor in steps self.zeros_position = 0 # the zero position self._count = -1 # internal step count from controller # request some info from controller to trigger the reading process self.serial.flushInput() self.serial.flushOutput() # MGMSG_HW_REQ_INFO self.serial.write(hexString('05 00 00 00 50 01')) self.serial.read(90) # just read the response # get the logger we loaded once in the begining self.logger = logger # extra class info - for logger self.ext = {'com_port': self.serial.port, 'ClassName': 'Motor'}
[docs] def delta_move(self, steps): ''' Relative rotation onpos the motor :param steps: the number of steps to move (negative -> backwards) :type steps: Integer ''' self.position += steps # MGMSG_MOT_MOVE_RELATIVE extended self.serial.write(hexString('48 04 06 00 D0 01')) # header self.serial.write(hexString('01 00')) # chanel id self.serial.write(int2hexStr(steps, 4)) # relative distance self.move_complete()
[docs] def abs_move(self, steps): ''' Relative rotation on the motor :param steps: the endpoint of motion :type steps: Integer ''' # MGMSG_MOT_MOVE_RELATIVE extended self.serial.write(hexString('48 04 06 00 D0 01')) # header self.serial.write(hexString('01 00')) # chanel id self.serial.write(int2hexStr(steps - self.position, 4)) # absolute distance self.position = steps # wait until move is complete self.move_complete()
[docs] def get_position(self): '''return the motors current position''' return self.position
[docs] def set_as_zero(self, new_zero): '''change the origin (zero)''' self.zeros_position = new_zero self.position -= new_zero
[docs] def set_vel_params(self, vel_init, accel, vel_fin): ''' Set the velocity parameters for the motor :param vel_init: initial velocity (steps / sec) :type vel_init: Integer :param accel: acceleration (steps / sec^2) :type accel: Integer :param vel_fin: max(final) velocity (steps / sec) :type vel_fin: Integer ''' # MGMSG_MOT_SET_VELPARAMS self.serial.write(hexString('13 04 0E 00 D0 01')) # head self.serial.write(hexString('01 00')) # chanel id self.serial.write(int2hexStr(vel_init, 4)) # initial velocity self.serial.write(int2hexStr(accel, 4)) # acceleration self.serial.write(int2hexStr(vel_fin, 4)) # final velocity
[docs] def close(self): '''releases motor resources''' self.serial.close()
def __str__(self): ''' <For Debugging Purposes> gives information relevant to the motor state ''' return 'position: ' + str(self.position) + '\nzeros-position: ' + str(self.zeros_position)
[docs] def move_complete(self): ''' Waits until the MOVE_COMPLETE message is received by the controller. Helper-function for delta_move() and abs_move() functions. ''' self.serial.reset_input_buffer() # read the beginning of the header response = self.serial.read(2) while response != hexString('64 04'): # MGMSG_MOT_MOVE_COMPLETED response = self.serial.read(2) # read the rest of the structure (20 bytes total) response_rest = self.serial.read(18) self._count = unpack('<l', response_rest[6:10])[0] # DEBUG self.logger.debug('move complete {}'.format(self._count), extra=self.ext) self.isMoving = False
def _get_count(self): ''':returns: the count''' return self._count def _go_to_abs(self, steps): # MGMSG_MOT_MOVE_RELATIVE extended self.serial.write(hexString('53 04 06 00 D0 01')) # header self.serial.write(hexString('01 00')) # chanel id self.serial.write(int2hexStr(steps, 4)) # absolute distance self.position = steps self.move_complete()
''' Copyright (C) 2017 Robert Polster This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. '''