Open FilipDominec opened 3 years ago
Furthermore, it would be great to somehow relate this project with e.g. https://github.com/qpit/thorlabs_apt/: I can see the latter exposes much more user-friendly commands, and uses APT.dll on Windows. So it seems to be a frontend for this library -- could thorpy substitute APT.dll and become a backend for thorlabs_apt for Linux?
Then there is https://github.com/freespace/pyAPT, apparently with rather friendly API, using a FTDI's driver to get along without APT.dll. Another project communicates with one Thorlabs instrument using the visa library https://github.com/clade/ThorlabsPM100. And it is unclear to me how yet another project, https://github.com/ekarademir/thorlabs-kinesis, interfaces the hardware.
It is quite hard to get acquainted with the Thorlabs-related libraries here on github! Most potential users are not real programmers, just scientists and engineers needing to get their instrumentation up and running...
There should be one-- and preferably only one --obvious way to do it.
Hey Filip What Python version and Linux do you use? I don't even get the test.py working :( I tried a BSC101 and BSC203. Btw, I think the thorlabs-kinesis project also wraps the .dll and thus is only useable on windows. I agree it would be nice to channel the efforts here and have only one project instead of 5 in particular since everyone literally has to do the same thing talking to the controller. Thanks Ben
Hi Ben and Filip, At the time I managed to make it work with a BSC201 with Raspbian (running on a raspberry Pi as you may have guessed), it is the only project I found that can work on linux so I stuck to it. I had several communication problems that I eventually solved (check my topic in the Solved issues category #16). Be aware that this code is not ready to work with stepper motors, as several commands are not implemented or only apply to classic motors. You might be interested in the fork of the project I made to suit my needs, where I added what was lacking for BSC201 using the Thorlabs communication protocol pdf.
Sorry for being slightly off-topic here, but this concerns the very basic question of how the future of this project could look like.
Bad news is that there is massive redundancy of lab control projects here on github. Aside of at least 5 projects focused on Thorlabs, there are unbelievable 35+ projects [https://github.com/LabPy/labpy-discussion/issues/23] attempting to support laboratory instrumentation of multiple manufacturers, often including Thorlabs. Much of capabilities of these projects overlap, but none of them is a clear superset of others.
Good news is that this has been noticed in last two years and part of the developers discuss collaborative unification of their instrumentation drivers into one package [https://github.com/python-data-acquisition/meta/issues/14].
So currently I am considering to get inspired by the code here and port the functionality into a more universal package. But I greatly appreciate the work spent on thorpy
.
Don't mean to butt in, just want to mention https://pypi.org/project/thorlabs-apt-protocol/, which is what I use.
In my opinion it is preferable to always use the serial interface. This works out-of-the-box on Linux, and on Windows you can enable it in the device manager:
Within Device Manager, right click on the APT device (under USB devices), and go to Properties. On the Advanced tab, check the box that says Load VCP (VCP stands for Virtual COM Port). Unplug and replug the USB cable to make it load the COM Port.
It then becomes really simple to make cross-platform Thorlabs APT interfaces. In comparison the dll is not portable and makes installation a bigger hassle.
Just my humble thoughts---I'm interested in the broader fragmentation problem but I don't have any concrete answers right now.
Thank you, I can see thorlabs-apt-protocol
is a part of yaq
. I will try to find time to try it out.
really all we'd need is some sort of easy-to-use moveAbsolute() and moveRelative() function, eg:
def moveAbsolute(motorObj,newPos):
steps_per_mm = 34527.5
motorObj._port.send_message(MGMSG_MOT_MOVE_ABSOLUTE_long(motorObj._chan_ident, int(newPos*steps_per_mm)))
(literally just copying @FilipDominec 's)
and either
def moveRelative(motorObj,moveBy):
steps_per_mm = 34527.5
motorObj._port.send_message(MGMSG_MOT_MOVE_RELATIVE_long(motorObj._chan_ident, int(moveBy*steps_per_mm)))
or
def moveRelative2(motorObj,moveBy):
curLoc=motorObj.position
newPos=curLoc+moveBy
moveAbsolute(motorObj,newPos)
(i have no idea what, functionally, is different between calling move_relative_long vs just polling the current location and calling move_absolute_long).
chuck these wherever you like, or change motorObj to self and chuck it into the GenericStage class (honestly, i thought i'd be able to call motorObj.position(newPosition) and get my stage to move. nope! oh well. no big deal. but there should be a method in there for absolute or relative motion imo).
(i may go ahead and do this myself with a commit. after a bit more testing of course...)
The following two additions to the genericStage class:
def setPosition(self, new_value):
. . assert type(new_value) in (float, int)
. . absolute_distance = int(new_value * self._EncCnt)
. . self._port.send_message(MGMSG_MOT_MOVE_ABSOLUTE_long(chan_ident = self._chan_ident, absolute_distance = absolute_distance))
and
def changePosition(self, moveBy):
. . assert type(moveBy) in (float, int)
. . relative_distance = int(moveBy * self._EncCnt)
. . self._port.send_message(MGMSG_MOT_MOVE_RELATIVE_long(chan_ident = self._chan_ident, relative_distance = relative_distance))
let you just call set / change with your stage object. eg, my rudimentary "move x and y to, or by" script might look like this:
from thorpy.comm.discovery import discover_stages
#from thorpy.message.motorcontrol import *
stages=list(discover_stages())
xmotor=stages[0] ; ymotor=stages[1]
while True:
. . control=input("do what:") #"x=5" to set x to 5, "y-=4" to decrement y by 4, etc
. . if "g" in control:
. . . . xmotor.print_state()
. . . . ymotor.print_state()
. . if "q" in control:
. . . . break
. . # pick which motor
. . if "x" in control:
. . . . mot=xmotor
. . elif "y" in control:
. . . . mot=ymotor
. . else:
. . . . continue
. . # parse out distance, and absolute vs relative
. . dist=float(control.split("=")[1])
. . if "-=" in control:
. . . . dist=dist*-1
. . if "+=" in control or "-=" in control:
. . . . mot.changePosition(dist)
. . else:
. . . . mot.setPosition(dist)
I still find it a little peculiar that the second "def position" is literally exactly what we need to call in order to set the position. we just....can't seem to call it. (all i did was copy and paste it here, and gave it a new name).
While I was able to get the linear stage moving (through trial and error) using
it would be much better if the project supplied some short practical examples of typical use.
(E.g. I did not find out how to make the commands to block further program flow until the movement is finished. I am
using time.sleep(delay)
hoping that the controller will finish within the delay.) The official Thorlabs guides were useless for me.