{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Scales\n", "\n", "PyLabRobot supports the following scales:\n", "\n", "- Mettler Toledo WXS205SDU\n", "\n", "Scales are controlled by the {class}`~pylabrobot.scales.scale.Scale` class. This class takes a backend as an argument. The backend is responsible for communicating with the scale and is specific to the hardware being used." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from pylabrobot.scales import Scale\n", "from pylabrobot.scales.mettler_toledo import MettlerToledoWXS205SDU" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "backend = MettlerToledoWXS205SDU(port=\"/dev/cu.usbserial-110\") # take any ScaleBackend you want\n", "scale = Scale(backend=backend, size_x=0, size_y=0, size_z=0)\n", "await scale.setup()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The {meth}`~pylabrobot.scales.scale.Scale.setup` method is used to initialize the scale. This is where the backend will connect to the scale and perform any necessary initialization.\n", "\n", "The {class}`~pylabrobot.scales.scale.Scale` class has a number of methods for controlling the scale and reading measurements. These are:\n", "\n", "- {meth}`~pylabrobot.scales.scale.Scale.get_weight`: Read the weight from the scale in grams.\n", "- {meth}`~pylabrobot.scales.scale.Scale.tare`: Tare the scale.\n", "- {meth}`~pylabrobot.scales.scale.Scale.zero`: Zero the scale." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "=(MettlerToledoWXS205SDU)\n", "\n", "## Mettler Toledo WXS205SDU\n", "\n", "The Mettler Toledo XS205 scale is controlled by the {class}`~pylabrobot.scales.mettler_toledo.MettlerToledoWXS205SDU` class. This scale is used by the Hamilton Liquid Verification Kit (LVK).\n", "\n", "The scale comes with an RS-232 serial port. You'll probably want to use a USB to serial adapter to connect it to your computer. Any $10 generic USB to serial adapter should work (e.g. something that uses FTDI).\n", "\n", "Note that this scale has a 'warm-up' time after plugging in that is documented as 60-90 minutes by Mettler Toledo depending on the document you like at. In our experience, 30 minutes is sufficient. If you try to take a measurement before this time, you will likely get a \"Command understood but currently not executable (balance is currently executing another command)\" error. Sometimes plugging the power cord in and out will make things work faster." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.00148" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "backend = MettlerToledoWXS205SDU(port=\"/dev/cu.usbserial-110\")\n", "scale = Scale(backend=backend)\n", "await scale.setup()\n", "await scale.get_weight(timeout=\"stable\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This scale provides various timeouts:\n", "\n", "- `\"stable\"`: The time to wait for the scale to stabilize before reading the weight. Note that this may take a very long time to finish if the scale cannot take a stable reading. If you're not using the air enclosure, even being near the scale can cause it to never stabilize.\n", "- 0: Read the value immediately\n", "- n>0: Try to get a stable value for n seconds. If the value is stable before n seconds, return it immediately. Otherwise, return the value after n seconds.\n", "\n", "These parameters are available for {meth}`~pylabrobot.scales.mettler_toledo.MettlerToledoWXS205SDU.get_weight`, {meth}`~pylabrobot.scales.mettler_toledo.MettlerToledoWXS205SDU.tare`, and {meth}`~pylabrobot.scales.mettler_toledo.MettlerToledoWXS205SDU.zero`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.00148" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "await scale.get_weight(timeout=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Example: getting timing information\n", "\n", "Let's say you wanted to determine how long it takes to take a measurement. In PyLabRobot, this is easy:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "backend = MettlerToledoWXS205SDU(port=\"/dev/cu.usbserial-110\")\n", "s = Scale(backend=backend)\n", "await s.setup()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "100.44 ms ± 6.78 ms\n" ] } ], "source": [ "import time\n", "import numpy as np\n", "\n", "l = []\n", "for i in range(10):\n", " t0 = time.monotonic_ns()\n", " await scale.get_weight(timeout=\"stable\")\n", " t1 = time.monotonic_ns()\n", " l.append((t1 - t0) / 1e6)\n", "\n", "print(f\"{np.mean(l):.2f} ms ± {np.std(l):.2f} ms\")" ] } ], "metadata": { "kernelspec": { "display_name": "env", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.12" } }, "nbformat": 4, "nbformat_minor": 2 }