219 lines
7.2 KiB
Python
219 lines
7.2 KiB
Python
"""
|
|
Data models for laser control module.
|
|
|
|
Provides dataclasses and enums for structured data representation
|
|
throughout the laser control system.
|
|
"""
|
|
|
|
from dataclasses import dataclass
|
|
from enum import IntEnum
|
|
from typing import Optional, Dict, Any
|
|
from datetime import datetime
|
|
|
|
|
|
class VariationType(IntEnum):
|
|
"""Types of parameter variation modes."""
|
|
MANUAL = 0x00
|
|
CHANGE_CURRENT_LD1 = 0x01
|
|
CHANGE_CURRENT_LD2 = 0x02
|
|
CHANGE_TEMPERATURE_LD1 = 0x03
|
|
CHANGE_TEMPERATURE_LD2 = 0x04
|
|
|
|
|
|
class DeviceState(IntEnum):
|
|
"""Device operational states."""
|
|
IDLE = 0x0000
|
|
RUNNING = 0x0001
|
|
BUSY = 0x0002
|
|
ERROR = 0x00FF
|
|
ERROR_OVERHEAT = 0x0100
|
|
ERROR_POWER = 0x0200
|
|
ERROR_COMMUNICATION = 0x0400
|
|
ERROR_INVALID_COMMAND = 0x0800
|
|
|
|
|
|
@dataclass
|
|
class ManualModeParams:
|
|
"""Parameters for manual control mode."""
|
|
temp1: float # Temperature for laser 1 (°C)
|
|
temp2: float # Temperature for laser 2 (°C)
|
|
current1: float # Current for laser 1 (mA)
|
|
current2: float # Current for laser 2 (mA)
|
|
pi_coeff1_p: float = 1.0 # PI controller proportional coefficient for laser 1
|
|
pi_coeff1_i: float = 0.5 # PI controller integral coefficient for laser 1
|
|
pi_coeff2_p: float = 1.0 # PI controller proportional coefficient for laser 2
|
|
pi_coeff2_i: float = 0.5 # PI controller integral coefficient for laser 2
|
|
|
|
def to_dict(self) -> Dict[str, float]:
|
|
"""Convert to dictionary representation."""
|
|
return {
|
|
'temp1': self.temp1,
|
|
'temp2': self.temp2,
|
|
'current1': self.current1,
|
|
'current2': self.current2,
|
|
'pi_coeff1_p': self.pi_coeff1_p,
|
|
'pi_coeff1_i': self.pi_coeff1_i,
|
|
'pi_coeff2_p': self.pi_coeff2_p,
|
|
'pi_coeff2_i': self.pi_coeff2_i
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class VariationParams:
|
|
"""Parameters for variation mode."""
|
|
variation_type: VariationType
|
|
# Static parameters (fixed during variation)
|
|
static_temp1: float
|
|
static_temp2: float
|
|
static_current1: float
|
|
static_current2: float
|
|
# Variation range
|
|
min_value: float # Minimum value for varied parameter
|
|
max_value: float # Maximum value for varied parameter
|
|
step: float # Step size for variation
|
|
# Time parameters
|
|
time_step: int # Time step in microseconds (20-100)
|
|
delay_time: int # Delay between measurements in milliseconds (3-10)
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
"""Convert to dictionary representation."""
|
|
return {
|
|
'variation_type': self.variation_type.value,
|
|
'static_temp1': self.static_temp1,
|
|
'static_temp2': self.static_temp2,
|
|
'static_current1': self.static_current1,
|
|
'static_current2': self.static_current2,
|
|
'min_value': self.min_value,
|
|
'max_value': self.max_value,
|
|
'step': self.step,
|
|
'time_step': self.time_step,
|
|
'delay_time': self.delay_time
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class Measurements:
|
|
"""Real-time measurements from the device."""
|
|
# Photodiode currents
|
|
current1: float # Photodiode current for laser 1 (mA)
|
|
current2: float # Photodiode current for laser 2 (mA)
|
|
# Temperatures
|
|
temp1: float # Temperature of laser 1 (°C)
|
|
temp2: float # Temperature of laser 2 (°C)
|
|
temp_ext1: Optional[float] = None # External thermistor 1 temperature (°C)
|
|
temp_ext2: Optional[float] = None # External thermistor 2 temperature (°C)
|
|
# Power supply voltages
|
|
voltage_3v3: float = 0.0 # 3.3V rail voltage
|
|
voltage_5v1: float = 0.0 # 5V rail 1 voltage
|
|
voltage_5v2: float = 0.0 # 5V rail 2 voltage
|
|
voltage_7v0: float = 0.0 # 7V rail voltage
|
|
# Metadata
|
|
timestamp: Optional[datetime] = None
|
|
message_id: Optional[int] = None
|
|
to6_counter_lsb: Optional[int] = None
|
|
to6_counter_msb: Optional[int] = None
|
|
|
|
def __post_init__(self):
|
|
"""Set timestamp if not provided."""
|
|
if self.timestamp is None:
|
|
self.timestamp = datetime.now()
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
"""Convert to dictionary representation."""
|
|
return {
|
|
'current1': self.current1,
|
|
'current2': self.current2,
|
|
'temp1': self.temp1,
|
|
'temp2': self.temp2,
|
|
'temp_ext1': self.temp_ext1,
|
|
'temp_ext2': self.temp_ext2,
|
|
'voltage_3v3': self.voltage_3v3,
|
|
'voltage_5v1': self.voltage_5v1,
|
|
'voltage_5v2': self.voltage_5v2,
|
|
'voltage_7v0': self.voltage_7v0,
|
|
'timestamp': self.timestamp.isoformat() if self.timestamp else None,
|
|
'message_id': self.message_id
|
|
}
|
|
|
|
def check_power_rails(self) -> Dict[str, bool]:
|
|
"""Check if power supply voltages are within acceptable range."""
|
|
return {
|
|
'3v3': 3.1 <= self.voltage_3v3 <= 3.5,
|
|
'5v1': 4.8 <= self.voltage_5v1 <= 5.3,
|
|
'5v2': 4.8 <= self.voltage_5v2 <= 5.3,
|
|
'7v0': 6.5 <= self.voltage_7v0 <= 7.5
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class DeviceStatus:
|
|
"""Complete device status information."""
|
|
state: DeviceState
|
|
measurements: Optional[Measurements] = None
|
|
is_connected: bool = False
|
|
last_command_id: Optional[int] = None
|
|
error_message: Optional[str] = None
|
|
|
|
@property
|
|
def is_idle(self) -> bool:
|
|
"""Check if device is idle."""
|
|
return self.state == DeviceState.IDLE
|
|
|
|
@property
|
|
def is_running(self) -> bool:
|
|
"""Check if device is running a task."""
|
|
return self.state == DeviceState.RUNNING
|
|
|
|
@property
|
|
def has_error(self) -> bool:
|
|
"""Check if device has any error."""
|
|
return self.state >= DeviceState.ERROR
|
|
|
|
@property
|
|
def error_type(self) -> Optional[str]:
|
|
"""Get human-readable error type."""
|
|
if not self.has_error:
|
|
return None
|
|
|
|
error_map = {
|
|
DeviceState.ERROR_OVERHEAT: "Overheating",
|
|
DeviceState.ERROR_POWER: "Power supply issue",
|
|
DeviceState.ERROR_COMMUNICATION: "Communication error",
|
|
DeviceState.ERROR_INVALID_COMMAND: "Invalid command"
|
|
}
|
|
return error_map.get(self.state, "Unknown error")
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
"""Convert to dictionary representation."""
|
|
return {
|
|
'state': self.state.value,
|
|
'state_name': self.state.name,
|
|
'measurements': self.measurements.to_dict() if self.measurements else None,
|
|
'is_connected': self.is_connected,
|
|
'last_command_id': self.last_command_id,
|
|
'error_message': self.error_message,
|
|
'is_idle': self.is_idle,
|
|
'is_running': self.is_running,
|
|
'has_error': self.has_error,
|
|
'error_type': self.error_type
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class CalibrationData:
|
|
"""Calibration data for device sensors."""
|
|
# Temperature calibration coefficients
|
|
temp1_offset: float = 0.0
|
|
temp1_scale: float = 1.0
|
|
temp2_offset: float = 0.0
|
|
temp2_scale: float = 1.0
|
|
# Current calibration coefficients
|
|
current1_offset: float = 0.0
|
|
current1_scale: float = 1.0
|
|
current2_offset: float = 0.0
|
|
current2_scale: float = 1.0
|
|
# Voltage calibration
|
|
voltage_3v3_scale: float = 1.0
|
|
voltage_5v1_scale: float = 1.0
|
|
voltage_5v2_scale: float = 1.0
|
|
voltage_7v0_scale: float = 1.0 |