{ "cells": [ { "cell_type": "markdown", "id": "bigbear-intro", "source": "# BigBear Orbital Shaker\n\nThe BigBear orbital shaker is a plate shaker with a serial (RS-232 / ASCII) interface. A single serial line can drive up to 16 shaker positions -- called **nests** -- wired together in a *daisy chain*, each addressed independently.\n\n| Property | Value |\n|---|---|\n| Communication | Serial, ASCII line protocol |\n| Serial settings | 9600 baud, 8 data bits, no parity, 1 stop bit, no handshake |\n| Line terminator | carriage return (`\\r`) |\n| Speed range | 60--3570 rpm |\n| Acceleration | 1--10 (device scale) |\n| Nests per chain | 1--16 |\n\n```{warning}\nThis driver has NOT been tested against hardware in PyLabRobot. The protocol,\nline terminator, and reply formats are reconstructed from the vendor software.\nIf you verify it on a shaker, please open a PR to remove the not-tested warning.\n```", "metadata": {} }, { "cell_type": "markdown", "id": "bigbear-daisy-md", "source": "## Daisy chaining\n\nMultiple shaker units share one serial connection: the host talks to the first unit, which is wired to the second, and so on down the chain. Each unit is a **nest** with a 1-based address.\n\nEvery command is addressed with an `@` prefix, where `` is the nest number written in **hexadecimal** -- so nest 10 is `@A` and nest 16 is `@10`. A command reaches only the nest it names; the others ignore it. This lets one port run up to 16 shakers with independent speed, direction, and start/stop.\n\nAt `setup()` the driver:\n\n1. sends `U` to put the chain into daisy-chain (addressing) mode,\n2. sends `~` to ask how many units are present, and\n3. checks that the reported count matches the `num_shakers` you passed.\n\nIf the counts disagree (a unit is off, unplugged, or `num_shakers` is wrong) setup raises a `BigBearError`. Set `num_shakers` to the number of physical units on the chain.", "metadata": {} }, { "cell_type": "markdown", "id": "bigbear-setup-md", "source": "## Physical setup\n\nConnect the shaker's serial port to your computer, typically through a USB-to-serial adapter. Chain any additional units in series and give the whole chain a single port.\n\nMake sure the shaker's serial parameters match the driver defaults (9600 baud, 8 data bits, no parity, 1 stop bit, no handshake).", "metadata": {} }, { "cell_type": "markdown", "id": "bigbear-connect-md", "source": "## Connect\n\n`setup()` opens the serial port, enters daisy-chain mode, and verifies the shaker count. It also logs the not-tested warning. Pass `num_shakers` to match your chain.", "metadata": {} }, { "cell_type": "code", "id": "bigbear-connect-code", "source": "from pylabrobot.big_bear import BigBearOrbitalShaker\n\nshaker = BigBearOrbitalShaker(port=\"/dev/ttyUSB0\", num_shakers=1) # replace with your port\nawait shaker.setup()", "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "id": "bigbear-shake-md", "source": "## Start shaking\n\n`start_shaking()` sets the acceleration, speed, and direction for a nest and starts it. Shaking continues until you stop it. `device_id` selects which nest (default 1).", "metadata": {} }, { "cell_type": "code", "id": "bigbear-shake-code", "source": "await shaker.start_shaking(\n rpm=750,\n acceleration=3,\n sequence=\"CW\",\n device_id=1,\n)", "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "id": "bigbear-stop-md", "source": "## Stop shaking\n\nStop a single nest with `stop_shaking()`, or every nest on the chain with `stop_all()`.", "metadata": {} }, { "cell_type": "code", "id": "bigbear-stop-code", "source": "await shaker.stop_shaking(device_id=1)\n# or, for the whole chain:\n# await shaker.stop_all()", "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "id": "bigbear-multi-md", "source": "## Driving multiple nests\n\nWith a multi-unit chain, address each nest by its `device_id`. Each runs independently.", "metadata": {} }, { "cell_type": "code", "id": "bigbear-multi-code", "source": "# Example for a 3-nest chain (create with num_shakers=3)\n# await shaker.start_shaking(rpm=500, device_id=1)\n# await shaker.start_shaking(rpm=900, sequence=\"CCW\", device_id=2)\n# await shaker.start_shaking(rpm=1200, device_id=3)", "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "id": "bigbear-home-md", "source": "## Homing\n\nHome a single nest with `find_home()`, or every nest with `home_all()`.", "metadata": {} }, { "cell_type": "code", "id": "bigbear-home-code", "source": "await shaker.find_home(device_id=1)\n# or, for the whole chain:\n# await shaker.home_all()", "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "id": "bigbear-info-md", "source": "## Device info\n\nRead a nest's serial-number fields (`Y`, `X`, `Z`). The reply format is device-defined; the raw fields are returned joined.", "metadata": {} }, { "cell_type": "code", "id": "bigbear-info-code", "source": "print(\"Serial number:\", await shaker.get_serial_number(device_id=1))", "metadata": {}, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "id": "bigbear-teardown-md", "source": "## Teardown\n\n`stop()` stops every nest and closes the serial connection.", "metadata": {} }, { "cell_type": "code", "id": "bigbear-teardown-code", "source": "await shaker.stop()", "metadata": {}, "execution_count": null, "outputs": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 5 }