Source code for tl_elliptec.devices.models

"""Concrete classes for every ELLx module covered by the protocol manual.

Capability composition follows the per-command "applicability" notes in
the manufacturer manual (not the summary index tables at the end of the
manual, which are inconsistent with the per-command notes and with each
other)::

    Model     Travel type          Motors  Motion cmds  Optimize/Clean  Extras
    ELL6      31mm slider (index)  1                                   -
    ELL6B     31mm slider (index)  2                                   -
    ELL9      31mm slider (index)  2                                   -
    ELL12     19mm slider (index)  2                                   -
    ELL14     360 deg rotary       2       yes          both            -
    ELL15     iris                 2       yes          optimize only   auto-homing
    ELL16     360 deg rotary       2       yes          both            no f/b tuning, no buttons
    ELL17     28mm linear          2       yes          both            -
    ELL18     360 deg rotary       2       yes          both            -
    ELL20     60mm linear          2       yes          both            -
    ELL21     360 deg rotary       2       yes          both            no f/b tuning, no buttons
    ELL22     360 deg filter rot.  2       yes          both            no f/b tuning, no buttons,
                                                                         zero-position, factory reset
"""
from __future__ import annotations

from .base import (
    AutoHomingMixin,
    ElliptecDevice,
    MotionMixin,
    OptimizeCleanMixin,
    ResetFactoryMixin,
    ZeroPositionMixin,
)


[docs] class ELL6(ElliptecDevice): """Bi-positional slider, 1 motor, 31mm indexed travel.""" has_motor2 = False
[docs] class ELL6B(ElliptecDevice): """Multi-position slider, 2 motors, 31mm indexed travel."""
[docs] class ELL9(ElliptecDevice): """Multi-position slider, 2 motors, 31mm indexed travel."""
[docs] class ELL12(ElliptecDevice): """Multi-position slider, 2 motors, 19mm indexed travel."""
[docs] class ELL14(MotionMixin, OptimizeCleanMixin, ElliptecDevice): """Rotary stage, 360 deg, 398 pulses/deg.""" DEFAULT_PULSES_PER_UNIT = 398.0 # pulses/degree PULSES_FIELD_IS_PER_REVOLUTION = True # get_info() reports 143360 pulses/rev, not 398 pulses/deg
[docs] class ELL15(AutoHomingMixin, MotionMixin, OptimizeCleanMixin, ElliptecDevice): """Motorized iris.""" supports_clean = False # "cm" is not offered for the ELL15 DEFAULT_PULSES_PER_UNIT = 1000.0 # pulses across the iris travel, per the manual's device table
[docs] class ELL16(MotionMixin, OptimizeCleanMixin, ElliptecDevice): """Rotary stage, 360 deg, 182 pulses/deg.""" supports_motor_tuning = False supports_button_messages = False DEFAULT_PULSES_PER_UNIT = 182.0 # pulses/degree PULSES_FIELD_IS_PER_REVOLUTION = True # get_info() reports 65536 pulses/rev, not 182 pulses/deg
[docs] class ELL17(MotionMixin, OptimizeCleanMixin, ElliptecDevice): """Linear stage, 28mm, 1024 pulses/mm.""" DEFAULT_PULSES_PER_UNIT = 1024.0 # pulses/mm
# get_info() reports 1024 directly as pulses/mm here, not pulses over # the full 28mm travel, so no PULSES_FIELD_IS_PER_REVOLUTION correction.
[docs] class ELL18(MotionMixin, OptimizeCleanMixin, ElliptecDevice): """Rotary stage, 360 deg, 398 pulses/deg.""" DEFAULT_PULSES_PER_UNIT = 398.0 # pulses/degree PULSES_FIELD_IS_PER_REVOLUTION = True # get_info() reports 143360 pulses/rev, not 398 pulses/deg
[docs] class ELL20(MotionMixin, OptimizeCleanMixin, ElliptecDevice): """Linear stage, 60mm, 1024 pulses/mm.""" DEFAULT_PULSES_PER_UNIT = 1024.0 # pulses/mm
[docs] class ELL21(MotionMixin, OptimizeCleanMixin, ElliptecDevice): """Rotary stage, 360 deg, 182 pulses/deg.""" supports_motor_tuning = False supports_button_messages = False DEFAULT_PULSES_PER_UNIT = 182.0 # pulses/degree PULSES_FIELD_IS_PER_REVOLUTION = True # get_info() reports 65536 pulses/rev, not 182 pulses/deg
[docs] class ELL22( ZeroPositionMixin, ResetFactoryMixin, MotionMixin, OptimizeCleanMixin, ElliptecDevice ): """ND filter rotary stage, 360 deg, 182 pulses/deg.""" supports_motor_tuning = False supports_button_messages = False DEFAULT_PULSES_PER_UNIT = 182.0 # pulses/degree PULSES_FIELD_IS_PER_REVOLUTION = True # confirmed empirically; get_info() reports pulses/rev
#: Maps the decimal model number (14 for an ELL14, etc.) reported by "in"/"IN" #: -- decoded from the wire's hex-ASCII "ELL type" field by #: ``DeviceInfo.from_reply`` -- to its class. Keyed by the plain decimal #: number on purpose: the hex-vs-decimal conversion belongs at that one wire #: boundary, not scattered through code that just wants to know "is this an #: ELL14". Note: ELL6 and ELL6B both report type 6 (they differ only in #: motor count); the factory disambiguates them by probing for a second motor. MODEL_REGISTRY: dict[int, type[ElliptecDevice]] = { 6: ELL6, 9: ELL9, 12: ELL12, 14: ELL14, 15: ELL15, 16: ELL16, 17: ELL17, 18: ELL18, 20: ELL20, 21: ELL21, 22: ELL22, }