Files
scanengine-3/docs/hardware/BBD203_DRIVER_README.md
T
2026-07-28 09:20:58 -05:00

10 KiB
Executable File
Raw Blame History

ThorLabs BBD203 Motor Controller Driver

Overview

This directory contains a complete implementation of the ThorLabs BBD203 3-channel benchtop brushless DC motor controller driver. The driver implements the full APT (Advanced Positioning Technology) binary communications protocol as specified in the BBD203_Communications_Protocol.md document.

Architecture

The BBD203 driver is split into three layers:

1. Protocol Layer (bbd203_protocol.py)

Low-level protocol implementation that handles:

  • Binary message construction and parsing
  • APT protocol message IDs and structures
  • Unit conversions (mm ↔ encoder counts, velocity/acceleration scaling)
  • Status bit definitions

Key Classes:

  • MessageID: Enumeration of all APT message IDs
  • APTMessage: Message builder and parser for binary protocol
  • APTProtocol: High-level protocol interface with unit conversions

2. Driver Layer (bbd203_driver.py)

Complete driver implementation providing:

  • Serial communication with automatic message reception thread
  • 3-channel management (independent motor control)
  • Blocking and non-blocking move operations
  • Status monitoring with automatic updates
  • Event callbacks for move/home completion
  • Thread-safe operation

Key Classes:

  • BBD203Channel: Represents state of a single motor channel
  • BBD203Driver: Main driver class for controller communication

3. Stage Interface Layer (thorlabs_stage.py)

Application-specific wrapper that:

  • Maps 3 motor channels to X/Y/Z axes
  • Provides simplified API for stage control
  • Integrates with the nueScan application
  • Maintains compatibility with existing UI

Channel Mapping:

  • Channel 1 → X-axis
  • Channel 2 → Y-axis
  • Channel 3 → Z-axis (optional)

Features

Communication

  • Binary APT protocol over USB/RS232
  • Baud rate: 115200 (configurable)
  • Automatic message reception in background thread
  • Command/response handling with proper timeout

Motion Control

  • Absolute positioning
  • Relative moves
  • Velocity control
  • Immediate and profiled stops
  • Configurable acceleration

Position Feedback

  • Real-time position updates (encoder counts)
  • Position in mm (with configurable scaling)
  • Status bit monitoring (homing, moving, errors, etc.)

Homing

  • Individual axis homing
  • All-axes homing
  • Blocking or non-blocking operation
  • Completion callbacks

Safety

  • Interlock checking before moves
  • Error detection and reporting
  • Motion error monitoring
  • Limit switch status

Usage

Connection Methods

The driver supports two connection methods:

Similar to ThorLabs Kinesis library - automatically finds the USB device:

from hardware.bbd203_driver import BBD203Driver

# Create driver instance
driver = BBD203Driver(encoder_counts_per_mm=20000)

# List available ThorLabs devices
devices = driver.list_thorlabs_devices()
for device in devices:
    print(f"Serial: {device['serial']}, Port: {device['port']}")

# Connect by serial number (auto-finds the port)
driver.connect_by_serial('83123456')  # Serial printed on controller

Method 2: Connect by Port Name

Direct connection to a specific port:

# Connect to specific port
driver.connect('/dev/ttyUSB0')  # or 'COM3' on Windows

Basic Movement


# Enable all channels
driver.enable_channel(1, True)  # X-axis
driver.enable_channel(2, True)  # Y-axis
driver.enable_channel(3, True)  # Z-axis

# Home all channels (blocking)
driver.home_all_channels(wait=True, timeout=60)

# Set velocity parameters
driver.set_velocity_params(channel=1, max_vel_mm_s=5.0, accel_mm_s2=10.0)

# Move to absolute position (non-blocking)
driver.move_absolute(channel=1, position_mm=10.0, wait=False)

# Move to absolute position (blocking)
driver.move_absolute(channel=2, position_mm=25.0, wait=True, timeout=30)

# Move relative
driver.move_relative(channel=1, distance_mm=-5.0, wait=True)

# Stop motion
driver.stop(channel=1, immediate=True)

# Get position
pos = driver.get_position(channel=1)
print(f"Position: {pos} mm")

# Get detailed status
status = driver.get_channel_status(channel=1)
print(f"Enabled: {status['enabled']}")
print(f"Homed: {status['homed']}")
print(f"Moving: {status['moving']}")

# Disconnect
driver.disconnect()

Using the Stage Interface

from hardware.thorlabs_stage import ThorLabsStage

# Create stage controller
stage = ThorLabsStage(encoder_counts_per_mm=20000)

# List available devices
devices = stage.list_devices()
for device in devices:
    print(f"BBD203 Serial: {device['serial']}")

# Connect by serial number (automatically enables all channels)
stage.connect('83123456')  # Serial number from controller label

# Home all axes
stage.home_all_axes(wait=True)

# Move to position
stage.move_absolute(x=10.0, y=20.0, wait=True)

# Move relative
stage.move_relative(dx=5.0, dy=-2.5, wait=True)

# Get position
pos = stage.get_position()
print(f"X: {pos['x']} mm, Y: {pos['y']} mm, Z: {pos['z']} mm")

# Check status
status = stage.get_status()
print(f"Ready: {status['ready']}")
print(f"X Homed: {status['x_homed']}")

# Disconnect
stage.disconnect()

Event Callbacks

# Define callback function
def on_move_complete(channel):
    print(f"Channel {channel} move completed!")

# Register callback
driver.register_move_complete_callback(1, on_move_complete)

# Start non-blocking move - callback will be called when complete
driver.move_absolute(channel=1, position_mm=50.0, wait=False)

Configuration

Encoder Scaling

The encoder resolution must be configured to match your specific motor/stage combination:

# Example: MLS203 stage with 20,000 counts/mm
driver = BBD203Driver(encoder_counts_per_mm=20000)

# Example: Custom stage with 2,000 counts/mm
driver = BBD203Driver(encoder_counts_per_mm=2000)

Common encoder resolutions:

  • MLS203: 20,000 counts/mm
  • DDS220: 2,000 counts/mm
  • Custom: Varies (check motor specifications)

Velocity and Acceleration

Velocity and acceleration use the APT scaling formulas:

VEL_APT = EncCnt × 102.4e-6 × 65536 × Vel
ACC_APT = EncCnt × (102.4e-6)² × 65536 × Acc

The driver handles these conversions automatically:

# Set velocity to 5 mm/s, acceleration to 10 mm/s²
driver.set_velocity_params(
    channel=1,
    max_vel_mm_s=5.0,
    accel_mm_s2=10.0
)

Integration with nueScan

The driver is integrated into nueScan through the ThorLabsStage wrapper class. The connection is simplified using serial number auto-detection:

Connecting in the UI

  1. Find Serial Number: Look at the label on your BBD203 controller (e.g., 83123456)
  2. Enter Serial: Type the serial number in the "ThorLABS MLS Stage Serial" field
  3. Connect: Click "Connect" button
    • Driver automatically finds the USB device
    • All 3 channels are enabled
    • Status updates begin
  4. Ready: The controller is now ready to home and move axes

Connection Process

When you click "Connect":

  • The driver scans all USB ports for ThorLabs devices (FTDI VID: 0x0403)
  • Finds the device matching your serial number
  • Automatically uses the correct COM port
  • Enables all channels (X/Y/Z axes)
  • Sets default velocity parameters

Troubleshooting Connection

If connection fails, a dialog will show:

  • The serial number you entered
  • List of all detected ThorLabs devices with their serial numbers
  • Helps you identify the correct serial to use

Protocol Details

Message Structure

All APT messages consist of:

  • 6-byte header (message ID, length, destination, source)
  • Optional data packet (variable length)

Destination Addressing

  • 0x21: Channel 1 (X-axis)
  • 0x22: Channel 2 (Y-axis)
  • 0x23: Channel 3 (Z-axis)
  • 0x11: All channels
  • 0x50: USB interface

Status Bits

Key status bits monitored by the driver:

Bit Mask Meaning
HOMING 0x00000200 Homing in progress
HOMED 0x00000400 Axis has been homed
TRACKING 0x00001000 Following target position
SETTLED 0x00002000 Position settled
MOTION_ERROR 0x00004000 Following error exceeded
MOTOR_ENABLED 0x80000000 Motor drive enabled
IN_MOTION_FORWARD 0x00000010 Moving forward
IN_MOTION_REVERSE 0x00000020 Moving reverse

Troubleshooting

Connection Issues

Problem: Cannot connect to controller

Solutions:

  • Verify COM port name is correct (ThorLabsStage.list_available_ports())
  • Check USB cable connection
  • Verify no other software has the port open
  • Try different baud rate (default: 115200)
  • Check device permissions on Linux

Homing Fails

Problem: Homing timeout or never completes

Solutions:

  • Increase homing timeout parameter
  • Check limit switches are functioning
  • Verify motor is enabled
  • Check for mechanical obstructions
  • Review homing parameters (direction, velocity)

Position Errors

Problem: Reported position doesn't match reality

Solutions:

  • Verify encoder_counts_per_mm setting matches your stage
  • Check encoder connections
  • Reset position counter if needed: driver.cmd_set_position_counter()
  • Verify stage is homed before moves

Communication Errors

Problem: Commands not acknowledged or responses missing

Solutions:

  • Increase serial timeout
  • Check for message buffer overflow
  • Verify automatic status updates are enabled
  • Add delays between rapid commands

Debug Output

The driver provides extensive debug output:

INFO: Messages about successful operations
DEBUG: Detailed command/response information
ERROR: Error conditions and failures
WARNING: Potential issues

Enable Python logging to capture all output:

import logging
logging.basicConfig(level=logging.DEBUG)

Performance Notes

  • Message processing runs in separate thread (no blocking)
  • Typical command response time: 10-50ms
  • Position updates: ~10Hz when status messages enabled
  • Move completion detected via asynchronous message
  • Thread-safe for concurrent channel operations

References

  • Protocol Documentation: BBD203_Communications_Protocol.md
  • APT Protocol Version: 42.1
  • Product Manual: Available from Thorlabs.com
  • Technical Support: techsupport@thorlabs.com

License

Copyright (C) 2025 Thomas Ales Licensed under GNU General Public License v2.0