{ "cells": [ { "cell_type": "markdown", "id": "678edf8f", "metadata": {}, "source": [ "# Agilent VSpin\n", "\n", "The VSpin centrifuge is controlled by the {class}`~pylabrobot.centrifuge.vspin_backend.VSpinBackend` class." ] }, { "cell_type": "code", "execution_count": null, "id": "e937791a", "metadata": {}, "outputs": [], "source": [ "from pylabrobot.centrifuge import Centrifuge, VSpinBackend\n", "vspin_backend = VSpinBackend() # VSpinBackend(device_id=\"YOUR_FTDI_ID_HERE\")\n", "cf = Centrifuge(name = \"centrifuge\", backend = vspin_backend, size_x= 1, size_y=1, size_z=1)\n", "await cf.setup()" ] }, { "cell_type": "markdown", "id": "e5ee122c", "metadata": {}, "source": [ "Before you can use the \"go to bucket\" commands, you need to calibrate the bucket positions. See [below](#calibrating-bucket-1-position) for instructions." ] }, { "cell_type": "code", "execution_count": null, "id": "9f9365f0", "metadata": {}, "outputs": [], "source": [ "await cf.go_to_bucket1()" ] }, { "cell_type": "code", "execution_count": null, "id": "c8b872e9", "metadata": {}, "outputs": [], "source": [ "await cf.go_to_bucket2()" ] }, { "cell_type": "code", "execution_count": null, "id": "ed867ca2", "metadata": {}, "outputs": [], "source": [ "await cf.spin(\n", " g=800,\n", " duration=60, # seconds\n", " acceleration=1.0, # 0-1\n", " deceleration=1.0, # 0-1\n", ")" ] }, { "cell_type": "markdown", "id": "a3587acc", "metadata": {}, "source": [ "Status commands" ] }, { "cell_type": "code", "execution_count": null, "id": "2d8d3047", "metadata": {}, "outputs": [], "source": [ "await vspin_backend.get_door_locked()" ] }, { "cell_type": "code", "execution_count": null, "id": "57bdc72d", "metadata": {}, "outputs": [], "source": [ "await vspin_backend.get_door_open()" ] }, { "cell_type": "code", "execution_count": null, "id": "d3f66052", "metadata": {}, "outputs": [], "source": [ "await vspin_backend.get_bucket_locked()" ] }, { "cell_type": "markdown", "id": "47c4cfc9", "metadata": {}, "source": [ "## Calibrating bucket 1 position\n", "\n", "You need to calibrate the bucket 1 position for every vspin once. There are two ways to do this:\n", "1. Manually: Move bucket 1 to the correct position using the physical controls on the centrifuge.\n", "2. Programmatically: Use the `go_to_position` command to move bucket 1 to the correct position.\n", "\n", "With bucket 1 in the correct position, save it with `cf.backend.set_bucket_1_position_to_current()`. This will save the calibration for the current centrifuge to disk at `~/.pylabrobot/vspin_bucket_calibrations.json` (based on the usb serial number)." ] }, { "cell_type": "markdown", "id": "8086eab1", "metadata": {}, "source": [ "### Moving using code\n", "\n", "Use `vspin_backend.go_to_position` to move the buckets to the correct position. A full rotation is 8000 ticks, so 4.5 degrees per 100 ticks." ] }, { "cell_type": "code", "execution_count": null, "id": "50fc77a3", "metadata": {}, "outputs": [], "source": [ "await vspin_backend.go_to_position(100)" ] }, { "cell_type": "code", "execution_count": null, "id": "7bb22121", "metadata": {}, "outputs": [], "source": [ "await vspin_backend.set_bucket_1_position_to_current()" ] }, { "cell_type": "markdown", "id": "3cbdc48f", "metadata": {}, "source": [ "### Manually rotating\n", "\n", "You can open the door unlock the bucket and manually rotate the buckets to the desired position.\n", "\n", "```{warning}\n", "High risk / high reward! The vspin has a safety mechanism that will close the door when it detects movement.\n", "This means the door will close when you rotate the buckets manually too fast.\n", "Be careful or it will eat your fingers!\n", "It will save time compared to using code though.\n", "```" ] }, { "cell_type": "code", "execution_count": null, "id": "031329fc", "metadata": {}, "outputs": [], "source": [ "await cf.open_door()\n", "await vspin_backend.unlock_bucket()" ] }, { "cell_type": "markdown", "id": "f0eae259", "metadata": {}, "source": [ "Manually rotate buckets to align bucket 1 with door" ] }, { "cell_type": "code", "execution_count": null, "id": "18a25ed9", "metadata": {}, "outputs": [], "source": [ "await vspin_backend.set_bucket_1_position_to_current()" ] }, { "cell_type": "markdown", "id": "c973648a", "metadata": {}, "source": [ "## Loader\n", "\n", "The VSpin can optionally be used with a loader (called Access2). The loader is optional because you can also use a robotic arm like an iSWAP to move a plate directly into the centrifuge.\n", "\n", "When using the loader, you must specify the FTDI device ids for both devices because both use FTDI and are otherwise indistinguishable. See [below](#2-finding-the-ftdi-id) for how to find the device ids.\n", "\n", "Here's how to use the loader:" ] }, { "cell_type": "code", "execution_count": null, "id": "f3e17e8f", "metadata": {}, "outputs": [], "source": [ "import asyncio\n", "\n", "from pylabrobot.centrifuge import Access2, VSpinBackend\n", "vspin_backend = VSpinBackend(device_id=\"YOUR_VSPIN_FTDI_ID_HERE\")\n", "centrifuge, loader = Access2(name=\"name\", vspin=vspin_backend, device_id=\"YOUR_LOADER_FTDI_ID_HERE\")\n", "\n", "# initialize the centrifuge and loader in parallel\n", "await asyncio.gather(\n", " centrifuge.setup(),\n", " loader.setup()\n", ")\n", "\n", "# go to a bucket and open the door before loading\n", "await centrifuge.go_to_bucket1()\n", "await centrifuge.open_door()\n", "\n", "# assign a plate to the loader before loading. This can also be done implicitly by for example\n", "# lh.move_plate(plate, loader)\n", "from pylabrobot.resources import Cor_96_wellplate_360ul_Fb\n", "plate = Cor_96_wellplate_360ul_Fb(name=\"plate\")\n", "loader.assign_child_resource(plate)\n", "\n", "# load and unload the plate\n", "await loader.load()\n", "await loader.unload()" ] }, { "cell_type": "markdown", "id": "e3de872f", "metadata": {}, "source": [ "## Installation\n", "\n", "The VSpin centrifuge connects to your system via a COM port. Integrating it with `pylabrobot` library requires some setup. Follow this guide to get started.\n", "\n", "### 1. Installing libftdi\n", "\n", "#### macOS\n", "\n", "Install libftdi using [Homebrew](https://brew.sh/):\n", "\n", "```bash\n", "brew install libftdi\n", "```\n", "\n", "#### Linux\n", "\n", "Debian (rpi) / Ubuntu etc:\n", "\n", "```bash\n", "sudo apt-get install libftdi-dev\n", "```\n", "\n", "Other distros have similar packages.\n", "\n", "#### Windows\n", "\n", "**Find Your Python Directory**\n", "\n", "To use the necessary FTDI `.dll` files, you need to locate your Python environment:\n", "\n", "1. Open Python in your terminal:\n", " ```python\n", " python\n", " >>> import sys\n", " >>> sys.executable\n", " ```\n", "2. This will print a path, e.g., `C:\\Python39\\python.exe`.\n", "3. Navigate to the `Scripts` folder in the same directory as `python.exe`.\n", "\n", "**Download FTDI DLLs**\n", "\n", "Download the required `.dll` files from the following link:\n", "[FTDI Development Kit](https://sourceforge.net/projects/picusb/files/libftdi1-1.5_devkit_x86_x64_19July2020.zip/download) (link will start download).\n", "\n", "1. Extract the downloaded zip file.\n", "2. Locate the `bin64` folder.\n", "3. Copy the files named:\n", " - `libftdi1.dll`\n", " - `libusb-1.0.dll`\n", "\n", "**Place DLLs in Python Scripts Folder**\n", "\n", "Paste the copied `.dll` files into the `Scripts` folder of your Python environment. This enables Python to communicate with FTDI devices.\n", "\n", "**Configuring the Driver with Zadig**\n", "\n", "Use Zadig to replace the default driver of the VSpin device with `libusbk`:\n", "\n", "1. **Identify the VSpin Device**\n", "\n", " - Open Zadig.\n", " - To confirm the VSpin device, disconnect the RS232 port from the centrifuge while monitoring the Zadig device list.\n", " - The device that disappears is your VSpin, likely titled \"USB Serial Converter.\"\n", "\n", "2. **Replace the Driver**\n", " - Select the identified VSpin device in Zadig.\n", " - Replace its driver with `libusbk`.\n", " - Optionally, rename the device to \"VSpin\" for easy identification.\n", "\n", "> **Note:** If you need to revert to the original driver for tools like the Agilent Centrifuge Config Tool, go to **Device Manager** and uninstall the `libusbk` driver. The default driver will reinstall automatically.\n", "\n", "### 2. Finding the FTDI ID\n", "\n", "To interact with the centrifuge programmatically, you need its FTDI device ID. Use the following steps to find it:\n", "\n", "1. Open a terminal and run:\n", " ```bash\n", " python -m pylibftdi.examples.list_devices\n", " ```\n", "2. This will output something like:\n", " ```\n", " FTDI:USB Serial Converter:FTE0RJ5T\n", " ```\n", "3. Copy the ID (`FTE0RJ5T` or your equivalent).\n", "\n", "You’re now ready to use your VSpin centrifuge with `pylabrobot`!" ] } ], "metadata": { "kernelspec": { "display_name": "env", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.9.23" } }, "nbformat": 4, "nbformat_minor": 5 }