-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/self tests #40
Changes from 5 commits
956be29
e548cbd
6531f2c
6f63913
672decd
16f8646
1edf599
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,107 @@ | ||||||
//! Booster NGFW Application | ||||||
//! | ||||||
//! # Copyright | ||||||
//! Copyright (C) 2020 QUARTIQ GmbH - All Rights Reserved | ||||||
//! Unauthorized usage, editing, or copying is strictly prohibited. | ||||||
//! Proprietary and confidential. | ||||||
use super::I2C; | ||||||
use max6639::Max6639; | ||||||
use shared_bus_rtic::BusProxy; | ||||||
|
||||||
/// Provides control of the chassis-mounted cooling fans. | ||||||
pub struct ChassisFans { | ||||||
fans: [Max6639<BusProxy<I2C>>; 3], | ||||||
} | ||||||
|
||||||
impl ChassisFans { | ||||||
/// Create a new fan controller. | ||||||
/// | ||||||
/// # Args | ||||||
/// * `fans` - The fan controllers to use. | ||||||
/// | ||||||
/// # Returns | ||||||
/// A new fan controller. | ||||||
pub fn new(fans: [Max6639<BusProxy<I2C>>; 3]) -> Self { | ||||||
ChassisFans { fans } | ||||||
} | ||||||
|
||||||
fn set_duty_cycles(&mut self, duty_cycle: f32) { | ||||||
for fan in self.fans.iter_mut() { | ||||||
fan.set_duty_cycle(max6639::Fan::Fan1, duty_cycle).unwrap(); | ||||||
fan.set_duty_cycle(max6639::Fan::Fan2, duty_cycle).unwrap(); | ||||||
} | ||||||
} | ||||||
|
||||||
fn read_rpms(&mut self) -> [u16; 6] { | ||||||
let mut rpms: [u16; 6] = [0; 6]; | ||||||
rpms[0] = self.fans[0].current_rpms(max6639::Fan::Fan1).unwrap(); | ||||||
rpms[1] = self.fans[0].current_rpms(max6639::Fan::Fan2).unwrap(); | ||||||
rpms[2] = self.fans[1].current_rpms(max6639::Fan::Fan1).unwrap(); | ||||||
rpms[3] = self.fans[1].current_rpms(max6639::Fan::Fan2).unwrap(); | ||||||
rpms[4] = self.fans[2].current_rpms(max6639::Fan::Fan1).unwrap(); | ||||||
rpms[5] = self.fans[2].current_rpms(max6639::Fan::Fan2).unwrap(); | ||||||
rpms | ||||||
} | ||||||
|
||||||
/// Perform a self-test of the fan operation. | ||||||
/// | ||||||
/// # Args | ||||||
/// * `delay` - An object to implement delays during the test. | ||||||
/// | ||||||
/// # Returns | ||||||
/// True if 5 of the six fans properly spun up to a high-speed RPM, all 6 were below a specific | ||||||
/// RPM at 10% duty cycle, and all fans had no speed when disabled. | ||||||
pub fn self_test( | ||||||
&mut self, | ||||||
delay: &mut impl embedded_hal::blocking::delay::DelayMs<u16>, | ||||||
) -> bool { | ||||||
delay.delay_ms(7000); | ||||||
let dead_rpms = self.read_rpms(); | ||||||
|
||||||
self.set_duty_cycles(0.1); | ||||||
delay.delay_ms(7000); | ||||||
let low_rpms = self.read_rpms(); | ||||||
|
||||||
self.set_duty_cycles(1.0); | ||||||
delay.delay_ms(2000); | ||||||
let high_rpms = self.read_rpms(); | ||||||
|
||||||
self.set_duty_cycles(0.0); | ||||||
|
||||||
// Check that all dead RPMS are zero. | ||||||
let fans_powered_down = | ||||||
dead_rpms | ||||||
.iter() | ||||||
.fold(0, |count, rpms| if *rpms == 0 { count + 1 } else { count }); | ||||||
|
||||||
// Check all the low RPMs are lower than 3200 RPMs. | ||||||
let fans_spun_low = low_rpms.iter().fold( | ||||||
0, | ||||||
|count, rpms| { | ||||||
if *rpms <= 3200 { | ||||||
count + 1 | ||||||
} else { | ||||||
count | ||||||
} | ||||||
}, | ||||||
); | ||||||
|
||||||
// Check all the high RPMs are higher than 4800 RPMs. | ||||||
let fans_spun_high = | ||||||
high_rpms.iter().fold( | ||||||
0, | ||||||
|count, rpms| { | ||||||
if *rpms >= 4800 { | ||||||
count + 1 | ||||||
} else { | ||||||
count | ||||||
} | ||||||
}, | ||||||
); | ||||||
|
||||||
// If 5 fans (the count mounted on the chassis) spun up to a nominal high speed RPM, 5-6 | ||||||
// fans were at a nominal low RPM, and 6 fans were not spinning when powered down, fans are | ||||||
// operating nominally. | ||||||
(fans_spun_high == 5) && (fans_spun_low >= 6) && (fans_powered_down == 6) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reading the comment:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've updated it such that low spinup requires a non-zero RPM and have slightly reworked this logic. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO verifying that the 1.0 duty cycle having high RPM and then going back to 0.1 duty (and later with feedback) would be enough. |
||||||
} | ||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't that just:
For the two others below as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I knew there had to be a better way. Thanks for pointing to filter(). I'm still getting used to rust iterators.