Implement LDO DUT model
Temperature-dependent LDO voltage regulator model with: - Output voltage tempco (ppm/°C) - Quiescent current tempco - Dropout voltage temperature dependence - Power dissipation calculation (Vin-Vout)*Iload + Vin*Iq - Dropout detection Implements DUTModel protocol for physics engine integration.
This commit is contained in:
@@ -3,3 +3,8 @@
|
||||
Provides thermal and electrical models for various device types
|
||||
including LDO regulators, op-amps, and other components.
|
||||
"""
|
||||
|
||||
from py_dvt_ate.simulation.physics.models.base import DUTModel
|
||||
from py_dvt_ate.simulation.physics.models.ldo import LDOModel, LDOParameters
|
||||
|
||||
__all__ = ["DUTModel", "LDOModel", "LDOParameters"]
|
||||
|
||||
219
src/py_dvt_ate/simulation/physics/models/ldo.py
Normal file
219
src/py_dvt_ate/simulation/physics/models/ldo.py
Normal file
@@ -0,0 +1,219 @@
|
||||
"""LDO (Low Dropout Regulator) DUT model.
|
||||
|
||||
Implements temperature-dependent electrical behaviour for an LDO voltage
|
||||
regulator, including output voltage tempco, quiescent current variation,
|
||||
and power dissipation calculations.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LDOParameters:
|
||||
"""Configuration parameters for an LDO model.
|
||||
|
||||
All temperature coefficients are referenced to 25°C.
|
||||
|
||||
Attributes:
|
||||
nominal_output_voltage: Nominal output voltage at 25°C in volts.
|
||||
tempco_ppm_per_c: Output voltage temperature coefficient in ppm/°C.
|
||||
quiescent_current_a: Quiescent current at 25°C in amps.
|
||||
quiescent_current_tempco: Quiescent current temperature coefficient (1/°C).
|
||||
dropout_voltage: Dropout voltage at 25°C in volts.
|
||||
max_output_current: Maximum output current in amps.
|
||||
"""
|
||||
|
||||
nominal_output_voltage: float = 3.3
|
||||
tempco_ppm_per_c: float = 50.0
|
||||
quiescent_current_a: float = 50e-6 # 50 µA
|
||||
quiescent_current_tempco: float = 0.003 # 0.3%/°C
|
||||
dropout_voltage: float = 0.3
|
||||
max_output_current: float = 0.5
|
||||
|
||||
|
||||
# Reference temperature for all calculations
|
||||
REFERENCE_TEMPERATURE_C = 25.0
|
||||
|
||||
|
||||
class LDOModel:
|
||||
"""Temperature-dependent LDO voltage regulator model.
|
||||
|
||||
Models the electrical behaviour of a linear voltage regulator with:
|
||||
- Output voltage that varies with temperature (tempco in ppm/°C)
|
||||
- Quiescent current that varies with temperature
|
||||
- Dropout voltage that increases with temperature
|
||||
- Power dissipation from (Vin - Vout) × Iload + Vin × Iq
|
||||
|
||||
This class implements the DUTModel protocol.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
params: LDOParameters | None = None,
|
||||
input_voltage: float = 5.0,
|
||||
load_current: float = 0.0,
|
||||
) -> None:
|
||||
"""Initialise the LDO model.
|
||||
|
||||
Args:
|
||||
params: LDO parameters. Uses defaults if None.
|
||||
input_voltage: Initial input voltage in volts.
|
||||
load_current: Initial load current in amps.
|
||||
"""
|
||||
self._params = params or LDOParameters()
|
||||
self._input_voltage = input_voltage
|
||||
self._load_current = load_current
|
||||
|
||||
@property
|
||||
def params(self) -> LDOParameters:
|
||||
"""Get the LDO parameters."""
|
||||
return self._params
|
||||
|
||||
@property
|
||||
def input_voltage(self) -> float:
|
||||
"""Get the current input voltage."""
|
||||
return self._input_voltage
|
||||
|
||||
@input_voltage.setter
|
||||
def input_voltage(self, value: float) -> None:
|
||||
"""Set the input voltage."""
|
||||
self._input_voltage = value
|
||||
|
||||
@property
|
||||
def load_current(self) -> float:
|
||||
"""Get the current load current."""
|
||||
return self._load_current
|
||||
|
||||
@load_current.setter
|
||||
def load_current(self, value: float) -> None:
|
||||
"""Set the load current."""
|
||||
self._load_current = value
|
||||
|
||||
def calculate_output_voltage(self, junction_temperature: float) -> float:
|
||||
"""Calculate the output voltage at the given junction temperature.
|
||||
|
||||
Implements: V_out(T) = V_nom × (1 + TC_vout × (T - 25) × 1e-6)
|
||||
|
||||
The output voltage is clamped to not exceed (Vin - Vdropout) when
|
||||
the regulator is in dropout.
|
||||
|
||||
Args:
|
||||
junction_temperature: DUT junction temperature in degrees Celsius.
|
||||
|
||||
Returns:
|
||||
Output voltage in volts.
|
||||
"""
|
||||
delta_t = junction_temperature - REFERENCE_TEMPERATURE_C
|
||||
tempco_factor = 1.0 + self._params.tempco_ppm_per_c * delta_t * 1e-6
|
||||
|
||||
ideal_vout = self._params.nominal_output_voltage * tempco_factor
|
||||
|
||||
# Calculate dropout voltage at temperature
|
||||
v_dropout = self._calculate_dropout_voltage(junction_temperature)
|
||||
|
||||
# Clamp output to not exceed (Vin - Vdropout)
|
||||
max_vout = max(0.0, self._input_voltage - v_dropout)
|
||||
|
||||
return min(ideal_vout, max_vout)
|
||||
|
||||
def calculate_quiescent_current(self, junction_temperature: float) -> float:
|
||||
"""Calculate the quiescent current at the given junction temperature.
|
||||
|
||||
Implements: I_q(T) = I_q_25 × (1 + TC_iq × (T - 25))
|
||||
|
||||
Args:
|
||||
junction_temperature: DUT junction temperature in degrees Celsius.
|
||||
|
||||
Returns:
|
||||
Quiescent current in amps.
|
||||
"""
|
||||
delta_t = junction_temperature - REFERENCE_TEMPERATURE_C
|
||||
tempco_factor = 1.0 + self._params.quiescent_current_tempco * delta_t
|
||||
|
||||
return self._params.quiescent_current_a * tempco_factor
|
||||
|
||||
def calculate_power_dissipation(
|
||||
self,
|
||||
input_voltage: float,
|
||||
load_current: float,
|
||||
junction_temperature: float,
|
||||
) -> float:
|
||||
"""Calculate the power dissipation for given operating conditions.
|
||||
|
||||
Implements: P_diss = (V_in - V_out) × I_load + V_in × I_q
|
||||
|
||||
The power dissipation comes from:
|
||||
- Voltage drop across the pass element times load current
|
||||
- Quiescent current times input voltage
|
||||
|
||||
Args:
|
||||
input_voltage: Input voltage in volts.
|
||||
load_current: Load current in amps.
|
||||
junction_temperature: DUT junction temperature in degrees Celsius.
|
||||
|
||||
Returns:
|
||||
Power dissipation in watts.
|
||||
"""
|
||||
# Temporarily set input voltage for output voltage calculation
|
||||
original_vin = self._input_voltage
|
||||
self._input_voltage = input_voltage
|
||||
|
||||
try:
|
||||
v_out = self.calculate_output_voltage(junction_temperature)
|
||||
i_q = self.calculate_quiescent_current(junction_temperature)
|
||||
|
||||
# Power in pass element
|
||||
p_pass = (input_voltage - v_out) * load_current
|
||||
|
||||
# Power from quiescent current
|
||||
p_quiescent = input_voltage * i_q
|
||||
|
||||
return p_pass + p_quiescent
|
||||
finally:
|
||||
self._input_voltage = original_vin
|
||||
|
||||
def _calculate_dropout_voltage(self, junction_temperature: float) -> float:
|
||||
"""Calculate the dropout voltage at the given temperature.
|
||||
|
||||
Implements: V_do(T) = V_do_25 × (T_K / 300)^1.5
|
||||
|
||||
where T_K is the temperature in Kelvin.
|
||||
|
||||
Dropout voltage increases with temperature due to increased
|
||||
resistance of the pass element.
|
||||
|
||||
Args:
|
||||
junction_temperature: Junction temperature in degrees Celsius.
|
||||
|
||||
Returns:
|
||||
Dropout voltage in volts.
|
||||
"""
|
||||
# Convert to Kelvin
|
||||
t_kelvin = junction_temperature + 273.15
|
||||
|
||||
# Temperature ratio (reference is approximately 300K ≈ 27°C)
|
||||
temp_ratio = t_kelvin / 300.0
|
||||
|
||||
return self._params.dropout_voltage * (temp_ratio**1.5)
|
||||
|
||||
def is_in_dropout(self, junction_temperature: float) -> bool:
|
||||
"""Check if the LDO is in dropout at current operating point.
|
||||
|
||||
The LDO is in dropout when the input voltage minus dropout voltage
|
||||
is less than the nominal output voltage.
|
||||
|
||||
Args:
|
||||
junction_temperature: Junction temperature in degrees Celsius.
|
||||
|
||||
Returns:
|
||||
True if in dropout, False otherwise.
|
||||
"""
|
||||
v_dropout = self._calculate_dropout_voltage(junction_temperature)
|
||||
headroom = self._input_voltage - v_dropout
|
||||
|
||||
# Get the ideal (temperature-adjusted) output voltage
|
||||
delta_t = junction_temperature - REFERENCE_TEMPERATURE_C
|
||||
tempco_factor = 1.0 + self._params.tempco_ppm_per_c * delta_t * 1e-6
|
||||
ideal_vout = self._params.nominal_output_voltage * tempco_factor
|
||||
|
||||
return headroom < ideal_vout
|
||||
Reference in New Issue
Block a user