AlexShkarin / pyLabLib

Python package for device control and experiment automation
http://pylablib.readthedocs.io
GNU General Public License v3.0
125 stars 28 forks source link

Thorlabs Kdc 101 controller and mts50-z8 stage continuous movement #64

Open stzogas opened 8 months ago

stzogas commented 8 months ago

Hi to all! I want to achieve continuous movement with on the fly changes of velocity. Thorlabs told me that is not possible via their softwrae kinesis but only via serial commands to program the controller/motor. I managed to write a python script that achieves on the fly velocity changes but time dependent. I want the changes to occur on the fly when the stage reaches each point i have given . Now the on the fly changes are achieved after a specific period of time. Any reccomenadation for how to modify the code to have on the fly changes of velocity when the stage reaches at each point without stopping?Below is the time dependent code.... `import serial import time from binascii import unhexlify

Basic Python APT/Kinesis Command Protocol Example using KDC101 and MTS50-Z8

Tested in Python 3.8.10

Command Protol PDF can be found https://www.thorlabs.com/Software/Motion%20Control/APT_Communications_Protocol.pdf

Pyserial is a not a native module installed within python and may need to be installed if not already

Port Settings

baud_rate = 115200 data_bits = 8 stop_bits = 1 Parity = serial.PARITY_NONE

Controller's Port and Channel

COM_Port = 'COM3' #Change to preferred

Channel = "01" #Channel is always 1 for a K Cube/T Cube ChanIdent = "0100" #Channel Ident if not in Header Destination = "50" #Destination; 50 for T Cube/K Cube, USB controllers DestinationI = "D0" #Logic Or Destination; D0 for T Cube/K Cube, USB controllers Source = "01" #Source Device_Unit_SF = 34304.96 #pg 34 of protocal PDF (as of Issue 23) Device_Unit_Vel = 772981.3692 Device_Unit_Acc = 263.8443072

Create Serial Object

KDC101 = serial.Serial(port = COM_Port, baudrate = baud_rate, bytesize=data_bits, parity=Parity, stopbits=stop_bits,timeout=0.1)

Get HW info; MGMSG_HW_REQ_INFO; may be require by a K Cube to allow confirmation Rx messages

REQ_INFO = "0500" #Message ID KDC101.write(unhexlify(REQ_INFO + "00" + "00" + Destination + Source)) KDC101.flushInput() KDC101.flushOutput()

Enable Stage; MGMSG_MOD_SET_CHANENABLESTATE

Enable = "1002" State = "01" KDC101.write(unhexlify(Enable + Channel + State + Destination + Source)) print('Stage Enabled') time.sleep(2)

Home Stage; MGMSG_MOT_MOVE_HOME

Home = "4304" print("Homing") KDC101.write(unhexlify(Home + Channel + "00" + Destination + Source))

Confirm stage homed before advancing; MGMSG_MOT_MOVE_HOMED

Rx = '' Homed = unhexlify("4404") while Rx != Homed: Rx = KDC101.read(2) print('Stage Homed') KDC101.flushInput() KDC101.flushOutput()

print("Move")

Set Velocity; MGMSG_MOT_SET_VELPARAMS

Velocity = "1304" MinVelocity = 0 #mm/s Acceleration = 1 #mm/s² MaxVelocity = 0.1 #mm/s

MinVelocityDU = round(Device_Unit_Vel MinVelocity) AccelerationDU = round(Device_Unit_Acc Acceleration) MaxVelocityDU = round(Device_Unit_Vel * MaxVelocity)

KDC101.write(unhexlify(Velocity + "0E00" + DestinationI + Source + ChanIdent) + MinVelocityDU.to_bytes(4, byteorder="little") + AccelerationDU.to_bytes(4, byteorder="little") + MaxVelocityDU.to_bytes(4, byteorder="little"))

AbsDistance = 12 #mm AbsDistanceDU = round(Device_Unit_SF * AbsDistance)

Move Stage; MGMSG_MOT_MOVE_ABSOLUTE

Move = "5304" KDC101.write(unhexlify(Move + "0600" + DestinationI + Source + ChanIdent) + AbsDistanceDU.to_bytes(4, byteorder="little"))

time.sleep(10)

Set Velocity; MGMSG_MOT_SET_VELPARAMS

Velocity = "1304" MinVelocity = 0 #mm/s Acceleration = 1 #mm/s² MaxVelocity = 2 #mm/s

MinVelocityDU = round(Device_Unit_Vel MinVelocity) AccelerationDU = round(Device_Unit_Acc Acceleration) MaxVelocityDU = round(Device_Unit_Vel * MaxVelocity)

KDC101.write(unhexlify(Velocity + "0E00" + DestinationI + Source + ChanIdent) + MinVelocityDU.to_bytes(4, byteorder="little") + AccelerationDU.to_bytes(4, byteorder="little") + MaxVelocityDU.to_bytes(4, byteorder="little"))

AbsDistance = 12 #mm AbsDistanceDU = round(Device_Unit_SF * AbsDistance)

Move Stage; MGMSG_MOT_MOVE_ABSOLUTE

Move = "5304" KDC101.write(unhexlify(Move + "0600" + DestinationI + Source + ChanIdent) + AbsDistanceDU.to_bytes(4, byteorder="little"))

Confirm stage moved before advancing; MGMSG_MOT_MOVE_COMPLETED

Rx = '' Completed = unhexlify("6404") while Rx != Completed: Rx = KDC101.read(2) print('Stage Moved') KDC101.flushInput() KDC101.flushOutput()

Get Position; MGMSG_MOT_REQ_USTATUSUPDATE

Status = "9004" KDC101.write(unhexlify(Status + Channel + "00" + Destination + Source))

Rx = KDC101.read(20)

Position = Rx[8:12]

PositionDU = int.from_bytes(Position, "little") print("Position:", PositionDU, "Device Units" ) PositionRU = PositionDU / 34304 print("Position:", PositionRU, "mm")

Disable Stage; MGMSG_MOD_SET_CHANENABLESTATE

Enable = "1002" State = "02" KDC101.write(unhexlify(Enable + Channel + State + Destination + Source))

print('Stage Disabled') time.sleep(0.1)

KDC101.close() del KDC101 `

AlexShkarin commented 7 months ago

Hello!

As far as I can tell, KDC101 has not built-in capabilities for that. Therefore, your best bet is to continuously check the position in the loop and changing the velocity as soon as you hit the desired position. This approach usually has about 100ms precision (i.e., the velocity will be changed within ~100ms from the position being reached); if you need a better precision, then you might ultimately have to use a different controller.