Files
scanengine-3/docs/hardware/BBD203_DRIVER_README.md
2026-02-09 14:40:34 -06:00

391 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
#### Method 1: Connect by Serial Number (Recommended)
Similar to ThorLabs Kinesis library - automatically finds the USB device:
```python
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:
```python
# Connect to specific port
driver.connect('/dev/ttyUSB0') # or 'COM3' on Windows
```
### Basic Movement
```python
# 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
```python
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
```python
# 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:
```python
# 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:
```python
# 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:
```python
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