UniteLabs

Deck & Carriers

Setting up the Tecan Freedom EVO worktable with tracks, model presets, and carriers.
The Freedom EVO is supported in liquid handling SDK versions >=0.35.0.

The Freedom EVO worktable is a series of 25 mm rail tracks (Tecan calls this surface the worktable; we call it the deck). Carriers are placed by track number, not by absolute coordinate, and each carrier occupies a contiguous span of tracks derived from its width. Labware such as plates and tip boxes are never added to the deck directly — they sit on sites belonging to a carrier.

Prerequisites

  • A switched on Tecan Freedom EVO device
  • A running Tecan Freedom EVO connector
  • Basic understanding of how labware is used (See the using standard labware tutorial)

Connect and Configure

from unitelabs.sdk import AsyncApiClient
from unitelabs.liquid_handling.tecan import TecanFreedomEvo, TecanFreedomEvoConfiguration
from unitelabs.labware import Vector

client = AsyncApiClient()

evo = TecanFreedomEvo(
    name="Tecan Freedom EVO",
    client=client,
    configuration=TecanFreedomEvoConfiguration(
        model="EVO150",
        mca_discard_location=Vector(x=1000, y=100, z=100),
    ),
)

await evo.configure()
await evo.initialize()
await evo.activate()
configure() reads the instrument's installed-module map from the firmware (whether a Robotic Manipulator Arm and/or Multi-Channel Arm are fitted) and only configures/initializes the modules that are actually present. initialize() calls configure() implicitly if it hasn't run yet.
Required for the MCA: if the instrument reports a Multi-Channel Arm, mca_discard_location must be set on the configuration before configure() is called — it's the deck-frame position (mm) of channel A1 when the head discards tips into the waste. Omitting it raises a ValueError.

Deck Models

Pass model on the configuration (as done in the example above) to set the track count from an EVO model preset. The track count is applied when configure() runs.

ModelTracks
EVO10030
EVO15045
EVO20069

For a non-standard deck, call deck.configure() directly with an explicit track count instead of a model preset:

await evo.deck.configure(tracks=40, min_track=1, max_track=38)

min_track/max_track bound where carriers may be placed (both default to the full track range); set either to None to remove that boundary.

Arrange Carriers

Carriers hold labware on fixed sites and are placed on the deck by track number. This example uses a 3-position flat microplate carrier.

from unitelabs.labware.plates import Standard96Plate
from unitelabs.labware.tecan import MP_3Pos_flat

plate_carrier = MP_3Pos_flat()
plate = Standard96Plate(identifier="DestinationPlate_96Well")

plate_carrier[0] = plate
evo.deck.add(plate_carrier, track=1)

deck.add() only accepts Carrier instances — passing a plate or tip box directly raises a RuntimeError. Tip boxes (EvoTipBox and its variants) also sit on an ordinary plate carrier site, not a dedicated tip carrier:

from unitelabs.labware.tecan import EvoTipBox_MCA_DiTi_200, EvoTip_MCA_DiTi_200, MP_4Pos_flat

tip_carrier = MP_4Pos_flat()
tip_box = EvoTipBox_MCA_DiTi_200(identifier="TipBox_200uL")
tip_box.fill(EvoTip_MCA_DiTi_200)

tip_carrier[0] = tip_box
evo.deck.add(tip_carrier, track=7)

Alternatively, add a carrier at an explicit absolute location instead of a track:

evo.deck.add(plate_carrier, location=Vector(x=25, y=0))

Track Boundaries and Overlaps

Placing a carrier outside min_track/max_track raises an IndexError. Placing a carrier so it overlaps tracks already occupied by another carrier raises an OccupiedError.

try:
    evo.deck.add(plate_carrier, track=1)  # already occupied
except Exception as error:
    print(error)
    # Invalid track: 1. Carrier occupies 6 tracks and track 1 is occupied by MP_3Pos_flat

Deck Summary

Print a track-oriented overview of the current deck layout — useful for debugging deck arrangements interactively.

print(evo.deck.summary())
   Track  Name                          ID            Position (x, y, z mm)
================================================================================
     1-6  MP_3Pos_flat                  24a65f1f      (0.0, 0.0, 0.0)
          └── Standard96Plate          DestinationP (10.0, 203.8, 6.0)
          └── <empty>
          └── <empty>
    7-12  MP_4Pos_flat                  34c2ae53      (150.0, 0.0, 0.0)
          └── EvoTipBox_MCA_DiTi_200   TipBox_200uL (163.2, 292.4, 6.9)
          └── <empty>
          └── <empty>
          └── <empty>

Remove a Carrier

evo.deck.remove(plate_carrier)

Or clear the whole deck:

evo.deck.clear()

System Controls

The Freedom EVO connector exposes door lock control, but has no stop, resume, or home commands implemented — calling them logs a warning instead of raising, so scripts written against the generic LiquidHandler interface don't break.

from unitelabs.liquid_handling.tecan import DoorLock

# Lock all doors
await evo.set_door_lock(True)

# Lock a specific subset
await evo.set_door_lock(True, doors=[DoorLock.LOCK_1, DoorLock.LOCK_2])
evo.stop(), evo.resume(), and evo.home() are no-ops that log a warning. There is currently no way to halt or home the instrument through the SDK; use the physical stop button or EVOware for emergency stops.