Developer Setup Profiles
September 2, 2026 ยท View on GitHub
This page is for maintainers adding or changing machine setup profiles.
Setup profiles live in:
src/dip_coater/setup_profiles/
The main files are:
machine_profile.pydefines the data model.registry.pydefines the bundled profiles and default setup per driver.
Profile Model
A setup profile describes machine geometry, direction, travel limits, homing direction, and limit switches.
Core fields:
MachineProfile(
key=AvailableMachineSetups.CUSTOM,
label="Custom",
mechanical_setup=MechanicalSetup(...),
invert_motor_direction=False,
home_direction=HomeDirection.UP,
limit_switches=None,
min_position_mm=0.0,
max_position_mm=100.0,
homing_max_distance_mm=100.0,
)
mechanical_setup controls unit conversion between motor revolutions and millimeters:
MechanicalSetup(
mm_per_revolution=4.0,
gearbox_ratio=1.0,
steps_per_revolution=200,
)
mm_per_revolution is travel per revolution of the lift's driven mechanism;
gearbox_ratio is motor revolutions per lift-drive revolution. All conversion
constants must be finite and positive, and steps_per_revolution must be a
positive integer. Invalid command-line overrides are rejected before a motor
connection is opened.
Limit Switches
Limit switches are configured with a LimitSwitchSetup. Each setup has one up switch and one down switch.
Each switch has:
source: where the state is read from.polarity: which raw state means triggered.pin: GPIO pin, only for GPIO switches.
Supported sources:
LimitSwitchSource.GPIO
LimitSwitchSource.DRIVER_REFERENCE
Supported polarities:
LimitSwitchPolarity.ACTIVE_HIGH
LimitSwitchPolarity.ACTIVE_LOW
ACTIVE_HIGH means raw True is triggered.
ACTIVE_LOW means raw False is triggered.
Both switches in a pair must use the same hardware source. GPIO pairs require two distinct, non-negative integer pin numbers; driver-reference switches do not accept GPIO pin numbers. Invalid wiring descriptions are rejected when the profile is constructed.
GPIO Switches
Use GPIO switches for Raspberry Pi wiring, such as the small TMC2209 setup:
LimitSwitchSetup.gpio(
up_pin=19,
down_pin=26,
up_nc=True,
down_nc=True,
)
For GPIO switches, up_nc=True and down_nc=True preserve the historical normally-closed behavior:
- GPIO high means triggered.
- GPIO low means open.
The app creates a GPIO backend only when the selected setup uses GPIO switches.
TMC5160 Reference Switches
Use driver reference switches for Landungsbruecke/TMC5160 L/R reference inputs:
LimitSwitchSetup.tmc5160_reference(
up_polarity=LimitSwitchPolarity.ACTIVE_LOW,
down_polarity=LimitSwitchPolarity.ACTIVE_LOW,
)
For the current Landungsbruecke wiring:
- L/R tied to GND is safe.
- L/R open or floating is triggered.
That is why the large setup uses ACTIVE_LOW for both directions.
Typical hardware wiring uses normally-closed switches at the extreme ends of travel:
- switch
COMtoGND - switch
NCto the TMC5160 EVALLorRreference input
See Hardware Setup for the operator-facing wiring note.
The app reads these states through the motor driver methods:
get_left_endstop()
get_right_endstop()
The TMC5160 startup config also enables automatic reference stops by default:
DEFAULT_REFERENCE_LEFT_STOP_ENABLED = True
DEFAULT_REFERENCE_RIGHT_STOP_ENABLED = True
Bundled Profiles
The bundled profiles are defined in registry.py.
small:
- Uses
SetupSmallCoater. - Uses GPIO limit switches on pins 19 and 26.
- Defaults to
HomeDirection.UP.
large:
- Uses
SetupLargeCoater. - Uses Landungsbruecke/TMC5160 driver reference switches.
- Defaults to
HomeDirection.DOWN.
Default setup per driver is also configured in registry.py:
DEFAULT_SETUP_BY_DRIVER = {
AvailableMotorDrivers.TMC2209: AvailableMachineSetups.SMALL_COATER,
AvailableMotorDrivers.TMC2660: AvailableMachineSetups.LARGE_COATER,
AvailableMotorDrivers.TMC5160: AvailableMachineSetups.LARGE_COATER,
}
The TMC2660 mapping preserves the historical default for dummy simulations.
Before hardware is opened, compatibility validation rejects any real driver
that cannot read the selected profile's driver-reference switches. In
particular, real TMC2660 hardware cannot use the bundled large profile; use a
verified GPIO-backed profile or TMC5160 hardware.
Add a New Setup
- Add a new enum value to
AvailableMachineSetups. - Add a
MachineProfileentry in_PROFILES. - Choose the correct
MechanicalSetup. - Configure motor direction with
invert_motor_direction. - Configure homing with
home_directionandhoming_max_distance_mm. - Configure
limit_switcheswithLimitSwitchSetup.gpio(...),LimitSwitchSetup.tmc5160_reference(...), orNone. - Update
DEFAULT_SETUP_BY_DRIVERonly if the new profile should become a default. - Add or update tests in
src/test/test_motion_architecture.py.
Example:
AvailableMachineSetups.MY_COATER = "my-coater"
_PROFILES[AvailableMachineSetups.MY_COATER] = MachineProfile(
key=AvailableMachineSetups.MY_COATER,
label="My Coater",
mechanical_setup=MechanicalSetup(
mm_per_revolution=4.0,
gearbox_ratio=1.0,
steps_per_revolution=200,
),
invert_motor_direction=False,
home_direction=HomeDirection.UP,
limit_switches=LimitSwitchSetup.tmc5160_reference(
up_polarity=LimitSwitchPolarity.ACTIVE_LOW,
down_polarity=LimitSwitchPolarity.ACTIVE_LOW,
),
min_position_mm=0.0,
max_position_mm=100.0,
homing_max_distance_mm=100.0,
)
Safety Checks
Profile travel bounds must be finite, with max_position_mm greater than
min_position_mm. homing_max_distance_mm must be finite and positive. These
checks happen before any motor connection is opened.
After changing a setup profile:
- Run non-hardware tests.
- Start the app in dummy mode and confirm the selected setup label.
- With hardware powered safely, check that limit switch status changes correctly before moving.
- Move only a short distance at low speed.
- Confirm that the motor stops when the active direction's limit switch is triggered.
uv run pytest src/test src/trinamic_wrapper/tests -q