Skip to content

Commit 70b9d04

Browse files
committed
dut_power: implement an error-free grace period after DUT power on
We have seen errors where the DUT power switch refuses to turn on when a power supply is connected but the OUT- pin of the power switch is not connected to the GND level of the TAC. The voltage measurements that lead to this decision are actually correct, because the voltage measurement is very high impedance and small leakage currents make their way from the power supply into the power switch. But being correct and being sensible are two different things. Make it so that one can always turn the output on, leave it on for a bit to let everything settle and only then start to check for errors on the voltage supply. Signed-off-by: Leonard Göhrs <[email protected]>
1 parent d8e70b0 commit 70b9d04

File tree

1 file changed

+87
-9
lines changed

1 file changed

+87
-9
lines changed

src/dut_power.rs

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ use prio::realtime_priority;
6363
const MAX_AGE: Duration = Duration::from_millis(300);
6464
const THREAD_INTERVAL: Duration = Duration::from_millis(100);
6565
const TASK_INTERVAL: Duration = Duration::from_millis(200);
66+
const TURN_ON_ERROR_GRACE_PERIOD: Duration = Duration::from_millis(600);
6667
const MAX_CURRENT: f32 = 5.0;
6768
const MAX_VOLTAGE: f32 = 48.0;
6869
const MIN_VOLTAGE: f32 = -1.0;
@@ -353,6 +354,12 @@ impl DutPwrThread {
353354
}
354355
};
355356

357+
// The grace period contains the number of loop iterations until
358+
// we start handling over/under voltage and overcurrent events.
359+
// This counts down to zero after turning on the output.
360+
// And is kept at TURN_ON_ERROR_GRACE_PERIOD while the output is off.
361+
let mut grace_period = TURN_ON_ERROR_GRACE_PERIOD;
362+
356363
// Run as long as there is a strong reference to `tick`.
357364
// As tick is a private member of the struct this is equivalent
358365
// to running as long as the DutPwrThread was not dropped.
@@ -413,10 +420,29 @@ impl DutPwrThread {
413420
.swap(OutputRequest::Idle as u8, Ordering::Relaxed)
414421
.into();
415422

416-
{
417-
// Don't even look at the requests if there is an ongoing
418-
// overvoltage condition. Instead turn the output off and
419-
// go back to measuring.
423+
// Checking for MAX_VOLTAGE, MIN_VOLTAGE, MAX_CURRENT error conditions while
424+
// the DUT power switch is off does not make a lot of sense,
425+
// considering the way we measure these values right now (behind the DUT power switch).
426+
// And what would we even do in this case? Turn the output even more off?
427+
// If we see one of these error conditions while the output is off it is
428+
// likely due to our high-impedance measurements and not due to a real error.
429+
// Ignore these kinds of errors while the output is off and for a few
430+
// THREAD_INTERVALs after turning it on.
431+
grace_period = match state.load(Ordering::Relaxed).into() {
432+
OutputState::On => grace_period.saturating_sub(THREAD_INTERVAL),
433+
OutputState::Off
434+
| OutputState::OffFloating
435+
| OutputState::Changing
436+
| OutputState::InvertedPolarity
437+
| OutputState::OverCurrent
438+
| OutputState::OverVoltage
439+
| OutputState::RealtimeViolation => TURN_ON_ERROR_GRACE_PERIOD,
440+
};
441+
442+
if grace_period == Duration::ZERO {
443+
// At this point the output is on and has been on for
444+
// TURN_ON_ERROR_GRACE_PERIOD, so we start checking for error conditions.
445+
420446
if volt > MAX_VOLTAGE {
421447
turn_off_with_reason(
422448
OutputState::OverVoltage,
@@ -428,9 +454,6 @@ impl DutPwrThread {
428454
continue;
429455
}
430456

431-
// Don't even look at the requests if there is an ongoin
432-
// polarity inversion. Turn off, go back to start, do not
433-
// collect $200.
434457
if volt < MIN_VOLTAGE {
435458
turn_off_with_reason(
436459
OutputState::InvertedPolarity,
@@ -442,8 +465,6 @@ impl DutPwrThread {
442465
continue;
443466
}
444467

445-
// Don't even look at the requests if there is an ongoin
446-
// overcurrent condition.
447468
if curr > MAX_CURRENT {
448469
turn_off_with_reason(
449470
OutputState::OverCurrent,
@@ -744,4 +765,61 @@ mod tests {
744765
assert_eq!(pwr_line.stub_get(), 1 - PWR_LINE_ASSERTED);
745766
assert_eq!(discharge_line.stub_get(), DISCHARGE_LINE_ASSERTED);
746767
}
768+
769+
#[test]
770+
fn grace_period() {
771+
let mut wtb = WatchedTasksBuilder::new();
772+
let pwr_line = find_line("DUT_PWR_EN").unwrap();
773+
let discharge_line = find_line("DUT_PWR_DISCH").unwrap();
774+
775+
let (adc, dut_pwr) = {
776+
let mut bb = BrokerBuilder::new();
777+
let adc = block_on(Adc::new(&mut bb, &mut wtb)).unwrap();
778+
let led = Topic::anonymous(None);
779+
780+
let dut_pwr = block_on(DutPwrThread::new(
781+
&mut bb,
782+
&mut wtb,
783+
adc.pwr_volt.clone(),
784+
adc.pwr_curr.clone(),
785+
led,
786+
))
787+
.unwrap();
788+
789+
(adc, dut_pwr)
790+
};
791+
792+
// Set acceptable voltage / current
793+
adc.pwr_volt.fast.set(MAX_VOLTAGE * 0.99);
794+
adc.pwr_curr.fast.set(MAX_CURRENT * 0.99);
795+
796+
println!("Turn Off");
797+
dut_pwr.request.set(OutputRequest::Off);
798+
block_on(sleep(Duration::from_millis(500)));
799+
assert_eq!(pwr_line.stub_get(), 1 - PWR_LINE_ASSERTED);
800+
assert_eq!(discharge_line.stub_get(), DISCHARGE_LINE_ASSERTED);
801+
assert_eq!(block_on(dut_pwr.state.get()), OutputState::Off);
802+
803+
println!("Set overvoltage");
804+
adc.pwr_volt.fast.set(MAX_VOLTAGE * 1.01);
805+
block_on(sleep(Duration::from_millis(500)));
806+
807+
println!("Check if output stays off and does not go into error state");
808+
assert_eq!(pwr_line.stub_get(), 1 - PWR_LINE_ASSERTED);
809+
assert_eq!(discharge_line.stub_get(), DISCHARGE_LINE_ASSERTED);
810+
assert_eq!(block_on(dut_pwr.state.get()), OutputState::Off);
811+
812+
println!("Turn On (with overvoltage applied)");
813+
dut_pwr.request.set(OutputRequest::On);
814+
block_on(sleep(Duration::from_millis(400)));
815+
assert_eq!(pwr_line.stub_get(), PWR_LINE_ASSERTED);
816+
assert_eq!(discharge_line.stub_get(), 1 - DISCHARGE_LINE_ASSERTED);
817+
assert_eq!(block_on(dut_pwr.state.get()), OutputState::On);
818+
819+
println!("Go into overvoltage error");
820+
block_on(sleep(Duration::from_millis(500)));
821+
assert_eq!(pwr_line.stub_get(), 1 - PWR_LINE_ASSERTED);
822+
assert_eq!(discharge_line.stub_get(), DISCHARGE_LINE_ASSERTED);
823+
assert_eq!(block_on(dut_pwr.state.get()), OutputState::OverVoltage);
824+
}
747825
}

0 commit comments

Comments
 (0)