AlexShkarin/pyLabLib

Thorlabs Kdc 101 controller and mts50-z8 stage continuous movement

Opened this issue · 1 comments

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
`

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.