Files
radar_system/python_app/hardware_full/laser_control/conversions.py
T
2026-10-06 19:36:00 +03:00

57 lines
1.9 KiB
Python

"""Physical unit conversions for the laser control module.
Converts between physical quantities (°C, mA, V) and the raw ADC/DAC integer
values used by the device firmware, using the hardware's bridge/divider formulas.
"""
import math
from .constants import ADC_BITS_16, BETA_INTERNAL, R0, R1, R3, R4, R5, R6, RREF, T0_K, VREF
def temp_c_to_n(temp_c: float) -> int:
"""
Convert temperature (°C) to 16-bit DAC integer (Wheatstone bridge setpoint).
Args:
temp_c: Temperature in degrees Celsius.
Returns:
Integer in [0, 65535] for the DAC.
"""
rt = R0 * math.exp(BETA_INTERNAL / (temp_c + 273) - BETA_INTERNAL / T0_K)
u = VREF / (R5 * (R3 + R4)) * (
R1 * R4 * (R5 + R6) - rt * (R3 * R6 - R4 * R5)
) / (rt + R1)
n = int(u * ADC_BITS_16 / VREF)
n = max(0, min(ADC_BITS_16, n))
return n
def current_ma_to_n(current_ma: float) -> int:
"""
Convert laser drive current (mA) to 16-bit DAC integer.
Args:
current_ma: Current in milliamps.
Returns:
Integer in [0, 65535] for the DAC.
"""
# Rounded like the lab GUI (_device_main.py), so both send identical DAC codes.
return max(0, min(ADC_BITS_16, round(ADC_BITS_16 / 2000 * RREF * current_ma)))
def variation_codes(min_value: float, max_value: float, step: float) -> tuple[int, int, int]:
low, high, delta = (current_ma_to_n(value) for value in (min_value, max_value, step))
if delta == 0 or low >= high:
raise ValueError("Current variation range and step must be representable by the DAC")
return low, high, delta
def variation_step_count(min_value: float, max_value: float, step: float) -> int:
"""SWEEP_STEP edges per sweep: firmware loops ``while (current < max) current += delta`` on these codes."""
low, high, delta = variation_codes(min_value, max_value, step)
return math.ceil((high - low) / delta)