{ "cells": [ { "cell_type": "markdown", "id": "gg-title", "metadata": {}, "source": "# Cole-Parmer GenoGrinder (fka SPEX GenoGrinder)\n\nThe GenoGrinder is a high-throughput plate shaker and homogenizer. It clamps a microplate (or a stack of plates, or a set of vials in a plate-format holder) between two platens and shakes it vertically for a fixed time at a fixed speed, grinding or mixing the contents of every well at once.\n\nProduct page: [Cole-Parmer SamplePrep HG-600-230 Geno/Grinder 2010](https://www.coleparmer.com/i/cole-parmer-sampleprep-hg-600-230-geno-grinder-2010-tissue-homogenizer-and-cell-lyser-230-vac-50-hz/0457684)\n\n| Property | Value |\n|---|---|\n| Communication | Serial, ASCII line protocol |\n| Serial settings | 9600 baud, 8 data bits, no parity, 1 stop bit |\n| Line terminator | carriage return (`\\r`) |\n| Duration range | 1--999 s |\n| Speed range | 1--9999 rpm |\n| Clamp | motorized (open/close) or fixed, depending on model |\n\n```{warning}\nThis driver has NOT been tested against hardware in PyLabRobot. `setup()` logs a\nwarning to that effect. If you verify it on your machine, please open a PR to\nremove the warning.\n```" }, { "cell_type": "markdown", "id": "gg-physical", "metadata": {}, "source": [ "## Physical setup\n", "\n", "Connect the GenoGrinder's serial port to your computer, typically through a USB-to-serial adapter, and note the port name (`/dev/ttyUSB*` on Linux, `/dev/tty.usbserial-*` on macOS, `COM*` on Windows).\n", "\n", "Make sure the instrument's serial parameters match the driver defaults (9600 baud, 8 data bits, no parity, 1 stop bit), and that the safety lid is closed -- the machine will not run with it open." ] }, { "cell_type": "markdown", "id": "gg-connect-md", "metadata": {}, "source": "## Connect\n\n`setup()` opens the serial port and runs the instrument's power-on routine, which homes the mechanism and readies the clamp. Its reply doubles as a communication check, so a successful `setup()` means the machine is talking and ready to run.\n\nSome GenoGrinder models have a fixed clamp that you tighten by hand instead of a motorized one. On those, pass `use_clamp_commands=False`: `open_clamp()` and `close_clamp()` then do nothing, so the same protocol code runs on either machine." }, { "cell_type": "code", "execution_count": null, "id": "gg-connect", "metadata": {}, "outputs": [], "source": [ "from pylabrobot.cole_parmer import GenoGrinder\n", "\n", "grinder = GenoGrinder(port=\"/dev/ttyUSB0\") # replace with your port\n", "await grinder.setup()" ] }, { "cell_type": "markdown", "id": "gg-clampstate-md", "metadata": {}, "source": "## Check the clamp\n\n`request_clamp_state()` reports whether the clamp is `\"open\"`, `\"closed\"`, or `\"unknown\"`." }, { "cell_type": "code", "execution_count": null, "id": "gg-clampstate", "metadata": {}, "outputs": [], "source": "print(\"Clamp:\", await grinder.request_clamp_state())" }, { "cell_type": "markdown", "id": "gg-open-md", "metadata": {}, "source": [ "## Open the clamp\n", "\n", "`open_clamp()` reads the current position and only moves if the clamp is not already open, so it is safe to call repeatedly." ] }, { "cell_type": "code", "execution_count": null, "id": "gg-open", "metadata": {}, "outputs": [], "source": [ "await grinder.open_clamp()" ] }, { "cell_type": "markdown", "id": "gg-load-md", "metadata": {}, "source": [ "## Load a plate\n", "\n", "Place your plate (or plate stack) in the clamp now, centered on the platen, and close the safety lid." ] }, { "cell_type": "markdown", "id": "gg-close-md", "metadata": {}, "source": [ "## Close the clamp\n", "\n", "`close_clamp()` clamps the plate down. Like `open_clamp()`, it checks the current position first." ] }, { "cell_type": "code", "execution_count": null, "id": "gg-close", "metadata": {}, "outputs": [], "source": [ "await grinder.close_clamp()" ] }, { "cell_type": "markdown", "id": "gg-shake-md", "metadata": {}, "source": [ "## Shake\n", "\n", "`shake()` uploads the run parameters, starts the run, then polls the instrument until it reports the run is complete -- so the call returns when the plate has actually finished shaking.\n", "\n", "`duration` is in seconds (1--999) and `speed` in rpm (1--9999). Start gentle and work up: hard grinding at high rpm can crack plates and unseat seals." ] }, { "cell_type": "code", "execution_count": null, "id": "gg-shake", "metadata": {}, "outputs": [], "source": [ "await grinder.shake(duration=30, speed=1500)" ] }, { "cell_type": "markdown", "id": "gg-status-md", "metadata": {}, "source": "## Read the status\n\n`request_status()` returns the instrument's raw status line -- `Standby` when idle, or one of the transient run states (`Running Sample`, `Locking`, `Mixing`, `Unlocking`, `Run Complete`) during a run. Useful when driving the machine from another task while a run is going." }, { "cell_type": "code", "execution_count": null, "id": "gg-status", "metadata": {}, "outputs": [], "source": "print(\"Status:\", await grinder.request_status())" }, { "cell_type": "markdown", "id": "gg-stopshaking-md", "metadata": {}, "source": [ "## Abort a run\n", "\n", "`stop_shaking()` stops a run in progress. Because `shake()` blocks until the run finishes, call this from a separate task (or after interrupting the cell) when you need to cut a run short." ] }, { "cell_type": "code", "execution_count": null, "id": "gg-stopshaking", "metadata": {}, "outputs": [], "source": [ "await grinder.stop_shaking()" ] }, { "cell_type": "markdown", "id": "gg-home-md", "metadata": {}, "source": [ "## Home the clamp\n", "\n", "`home_clamp()` returns the clamp to its reference position. Use it to recover a known state after an aborted run." ] }, { "cell_type": "code", "execution_count": null, "id": "gg-home", "metadata": {}, "outputs": [], "source": [ "await grinder.home_clamp()" ] }, { "cell_type": "markdown", "id": "gg-unload-md", "metadata": {}, "source": [ "## Unload the plate\n", "\n", "Open the clamp again and take the plate out." ] }, { "cell_type": "code", "execution_count": null, "id": "gg-unload", "metadata": {}, "outputs": [], "source": [ "await grinder.open_clamp()" ] }, { "cell_type": "markdown", "id": "gg-teardown-md", "metadata": {}, "source": [ "## Teardown\n", "\n", "`stop()` halts any run still in progress and closes the serial connection." ] }, { "cell_type": "code", "execution_count": null, "id": "gg-teardown", "metadata": {}, "outputs": [], "source": [ "await grinder.stop()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 5 }