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

Absolute movement causes the stage to move continously in wrong direction #83

Open 01baftb opened 2 months ago

01baftb commented 2 months ago

I am facing an issue with pyLabLib giving unexpected behavior when trying to control a Thorlabs DRV014 50mm stepper motor stage connected to BSC203 controller. After homing, I move the stage to desired absolute positions. For example, from 0mm to 3mm, then 3mm to 7mm, then 7mm to 3mm. On the 3rd absolute movement (i.e. 7mm to 3mm), the stage starts moving in the forward direction without stopping instead of going backwards and stopping at 3mm. Below is my code to replicate the issue.

I also notice the Enable light is not ON, I have to physically press the ON button to enable the channel. However, the pyLabLib is able to properly connect and interact with the stage even when the enable is OFF. If I launch the Kinesis software, it automatically enables the channel to ON.

Python 3.11.9 pylablib 1.4.2

>>> from pylablib.devices import Thorlabs
>>> my_serial = "70877XXX" # Real serial number is not shown 
>>> stage = Thorlabs.KinesisMotor(my_serial, is_rack_system=True, scale=409600, default_channel=1)
>>> stage.get_device_info()
TDeviceInfo(serial_no=70000000, model_no='BSC203', fw_ver='2.3.4', hw_type=32, hw_ver=2, mod_state=0, nchannels=3, notes='APT Stepper Motor Controller')
>>> stage.get_full_info(-10)
{'velocity_parameters': TVelocityParams(min_velocity=0.0, acceleration=19.99985352990614, max_velocity=20.002642021804558), 'jog_parameters': TJogParams(mode='step', step_size=0.5, min_velocity=4.548074236214605e-06, acceleration=0.4999907901918369, max_velocity=1.000132121556562, stop_mode='profiled'), 'homing_parameters': THomeParams(home_direction='reverse', limit_switch='reverse', velocity=1.000132121556562, offset_distance=0.1), 'gen_move_parameters': TGenMoveParams(backlash_distance=0.15645751953125), 'limit_switch_parameters': TLimitSwitchParams(hw_kind_cw='break', hw_kind_ccw='break', hw_swapped=False, sw_position_cw=0.0, sw_position_ccw=0.0, sw_kind='ignore'), 'position': 0.0, 'status': ['tracking', 'digio1', 'enabled'], 'cls': 'KinesisMotor', 'conn': {'port': '70877XXX', 'baudrate': 115200, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': 0, 'rtscts': True}, 'device_info': TDeviceInfo(serial_no=70000000, model_no='BSC203', fw_ver='2.3.4', hw_type=32, hw_ver=2, mod_state=0, nchannels=3, notes='APT Stepper Motor Controller'), 'channel': [1], 'scale_units': 'user_step', 'scale': (409600, 21987328.0, 4506.08300032), 'stage': None}
>>> stage.home()
>>> stage.get_position()
0.0 
>>> stage.move_to(3.0)  
>>> stage.get_position()
3.0 
>>> stage.move_to(7.0)       
>>> stage.get_position()
7.0 
>>> stage.move_to(3.0)   
>>> stage.stop()
>>> stage.get_position()
67.78671875
AlexShkarin commented 2 months ago

This indeed looks pretty strange, especially considering the fact that the first move to 3mm has no problems, and the commands sent to the device should be identical in both cases. Can you check that this issue does not arise in the Kinesis software and is specific to pylablib, to exclude hardware problems?

Do you know what condition causes this issue? Does it always arise when moving backwards? Or only past a specific point? Also, it looks like the final position is 67mm, which is past the stage 50mm travel range. Do you know how this happens? Does the motor try to run agains the stop point, even when the limit switch is engaged? Can you check (at least, roughly), that the calibration is correct, e.g., that moving to 25mm position places the stage in the middle of its range?

Regarding the ON/OFF light: you can try using the enable_channel method and see if it has the desired effect.

Sincerely,

Alexey.

01baftb commented 2 months ago

Regarding the ON/OFF light: you can try using the enable_channel method and see if it has the desired effect.

The function enable_channel() is not defined in pylablib 1.4.2, but instead _enable_channel() is defined. Using stage._enable_channel() has no effect and it does not resolve the issue. Calling _enable_channel() does not toggle the enable light on the controller.

Can you check that this issue does not arise in the Kinesis software and is specific to pylablib, to exclude hardware problems?

I have confirmed the issue does not occur when I control the stage using the Kinesis software. Also, the issue does not occur if I first let Kinesis software connect to the stage then I disconnect. Below are steps to replicate.

1) Power OFF the controller 2) Power ON the controller 3) Launch Kinesis software and let it connect to stage. Notice the enable LED also turns on automatically without having to physically press the button. 4) In Kinesis, disconnect the stage so we can open connection with Python 5) Execute the code in Python as posted in the original post

If I connect to stage with Kinesis software before connecting via Python, I notice the output of the stage.get_full_info(-10) is different. Below is the output of stage.get_full_info(-10) if I connect to Kinesis before connecting via Python. If you diff to see the difference, you will see the values of min_velocity, TGenMoveParams(backlash_distance, sw_position_cw, sw_position_ccw. If I manually set the values of these parameters in Python to be same as how it is set when connected via Kinesis, it still does not resolve the issue. Also note, previously in the Kinesis software, I set the stage to store (i.e. persist) the default settings of the HS DRV014 50mm stage.

>>> stage.get_full_info(-10)
{'velocity_parameters': TVelocityParams(min_velocity=0.0, acceleration=19.99985352990614, max_velocity=20.002642021804558), 'jog_parameters': TJogParams(mode='step', step_size=0.5, min_velocity=0.0, acceleration=0.4999907901918369, max_velocity=1.000132121556562, stop_mode='profiled'), 'homing_parameters': THomeParams(home_direction='reverse', limit_switch='reverse', velocity=1.000132121556562, offset_distance=0.1), 'gen_move_parameters': TGenMoveParams(backlash_distance=0.01), 'limit_switch_parameters': TLimitSwitchParams(hw_kind_cw='break', hw_kind_ccw='break', hw_swapped=False, sw_position_cw=3.0, sw_position_ccw=1.0, sw_kind='ignore'), 'position': 0.0, 'status': ['tracking', 'digio1', 'enabled'], 'cls': 'KinesisMotor', 'conn': {'port': '70877XXX', 'baudrate': 115200, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': 0, 'rtscts': True}, 'device_info': TDeviceInfo(serial_no=70000000, model_no='BSC203', fw_ver='2.3.4', hw_type=32, hw_ver=2, mod_state=0, nchannels=3, notes='APT Stepper Motor Controller'), 'channel': [1], 'scale_units': 'user_step', 'scale': (409600, 21987328.0, 4506.08300032), 'stage': None}

Do you know what condition causes this issue? Does it always arise when moving backwards? Or only past a specific point? Also, it looks like the final position is 67mm, which is past the stage 50mm travel range. Do you know how this happens? Does the motor try to run agains the stop point, even when the limit switch is engaged? Can you check (at least, roughly), that the calibration is correct, e.g., that moving to 25mm position places the stage in the middle of its range?

Right now it seems the issue arises whenever I try to move backwards. The reason the final position in my example is at 67mm is because the stage continuously moves forwards without stopping. It goes beyond the limit and keeps trying to move forward until I manually stop it. Calibration is correct, I confirmed moving to 25mm puts the stage in the middle.

Also I have confirmed this issue occurs on both channels of the BSC203 controller. In addition, I have another DRV014 stage and the issue occurs on that also.

Thank you for your help and creating this library. I hope we can determine the source of this issue.

ethan-jtaylor commented 2 months ago

Seconding this issue on the BSC203 controller with DRV208 stepper motors.

AlexShkarin commented 2 months ago

Thank you for the detailed description!

Unfortunately, I do not have access to BSC20x controllers, so I can only deduce something based on the Kinesis simulator. It looks like there could be a couple of things going on:

Sincerely,

Alexey.

X-Guo-TUD commented 2 weeks ago

I am facing an issue with pyLabLib giving unexpected behavior when trying to control a Thorlabs DRV014 50mm stepper motor stage connected to BSC203 controller. After homing, I move the stage to desired absolute positions. For example, from 0mm to 3mm, then 3mm to 7mm, then 7mm to 3mm. On the 3rd absolute movement (i.e. 7mm to 3mm), the stage starts moving in the forward direction without stopping instead of going backwards and stopping at 3mm. Below is my code to replicate the issue.

I also notice the Enable light is not ON, I have to physically press the ON button to enable the channel. However, the pyLabLib is able to properly connect and interact with the stage even when the enable is OFF. If I launch the Kinesis software, it automatically enables the channel to ON.

Python 3.11.9 pylablib 1.4.2

>>> from pylablib.devices import Thorlabs
>>> my_serial = "70877XXX" # Real serial number is not shown 
>>> stage = Thorlabs.KinesisMotor(my_serial, is_rack_system=True, scale=409600, default_channel=1)
>>> stage.get_device_info()
TDeviceInfo(serial_no=70000000, model_no='BSC203', fw_ver='2.3.4', hw_type=32, hw_ver=2, mod_state=0, nchannels=3, notes='APT Stepper Motor Controller')
>>> stage.get_full_info(-10)
{'velocity_parameters': TVelocityParams(min_velocity=0.0, acceleration=19.99985352990614, max_velocity=20.002642021804558), 'jog_parameters': TJogParams(mode='step', step_size=0.5, min_velocity=4.548074236214605e-06, acceleration=0.4999907901918369, max_velocity=1.000132121556562, stop_mode='profiled'), 'homing_parameters': THomeParams(home_direction='reverse', limit_switch='reverse', velocity=1.000132121556562, offset_distance=0.1), 'gen_move_parameters': TGenMoveParams(backlash_distance=0.15645751953125), 'limit_switch_parameters': TLimitSwitchParams(hw_kind_cw='break', hw_kind_ccw='break', hw_swapped=False, sw_position_cw=0.0, sw_position_ccw=0.0, sw_kind='ignore'), 'position': 0.0, 'status': ['tracking', 'digio1', 'enabled'], 'cls': 'KinesisMotor', 'conn': {'port': '70877XXX', 'baudrate': 115200, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': 0, 'rtscts': True}, 'device_info': TDeviceInfo(serial_no=70000000, model_no='BSC203', fw_ver='2.3.4', hw_type=32, hw_ver=2, mod_state=0, nchannels=3, notes='APT Stepper Motor Controller'), 'channel': [1], 'scale_units': 'user_step', 'scale': (409600, 21987328.0, 4506.08300032), 'stage': None}
>>> stage.home()
>>> stage.get_position()
0.0 
>>> stage.move_to(3.0)  
>>> stage.get_position()
3.0 
>>> stage.move_to(7.0)       
>>> stage.get_position()
7.0 
>>> stage.move_to(3.0)   
>>> stage.stop()
>>> stage.get_position()
67.78671875

I have exactly the same setup and the same version of python. When I copied this code in IDLE 3.11, the IDLE will be stuck at the line of stage.home(), Does anyone have any idea about my issue? Is my installation of pylablib wrong? thorlab-stage-issue