#![allow(clippy::excessive_precision)]
use crate::core::scalar::ControlScalar;
#[derive(Debug, Clone, Copy)]
pub struct DeadTimeCompensator<S: ControlScalar> {
pub dead_time: S,
pub v_dc: S,
pub threshold: S,
pub f_sw: S,
}
impl<S: ControlScalar> DeadTimeCompensator<S> {
pub fn new(dead_time: S, v_dc: S, threshold: S, f_sw: S) -> Self {
Self {
dead_time,
v_dc,
threshold,
f_sw,
}
}
pub fn dead_time_voltage(&self) -> S {
self.v_dc * self.dead_time * self.f_sw
}
pub fn compensate_phase(&self, v_ref: S, i_phase: S) -> S {
let vdt = self.dead_time_voltage();
let abs_i = i_phase.abs();
let polarity = if abs_i >= self.threshold {
i_phase.signum()
} else if self.threshold > S::ZERO {
i_phase / self.threshold
} else {
S::ZERO
};
v_ref + vdt * polarity
}
pub fn compensate(&self, v_ref: [S; 3], i_phase: [S; 3]) -> [S; 3] {
[
self.compensate_phase(v_ref[0], i_phase[0]),
self.compensate_phase(v_ref[1], i_phase[1]),
self.compensate_phase(v_ref[2], i_phase[2]),
]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dead_time_voltage_magnitude() {
let comp = DeadTimeCompensator::<f32>::new(500e-9, 400.0, 0.1, 10_000.0);
let vdt = comp.dead_time_voltage();
assert!((vdt - 2.0_f32).abs() < 1e-3, "Vdt={vdt}");
}
#[test]
fn test_compensate_positive_current() {
let comp = DeadTimeCompensator::<f32>::new(500e-9, 400.0, 0.1, 10_000.0);
let vdt = comp.dead_time_voltage(); let v_in = 100.0_f32;
let i = 5.0_f32; let v_out = comp.compensate_phase(v_in, i);
assert!((v_out - (v_in + vdt)).abs() < 1e-4, "v_out={v_out}");
}
#[test]
fn test_compensate_negative_current() {
let comp = DeadTimeCompensator::<f32>::new(500e-9, 400.0, 0.1, 10_000.0);
let vdt = comp.dead_time_voltage(); let v_in = 100.0_f32;
let i = -5.0_f32;
let v_out = comp.compensate_phase(v_in, i);
assert!((v_out - (v_in - vdt)).abs() < 1e-4, "v_out={v_out}");
}
#[test]
fn test_compensate_three_phase() {
let comp = DeadTimeCompensator::<f32>::new(500e-9, 400.0, 0.1, 10_000.0);
let v_ref = [100.0_f32, -50.0, -50.0];
let i_phase = [5.0_f32, -2.5, -2.5];
let compensated = comp.compensate(v_ref, i_phase);
let vdt = comp.dead_time_voltage();
assert!((compensated[0] - (100.0 + vdt)).abs() < 1e-4);
assert!((compensated[1] - (-50.0 - vdt)).abs() < 1e-4);
assert!((compensated[2] - (-50.0 - vdt)).abs() < 1e-4);
}
#[test]
fn test_compensate_near_zero_current() {
let comp = DeadTimeCompensator::<f32>::new(500e-9, 400.0, 0.1, 10_000.0);
let vdt = comp.dead_time_voltage(); let v_in = 0.0_f32;
let i = 0.05_f32; let v_out = comp.compensate_phase(v_in, i);
let expected = vdt * 0.5;
assert!(
(v_out - expected).abs() < 1e-4,
"v_out={v_out}, expected={expected}"
);
}
}