I’m in a situation where PLR makes the most sense of all available options as we integrate Hamiltons with some custom hardware. I’ve done some hello world level tests and it seems to be working (very well done Rick and everyone else who has contributed). There’s a last hurdle in that we need the autoload to pull carriers part of the way out. Hamilton sent a library with that functionality for VENUS, so I’m looking to make some equivalent functions in PLR. Before I start throwing firmware commands around, a few questions
Anything I should be scared of as far as doing irrecoverable damage?
In the FW docs I see tables like below. Am I right in reading that if I want to move the X drive to track 1 with and override max speed with 3000 and max acceleration I would want the assembled command to look like XPxp1xv3000xr3? (I don’t expect to need to deviate from the defaults, just making sure I have the syntax right)
I’m looking at the hsl library from Hamilton and seeing some GUID-looking functions with GUID looking parameters. Do I need to think about these if I’m letting PLR assemble commands with auto_id?
docs
<edit the forum won’t let me embed images yet but the table has columsn for command XP, parameters xp##, xv###, xr#, and some naked or zero padded integers as values for the params)
@CamilloMoschner We need to present tubes to a fixed location that isn’t accessible by the channels. How close is this to what you’re doing? If you have it already and don’t mind sharing I wouldn’t mind saving some time, otherwise I’ll plan on contributing what I come up with when it’s functional (and maybe even clean). I haven’t gotten in to the labware resources in the library but expecting that I will be able to get the spacing of sites from there and use that to calculate how far to pull the carrier out for each site.
I believe I have been the only person so far who has been integrated the STAR autoload module, and would love to work together with you on improving it!
I have updated it quite a bit a couple of weeks ago:
No. As long as you don’t use “set” commands to modify the STAR’s memory you can do basically anything - the embedded systems engineers who built this machine have done an incredible job at securing it from self-harm via absurd input parameters. The only thing to keep an eye out and do carefully is physical stuff: e.g. don’t move the carrier out onto the autoload belt and then tell the autoload sled to move through the carrier
implemented in basic form in PLR:main line 7405 - though modifying acceleration is not yet, and would be a great addition:
you can just add the parameters into the send_command as Rick has described above and submit a PR
(Note the extra safety I added into this command which I found alternative solutions lack )
As Rick mentioned: no, that is all done automatically by PLR.
I’m sorry, can you please explain the relationship between channels <> tubes <> autoload
If I understand correctly:
You need to read a (vertical) barcode from a tube carrier (I assume the 24 site one?) and only need to scan a specific tube in a specific site of the tube carrier?
There are 2 ways I could see that being implemented:
The “now” way: pull carrier onto loading tray / or completely out, then load it again and just scan ALL sites → a lot more info than needed but you can just use the one site index you need and disregard the remaining info.
The “let’s build it / takes time” way: there is a low-level command to move a carrier out based on the increments of the autoload wheel … we do know the mm/increment and can use this to move the carrier to a pretty precise location; I’ve meant to build this at some point but it has been low in my priority list (there are some pretty neat “other” applications this opens up ). With that in place you could achieve the movement to the specified tube, but then you’d still have to figure out how to granularly use the 1D barcode scanner which I currently don’t know.
So far I only know how to use the 1D barcode scanner as part of the loading routine.
We’re not actually using the barcode scanner for this. What’s happening is we are composing a bunch of different reagent mixtures with a gizmo off deck and want to get those transferred to some plates on deck. Liquid flows from gizmo → tubes on 24-tube carrier → final destination plate. Formulatrix’s Tempest + an arm would get us in the right neighborhood, but we’re DIYing for a few reasons not least of which is money.
Seems like it’s route 2 then. It sounds like our interests overlap a bit here so I’ll be really interested in any feedback you have when I’ve got something working.
One of our three does have an iswap - what are you thinking?
I’m sending some basic commands, delighting that the robot moves when I do so, and have found a fun way to cause collisions. NB: an initialized Y drive is not safe to engage with a carrier until you spin it a few degrees
A couple of questions:
Do you have the steps to mm conversion for the autoload? I see some for iswaps in the code already but haven’t found one for the y drive on the autoload
Update: I’m measuring it around 0.0645 mm/step with some lab tape and calipers from a range of 500 - 2250 steps
What would you think of updating the container coordinates whenever the autoload moves a carrier? It could be useful for some of what I’m trying to do, but at one extreme you could end up where you’re unloaded by the definition of what the autoload is doing which kind of clashes with the definition of what is on the deck or not. I think it’s likely harmless, but wonder if I’d be messing with the intent of other parts of the code. I’ve mostly looked at the parts that pertain to exactly what I’m doing so far.
I don’t know the constraints of your “gizmo”, but I assume it cannot move around and therefore has to be placed into a fixed location.
(I just assume here it’s a 12-to-1 rotor valve attached to a flow sensor attached to a peristaltic pump and the necessary tubing for connecting it all together… that costs about 1k EUR and can mix with tuneable accuracy up to 12 different liquids quite quickly )
Sounds like you are intending to position it right in front of your STAR to utilise the autoload’s capability to move tubes in different tube carrier site right underneath it for filling?
But in that case you want to move the tube carrier back onto the STAR deck and then use the standard 1000uL channels to distribute the liquid mixture… which will be slow because only one channel can enter the tubes at a time.
Question: Is it possible to position your gizmo to the left of your STAR and use the iSWAP to move a trough-plate underneath the gizmo for filling specific compartments of the trough-plate?
…then you can use the iSWAP to move the filled trough-plate back onto the deck and all channels can be used to parallelise/accelerate the filling of your final plate?
The number should be 0.06404424 mm/step for the y drive aka “carrier handler wheel” (PLR docs).
That is a really good question: I think that at some point a true to physical reality modelling of the carriers, as you are suggesting, is needed.
But this is a decently sized project: not only do we need to connect load and unload (and all the new in-between commands) with the resource model (which currently is not the case), but during deck model instantiation we’d need to add new parameters to liquid handling decks whether a carrier is instantiated on the deck or on the loading tray.
On top of that, we’d need to think about how we want to deal with this modelling for all the STAR(let)s that do not have an autoload and/or loading tray.
it would still be on the deck I think, just with a different y-position. when assigning carriers to the deck, we use the default y of 63. after that, if the autoload or something else updates this position, everything else will adapt automatically since locations wrt deck (fka “absolute” locations) are always computed lazily. that means if you move it forward by 1mm, by the time you perform an operation like plate pickup, it will know where the plate is at that time. I don’t think we need to model where the carrier is, we just need to update its y location
is that so? I think if we model it simply as updating y locations based on the values passed to the autoload/unload functions, it can actually be quite a short diff. maybe I am missing something
On top of that, we’d need to think about how we want to deal with this modelling for all the STAR(let)s that do not have an autoload and/or loading tray.
in this cases, the method for moving carriers using the autoload will fail before updating a carrier’s y location
all commands in Using the autoload & 1D barcode reader — PyLabRobot documentation would need to be updated, with y-distances that are currently unknown (i.e. What is the relative y deviation in between the “3 zones of the carriers”, deck <> on_autoload_belt <> on_loading_tray?).
lh.deck.assign_child(carrier_x, track=30, zone=”loading_tray”) should be a thing, no?
Because any automated Protocol actually has 2 possible “zones”/y-locations in which a carrier can potentially start in. (but we do not know the “loading_tray” y coordinate… I’d assume it’s something like 63 mm (normal/on_deck flb)- 497 mm(size_y of carrier) - 63 mm (guess: are the stop hooks of the tracks at y=0???) - unknowns
I’m happy to review and support anyone who wants to get into this but it’s not on our priority list atm
Thanks to a weather-related WFH day I have made some progress. There aren’t much in the way of commands for getting the current situation in the docs I have (a 2015 document, maybe someone here has something newer?), so it’s hard to wrap these up nicely without giving future users of these commands the opportunity for some hardware crashes.
In the same vein, for making the coordinates of the carriers reflect physical reality there are potential order of operations issues that make it tricky to make this a really safe operation. If you engage the carrier wheel and then rotate it to zero, and you have to do some rotation after initialization or the teeth won’t bite the carrier’s tracks, the carrier moves. But if you’re using that same command to get the wheel in position prior to raising it for a move, the carrier doesn’t move. Maybe this is an issue that just needs to be given a few cautionary notes in the documentation. In any case I’ll put update_labware_coordinates as an option for the autoload functions that move things around and start a PR once I’ve tested a little more. If anyone has real distances between load, unload, and belt positions do let me know and I’ll plug in some hand measurements if not.
And @CamilloMoschner the iswap idea is a good one, better in some ways. I’m carrying on with the autoload version but will look at your suggestion as a backup or parallel implementation.