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

597 lines
16 KiB
Markdown
Executable File

# Helios Laser System Driver
## Overview
This directory contains a complete implementation of the Helios laser system driver. The driver implements the full RS-232 ASCII communications protocol as specified in the helios_comms_protocol.pdf document.
The Helios laser system is a pulsed solid-state laser with:
- Diode-pumped Nd:YAG/Nd:YLF laser head
- Q-switched operation
- Frequency control (16.7 kHz - 125 kHz)
- Current control (0-7000 mA)
- Power monitoring
- Temperature monitoring (4 sensors)
- External trigger capability
## Architecture
The Helios driver is split into three layers:
### 1. Protocol Layer (`helios_protocol.py`)
Low-level protocol implementation that handles:
- ASCII command construction
- Response parsing and validation
- Unit conversions (Hz ↔ ns, °C ↔ m°C)
- Parameter range validation
- Status register decoding
**Key Classes:**
- `HeliosCommand`: Command constants and builders
- `HeliosProtocol`: High-level protocol interface with validation
### 2. Driver Layer (`helios_driver.py`)
Complete driver implementation providing:
- RS-232 serial communication (9600 baud, 8N1)
- Thread-safe command/query operations
- Comprehensive status monitoring
- Temperature monitoring (pump, resonator, q-switch, power stage)
- Power monitoring
- Laser enable/disable control
- Pulse mode control (single, gating, continuous)
- Frequency and current control
**Key Classes:**
- `PulseMode`: Enumeration of pulse modes
- `HeliosStatus`: Status data structure
- `HeliosDriver`: Main driver class for laser communication
### 3. Integration Layer (`hardware/microscope.py`)
Application-specific integration that:
- Combines Helios with Genesis microscope systems
- Provides unified status monitoring
- Integrates with nueScan application
- Implements safety interlocks
- Provides emergency stop functionality
## Features
### Communication
- ASCII-based RS-232 protocol
- Baud rate: 9600, 8 data bits, no parity, 1 stop bit
- Commands terminated with carriage return (CR)
- Thread-safe operation with mutex locking
- Configurable timeout (default: 1 second)
### Laser Control
- Laser enable/disable
- Three pulse modes:
- Single pulse (one pulse per trigger)
- Continuous gating (pulse train while triggered)
- Continuous pulsing (free-running)
- Frequency control (16.7 kHz to 125 kHz)
- Diode current control (0-7000 mA)
### Monitoring
- Real-time power measurement (mW)
- Four temperature sensors:
- Pump diode temperature
- Resonator temperature
- Q-switch temperature
- Power stage temperature
- Operation hours counter
- Comprehensive status register
- Error detection
### Safety
- Temperature monitoring with warnings
- Error status detection
- Laser enable/disable control
- Emergency stop capability
- Integration with system interlocks
## Usage
### Connection Methods
The driver supports connection to a specific COM port:
```python
from hardware.helios_driver import HeliosDriver
# Create driver instance
driver = HeliosDriver(timeout=1.0)
# List available COM ports
ports = HeliosDriver.list_available_ports()
for port in ports:
print(f"Available port: {port}")
# Connect to specific port
driver.connect('COM5') # or '/dev/ttyUSB0' on Linux
# Get device information
print(f"Controller S/N: {driver.get_controller_serial()}")
print(f"Head S/N: {driver.get_head_serial()}")
```
### Basic Laser Control
```python
# Set frequency (in Hz)
driver.set_frequency_hz(10000) # 10 kHz
# Set diode current (in mA)
driver.set_current_ma(500) # 500 mA
# Set pulse mode
from hardware.helios_driver import PulseMode
driver.set_pulse_mode(PulseMode.CONTINUOUS_PULSING)
# Enable laser
driver.set_laser_enable(True)
# Check if laser is enabled
if driver.is_laser_enabled():
print("Laser is ON")
# Disable laser
driver.set_laser_enable(False)
# Disconnect
driver.disconnect()
```
### Monitoring
```python
# Get current power
power_mw = driver.get_power_mw()
print(f"Output power: {power_mw} mW")
# Get temperatures (in Celsius)
temps = driver.get_all_temperatures()
print(f"Pump: {temps['pump_temp_c']:.1f}°C")
print(f"Resonator: {temps['resonator_temp_c']:.1f}°C")
print(f"Q-switch: {temps['qswitch_temp_c']:.1f}°C")
print(f"Power stage: {temps['power_stage_temp_c']:.1f}°C")
# Get operation hours
hours = driver.get_operation_hours()
print(f"Operation time: {hours} hours")
# Get comprehensive status
status = driver.get_status()
print(f"Connected: {status['connected']}")
print(f"Laser enabled: {status['laser_enabled']}")
print(f"Frequency: {status['frequency_hz']} Hz")
print(f"Current: {status['current_ma']} mA")
print(f"Power: {status['power_mw']} mW")
print(f"Has errors: {status['has_errors']}")
```
### Status Updates
```python
# Manually update status from hardware
driver.update_status()
# Status is automatically updated on each get_status() call
status = driver.get_status()
# Access cached values without querying hardware
freq = driver.get_frequency_hz() # Returns last read value
current = driver.get_current_ma() # Returns last read value
```
### Using Through Microscope Controller
The Helios driver is integrated into the application through the `MicroscopeController`:
```python
from hardware.microscope import MicroscopeController
# Create controller
microscope = MicroscopeController()
# Connect Helios
microscope.connect_helios('COM5')
# Apply settings from dialog
settings = {
'com_port': 'COM5',
'frequency_hz': 10000,
'current_ma': 500
}
microscope.apply_helios_settings(settings)
# Enable laser
microscope.helios_enable_laser(True)
# Get status
status = microscope.get_helios_status()
print(f"Helios ready: {status['ready']}")
print(f"Power: {status['power_mw']} mW")
# Disable laser
microscope.helios_enable_laser(False)
# Disconnect
microscope.disconnect_helios()
```
## Configuration
### Frequency Control
The Helios laser operates by setting the pulse period in nanoseconds. The driver automatically converts between frequency (Hz) and period (ns):
```python
# Set frequency in Hz (driver converts to period in ns)
driver.set_frequency_hz(10000) # 10 kHz → 100,000 ns period
# Valid frequency range: 16.7 kHz to 125 kHz
# Valid period range: 8000 ns to 60000 ns
```
Conversion formulas:
```
Period (ns) = 1,000,000,000 / Frequency (Hz)
Frequency (Hz) = 1,000,000,000 / Period (ns)
```
### Current Control
The diode current controls the laser output power:
```python
# Set current in milliamps
driver.set_current_ma(500) # 500 mA
# Valid range: 0 to 7000 mA
```
**Important:** Higher currents produce more power but also more heat. Monitor temperatures when operating at high current.
### Pulse Modes
Three pulse modes are available:
```python
from hardware.helios_driver import PulseMode
# Single pulse mode (one pulse per trigger)
driver.set_pulse_mode(PulseMode.SINGLE_PULSE)
# Continuous gating mode (pulse train while triggered)
driver.set_pulse_mode(PulseMode.CONTINUOUS_GATING)
# Continuous pulsing mode (free-running)
driver.set_pulse_mode(PulseMode.CONTINUOUS_PULSING)
```
**Mode Descriptions:**
- **Single Pulse (LDG=0)**: One pulse generated per external trigger
- **Continuous Gating (LDG=1)**: Pulse train while external trigger is high
- **Continuous Pulsing (LDG=2)**: Free-running at set frequency (default)
### Temperature Monitoring
The driver monitors four temperature sensors:
```python
# Individual temperatures
pump_temp = driver.query_pump_temp_c()
resonator_temp = driver.query_resonator_temp_c()
qswitch_temp = driver.query_qswitch_temp_c()
power_stage_temp = driver.query_power_stage_temp_c()
# All temperatures at once
temps = driver.get_all_temperatures()
```
**Temperature Ranges:**
- Normal operation: < 50°C
- Warning threshold: > 60°C
- Critical threshold: > 70°C
## Integration with nueScan
The Helios driver is integrated into nueScan through the settings dialog and microscope controller.
### Configuration in UI
1. **Open Helios Settings**
- Click "Helios Device Settings" button in main window
2. **Configure Parameters**
- **COM Port**: Select from dropdown (automatically populated)
- **Frequency**: Enter in Hz (16,666 - 125,000 Hz)
- **Current**: Enter in mA (0 - 7000 mA)
3. **Apply Settings**
- Click OK to apply and connect
- Settings are validated before sending to hardware
### Settings Dialog Integration
The `HeliosDialog` class provides:
- Automatic COM port enumeration
- Input validation with range checking
- User-friendly error messages
- Settings persistence
```python
# Dialog usage (called from main window)
from dialogs.helios_dialog import HeliosDialog
dialog = HeliosDialog(parent=self)
if dialog.exec() == QDialog.DialogCode.Accepted:
settings = dialog.get_settings() # Returns None if validation fails
if settings:
self.microscope.apply_helios_settings(settings)
```
### Validation Rules
The dialog validates all inputs before accepting:
**Frequency Validation:**
- Range: 16,666 Hz to 125,000 Hz
- Reason: Hardware period limit of 8000-60000 ns
- Error message shows entered value and valid range
**Current Validation:**
- Range: 0 to 7000 mA
- Reason: Maximum diode current rating
- Error message shows entered value and valid range
**COM Port Validation:**
- Must select valid port from list
- Cannot accept "No ports found" placeholder
- Error message prompts to check connections
## Protocol Details
### Command Format
All commands follow the format:
```
COMMAND [value]<CR>
```
Where:
- `COMMAND` is a 3-letter mnemonic (e.g., LDO, LDF, LDS)
- `[value]` is optional numeric parameter
- `<CR>` is carriage return (0x0D)
### Command Set
| Command | Parameter | Description |
|---------|-----------|-------------|
| LDO | 0/1 | Laser enable (0=off, 1=on) |
| LDG | 0/1/2 | Pulse mode (0=single, 1=gating, 2=continuous) |
| LDF | 8000-60000 | Pulse period in nanoseconds |
| LDS | 0-7000 | Diode current in milliamps |
| LDP | - | Query output power (mW) |
| LDPT | - | Query pump temperature (m°C) |
| LDRT | - | Query resonator temperature (m°C) |
| LDQT | - | Query q-switch temperature (m°C) |
| LDPST | - | Query power stage temperature (m°C) |
| LDSR | - | Query status register |
| LDOH | - | Query operation hours |
| LDCSN | - | Query controller serial number |
| LDHSN | - | Query head serial number |
### Response Format
Responses are numeric values terminated with `<CR>`:
```
12345<CR>
```
**Exception:** Serial numbers are returned as strings:
```
SN12345678<CR>
```
### Status Register
The status register (LDSR) returns a 16-bit value with error flags:
| Bit | Mask | Meaning |
|-----|------|---------|
| 0 | 0x0001 | Pump temperature error |
| 1 | 0x0002 | Resonator temperature error |
| 2 | 0x0004 | Q-switch temperature error |
| 3 | 0x0008 | Power stage temperature error |
| 4 | 0x0010 | Diode current error |
| 5 | 0x0020 | Interlock open |
| 6 | 0x0040 | Over-power condition |
| 7 | 0x0080 | Under-voltage condition |
A status of 0 indicates no errors.
### Set and Verify Pattern
For critical parameters, the driver uses a set-and-verify pattern:
```python
def _set_and_verify(self, set_cmd: bytes, query_cmd: bytes, expected: str) -> bool:
# Send set command
self._serial.write(set_cmd)
time.sleep(0.05) # Allow hardware to process
# Query back the value
self._serial.write(query_cmd)
response = self._read_response()
# Verify it matches
return response.strip() == expected.strip()
```
This ensures commands are executed correctly and hardware state matches software state.
## Troubleshooting
### Connection Issues
**Problem:** Cannot connect to laser
**Solutions:**
- Verify COM port name is correct (`HeliosDriver.list_available_ports()`)
- Check RS-232 cable connection
- Verify laser controller is powered on
- Try different COM port
- Check device permissions on Linux (`sudo usermod -a -G dialout $USER`)
### Communication Errors
**Problem:** Commands fail or no response
**Solutions:**
- Verify baud rate is 9600 (default)
- Check cable for proper null-modem configuration if needed
- Increase timeout: `driver = HeliosDriver(timeout=2.0)`
- Check for CR line termination (0x0D)
- Verify no other software has port open
### Frequency/Current Not Updating
**Problem:** Settings don't change on hardware
**Solutions:**
- Check return value of `set_frequency_hz()` and `set_current_ma()`
- Verify parameters are in valid range
- Check status register for errors: `driver.query_status_register()`
- Ensure laser is not in error state
- Try power cycling the controller
### Temperature Warnings
**Problem:** High temperature readings
**Solutions:**
- Check ventilation around laser head and controller
- Reduce diode current if at maximum
- Allow longer cool-down between operations
- Clean air filters if present
- Check for blocked cooling fans
### Laser Won't Enable
**Problem:** `set_laser_enable(True)` fails or laser stays off
**Solutions:**
- Check interlock connections (bit 5 of status register)
- Verify all interlocks are closed
- Check for error flags in status register
- Ensure parameters (frequency, current) are set
- Check external enable switch if present
- Review safety interlock documentation
### Status Register Errors
**Problem:** Status register shows error bits set
**Solutions:**
- Decode status register: `HeliosProtocol.decode_status_register(value)`
- Address specific error conditions:
- Temperature errors: Improve cooling
- Current error: Reduce current setting
- Interlock open: Check safety connections
- Over-power: Reduce current
- Under-voltage: Check power supply
## Debug Output
The driver provides extensive debug output:
```
INFO: Informational messages about operations
DEBUG: Detailed command/response information
WARNING: Potential issues (high temp, errors)
ERROR: Operation failures
```
Enable Python logging to capture all output:
```python
import logging
logging.basicConfig(level=logging.DEBUG)
```
Example debug output:
```
INFO: Connecting to Helios laser on COM5
DEBUG: Sending command: b'LDCSN\r'
DEBUG: Received response: SN12345678
INFO: Successfully connected to Helios on COM5
DEBUG: Sending command: b'LDF 100000\r'
DEBUG: Verifying frequency setting...
INFO: Frequency set to 10000.0 Hz (period: 100000 ns)
```
## Performance Notes
- Command response time: 50-100ms typical
- Temperature queries: ~100ms per sensor
- Status register query: ~50ms
- All queries are synchronous (blocking)
- Thread-safe for concurrent access (mutex protected)
- Set-and-verify adds ~50ms overhead for reliability
## Safety Considerations
### Laser Safety
- **Class 4 Laser**: Hazardous to eyes and skin
- Always verify laser is disabled before opening beam paths
- Use appropriate laser safety eyewear
- Follow all facility laser safety procedures
- Ensure proper interlock connections
### Thermal Management
- Monitor temperatures during operation
- Allow adequate cool-down between high-power operations
- Ensure proper ventilation
- Do not block cooling vents
### Electrical Safety
- Verify proper grounding
- Use shielded cables for trigger/status connections
- Follow proper ESD procedures when servicing
## Hardware Connections
### Utility Connector (9-pin D-Sub)
The utility connector provides external control:
| Pin | Signal | Description |
|-----|--------|-------------|
| 1 | GND | Ground |
| 2 | Laser Disable | Input: Pull low to disable laser |
| 3 | External Trigger | Input: Rising edge triggers pulse |
| 4 | Status Out | Output: High when ready |
| 5 | GND | Ground |
| 6-9 | NC | Not connected |
Trigger specifications:
- Input: TTL/CMOS compatible
- Minimum pulse width: 100ns
- Maximum frequency: Limited by pulse mode setting
## References
- **Protocol Documentation**: `helios_comms_protocol.pdf`
- **RS-232 Standard**: EIA/TIA-232
- **Integration Guide**: `SETUP.md`
- **Connection Guide**: See main window Helios settings dialog
## License
Copyright (C) 2025 Thomas Ales
Licensed under GNU General Public License v2.0