diff --git a/fbw-a32nx/src/systems/instruments/src/SD/Pages/Press/Press.tsx b/fbw-a32nx/src/systems/instruments/src/SD/Pages/Press/Press.tsx
index 14f20746014..e69ad36c16e 100644
--- a/fbw-a32nx/src/systems/instruments/src/SD/Pages/Press/Press.tsx
+++ b/fbw-a32nx/src/systems/instruments/src/SD/Pages/Press/Press.tsx
@@ -54,6 +54,10 @@ export const PressPage: FC = () => {
}, [cabinAlt]);
const deltaPress = splitDecimals(MathUtils.clamp(deltaPsi, -9.9, 9.9));
+ // TODO: SDAC logic missing. Delta pressure is not available when the SDAC indication is not valid.
+ // This happens when both the CPCs and ADRs are not sending pressure information. Here we only check
+ // for CPC no computed data.
+ const deltaPressNotAvail = arincDeltaPsi.isNoComputedData();
const cax = 455;
const dpx = 110;
const y = 165;
@@ -77,19 +81,30 @@ export const PressPage: FC = () => {
PSI
- = 8.5 ? 'Amber' : 'Green'}`} x={dpx + 38} y={y + 25}>
+ = 8.5 ? 'Amber' : 'Green'} ${deltaPressNotAvail ? 'hide' : 'show'}`}
+ x={dpx + 38}
+ y={y + 25}
+ >
{deltaPress[0]}
- = 8.5 ? 'Amber' : 'Green'}`} x={dpx + 53} y={y + 25}>
+ = 8.5 ? 'Amber' : 'Green'} ${deltaPressNotAvail ? 'hide' : 'show'}`}
+ x={dpx + 53}
+ y={y + 25}
+ >
.
= 8.5 ? 'Amber' : 'Green'}`}
+ className={`Standard End ${deltaPsi < -0.4 || deltaPsi >= 8.5 ? 'Amber' : 'Green'} ${deltaPressNotAvail ? 'hide' : 'show'}`}
x={dpx + 63}
y={y + 25}
>
{deltaPress[1]}
+
+ XX
+
{
radius={radius}
startAngle={210}
endAngle={50}
- className={`GaugeIndicator ${deltaPsi < -0.4 || deltaPsi >= 8.5 ? 'Amber' : ''}`}
+ className={`GaugeIndicator ${deltaPsi < -0.4 || deltaPsi >= 8.5 ? 'Amber' : ''} ${deltaPressNotAvail ? 'hide' : 'show'}`}
indicator
/>
diff --git a/fbw-a32nx/src/wasm/systems/a320_systems/src/air_conditioning.rs b/fbw-a32nx/src/wasm/systems/a320_systems/src/air_conditioning.rs
index 8a807fc97da..c210bb4bf4a 100644
--- a/fbw-a32nx/src/wasm/systems/a320_systems/src/air_conditioning.rs
+++ b/fbw-a32nx/src/wasm/systems/a320_systems/src/air_conditioning.rs
@@ -4,7 +4,7 @@ use systems::{
acs_controller::{AcscId, AirConditioningSystemController, Pack},
cabin_air::CabinAirSimulation,
cabin_pressure_controller::{CabinPressureController, CpcId},
- pressure_valve::{OutflowValve, SafetyValve},
+ pressure_valve::{OutflowValve, SafetyValve, SafetyValveSignal},
AdirsToAirCondInterface, Air, AirConditioningOverheadShared, AirConditioningPack, CabinFan,
Channel, DuctTemperature, MixerUnit, OutflowValveSignal, OutletAir, OverheadFlowSelector,
PackFlowControllers, PressurizationConstants, PressurizationOverheadShared, TrimAirSystem,
@@ -696,6 +696,7 @@ struct A320PressurizationSystem {
cpc_interface: [PressurizationSystemInterfaceUnit; 2],
outflow_valve: [OutflowValve; 1], // Array to prepare for more than 1 outflow valve in A380
safety_valve: SafetyValve,
+ safety_valve_signal: SafetyValveSignal,
residual_pressure_controller: ResidualPressureController,
active_system: usize,
@@ -725,6 +726,7 @@ impl A320PressurizationSystem {
vec![ElectricalBusType::DirectCurrentBattery],
)],
safety_valve: SafetyValve::new(),
+ safety_valve_signal: SafetyValveSignal::new(),
residual_pressure_controller: ResidualPressureController::new(),
active_system: active as usize,
@@ -794,8 +796,12 @@ impl A320PressurizationSystem {
});
}
- self.safety_valve
- .update(context, &self.cpc[self.active_system - 1]);
+ self.safety_valve_signal.update(
+ context,
+ cabin_simulation.cabin_pressure(),
+ self.safety_valve.open_amount(),
+ );
+ self.safety_valve.update(context, &self.safety_valve_signal);
self.switch_active_system();
@@ -2628,7 +2634,7 @@ mod tests {
InternationalStandardAtmosphere::pressure_at_altitude(Length::default())
- Pressure::new::(10.),
)
- .iterate(10);
+ .iterate(2);
assert!(test_bed.safety_valve_open_amount() > Ratio::default());
}
diff --git a/fbw-a380x/src/wasm/systems/a380_systems/src/air_conditioning/local_controllers/outflow_valve_control_module.rs b/fbw-a380x/src/wasm/systems/a380_systems/src/air_conditioning/local_controllers/outflow_valve_control_module.rs
index c77b1bff707..0b4233ba99f 100644
--- a/fbw-a380x/src/wasm/systems/a380_systems/src/air_conditioning/local_controllers/outflow_valve_control_module.rs
+++ b/fbw-a380x/src/wasm/systems/a380_systems/src/air_conditioning/local_controllers/outflow_valve_control_module.rs
@@ -1,12 +1,11 @@
use systems::{
air_conditioning::{
- cabin_pressure_controller::OutflowValveController,
- pressure_valve::{OutflowValve, PressureValveSignal},
+ cabin_pressure_controller::OutflowValveController, pressure_valve::OutflowValve,
AdirsToAirCondInterface, Air, OperatingChannel, PressurizationConstants,
PressurizationOverheadShared,
},
shared::{
- low_pass_filter::LowPassFilter, CabinSimulation, ControllerSignal, ElectricalBusType,
+ low_pass_filter::LowPassFilter, CabinSimulation, ElectricalBusType,
InternationalStandardAtmosphere,
},
simulation::{
@@ -21,7 +20,6 @@ use uom::si::{
f64::*,
length::foot,
pressure::{hectopascal, psi},
- ratio::percent,
velocity::foot_per_minute,
};
@@ -139,10 +137,6 @@ impl OutflowValveControlModule {
fn switch_active_channel(&mut self) {
std::mem::swap(&mut self.stand_by_channel, &mut self.active_channel);
}
-
- pub fn negative_relief_valve_trigger(&self) -> &impl ControllerSignal {
- &self.epp
- }
}
impl OcsmShared for OutflowValveControlModule {
@@ -449,32 +443,3 @@ impl EmergencyPressurizationPartition {
&self.outflow_valve_controller
}
}
-
-/// Negative relieve valves signal. This returns a controller signal, but the valves are mechanical assemblies
-impl ControllerSignal for EmergencyPressurizationPartition {
- fn signal(&self) -> Option {
- let open = Some(PressureValveSignal::Open(
- Ratio::new::(100.),
- Duration::from_secs(1),
- ));
- let closed = Some(PressureValveSignal::Close(
- Ratio::new::(0.),
- Duration::from_secs(1),
- ));
- if self.differential_pressure.get::()
- < A380PressurizationConstants::MIN_SAFETY_DELTA_P + 0.2
- {
- if self.differential_pressure.get::()
- < A380PressurizationConstants::MIN_SAFETY_DELTA_P
- {
- open
- } else {
- Some(PressureValveSignal::Neutral)
- }
- } else if self.safety_valve_open_amount.get::() > 0. {
- closed
- } else {
- Some(PressureValveSignal::Neutral)
- }
- }
-}
diff --git a/fbw-a380x/src/wasm/systems/a380_systems/src/air_conditioning/mod.rs b/fbw-a380x/src/wasm/systems/a380_systems/src/air_conditioning/mod.rs
index 7ee26151b3f..f1427bcc236 100644
--- a/fbw-a380x/src/wasm/systems/a380_systems/src/air_conditioning/mod.rs
+++ b/fbw-a380x/src/wasm/systems/a380_systems/src/air_conditioning/mod.rs
@@ -1,7 +1,9 @@
use systems::{
accept_iterable,
air_conditioning::{
- acs_controller::Pack, cabin_air::CabinAirSimulation, pressure_valve::SafetyValve,
+ acs_controller::Pack,
+ cabin_air::CabinAirSimulation,
+ pressure_valve::{NegativeRelieveValveSignal, SafetyValve},
AdirsToAirCondInterface, Air, AirConditioningOverheadShared, AirConditioningPack,
AirHeater, CabinFan, DuctTemperature, MixerUnit, OutletAir, OverheadFlowSelector, PackFlow,
PackFlowControllers, PressurizationConstants, PressurizationOverheadShared, TrimAirSystem,
@@ -861,6 +863,7 @@ struct A380PressurizationSystem {
negative_relief_valves_id: VariableIdentifier,
negative_relief_valves: SafetyValve,
+ negative_relief_valves_signal: NegativeRelieveValveSignal,
}
impl A380PressurizationSystem {
@@ -904,6 +907,7 @@ impl A380PressurizationSystem {
negative_relief_valves_id: context
.get_identifier("PRESS_SAFETY_VALVE_OPEN_PERCENTAGE".to_owned()),
negative_relief_valves: SafetyValve::new(),
+ negative_relief_valves_signal: NegativeRelieveValveSignal::new(),
}
}
@@ -926,9 +930,14 @@ impl A380PressurizationSystem {
);
}
+ self.negative_relief_valves_signal.update(
+ context,
+ cabin_simulation.cabin_pressure(),
+ self.negative_relief_valves.open_amount(),
+ );
// TODO Add check for failure
self.negative_relief_valves
- .update(context, self.ocsm[0].negative_relief_valve_trigger());
+ .update(context, &self.negative_relief_valves_signal);
}
fn safety_valve_open_amount(&self) -> Ratio {
diff --git a/fbw-common/src/wasm/systems/systems/src/air_conditioning/cabin_pressure_controller.rs b/fbw-common/src/wasm/systems/systems/src/air_conditioning/cabin_pressure_controller.rs
index 6526e275782..a0c2ad6c007 100644
--- a/fbw-common/src/wasm/systems/systems/src/air_conditioning/cabin_pressure_controller.rs
+++ b/fbw-common/src/wasm/systems/systems/src/air_conditioning/cabin_pressure_controller.rs
@@ -13,8 +13,8 @@ use crate::{
};
use super::{
- pressure_valve::{OutflowValve, PressureValveSignal, SafetyValve},
- AdirsToAirCondInterface, OutflowValveSignal, PressurizationConstants,
+ pressure_valve::{OutflowValve, SafetyValve},
+ AdirsToAirCondInterface, Air, OutflowValveSignal, PressurizationConstants,
PressurizationOverheadShared,
};
@@ -56,6 +56,7 @@ pub struct CabinPressureController {
pressure_schedule_manager: Option,
manual_partition: Option,
outflow_valve_controller: OutflowValveController,
+ adirs_data_is_valid: bool,
exterior_pressure: LowPassFilter,
exterior_flight_altitude: Length,
exterior_vertical_speed: LowPassFilter,
@@ -124,6 +125,7 @@ impl CabinPressureController {
Self::OFV_CONTROLLER_KP,
Self::OFV_CONTROLLER_KI,
),
+ adirs_data_is_valid: false,
exterior_pressure: LowPassFilter::new_with_init_value(
Self::AMBIENT_CONDITIONS_FILTER_TIME_CONSTANT,
Pressure::new::(Self::P_0),
@@ -172,6 +174,9 @@ impl CabinPressureController {
safety_valve: &SafetyValve,
is_active: bool,
) {
+ self.adirs_data_is_valid = [1, 2, 3]
+ .iter()
+ .any(|&adr| adirs.ambient_static_pressure(adr).is_normal_operation());
let (adirs_airspeed, _) = self.adirs_values_calculation(adirs);
self.cabin_pressure = cabin_simulation.cabin_pressure();
@@ -255,9 +260,9 @@ impl CabinPressureController {
let (_, adirs_ambient_pressure) = self.adirs_values_calculation(adirs);
let new_exterior_altitude: Length;
- if !self.is_initialised {
+ if !self.is_initialised && adirs_ambient_pressure.is_some() {
self.exterior_pressure.reset(
- adirs_ambient_pressure.unwrap_or_else(|| Pressure::new::(Self::P_0)),
+ adirs_ambient_pressure.unwrap_or_else(|| Pressure::new::(Air::P_0)),
);
new_exterior_altitude =
self.calculate_altitude(self.exterior_pressure.output(), self.reference_pressure);
@@ -265,7 +270,7 @@ impl CabinPressureController {
} else {
self.exterior_pressure.update(
context.delta(),
- adirs_ambient_pressure.unwrap_or_else(|| Pressure::new::(Self::P_0)),
+ adirs_ambient_pressure.unwrap_or_else(|| Pressure::new::(Air::P_0)),
);
new_exterior_altitude =
@@ -641,39 +646,6 @@ impl ControllerSignal
}
}
-// Safety valve signal
-impl ControllerSignal
- for CabinPressureController
-{
- fn signal(&self) -> Option {
- let open = Some(PressureValveSignal::Open(
- Ratio::new::(100.),
- Duration::from_secs(1),
- ));
- let closed = Some(PressureValveSignal::Close(
- Ratio::new::(0.),
- Duration::from_secs(1),
- ));
- if self.cabin_delta_p() > Pressure::new::(8.1) {
- if self.cabin_delta_p() > Pressure::new::(8.6) {
- open
- } else {
- Some(PressureValveSignal::Neutral)
- }
- } else if self.cabin_delta_p() < Pressure::new::(-0.5) {
- if self.cabin_delta_p() < Pressure::new::(-1.) {
- open
- } else {
- Some(PressureValveSignal::Neutral)
- }
- } else if self.safety_valve_open_amount > Ratio::new::(0.) {
- closed
- } else {
- Some(PressureValveSignal::Neutral)
- }
- }
-}
-
impl SimulationElement for CabinPressureController {
fn write(&self, writer: &mut SimulatorWriter) {
let ssm = if self.failure.is_active() {
@@ -682,13 +654,26 @@ impl SimulationElement for CabinPressureController {
+ ambient_pressure: Pressure,
+ cabin_pressure: Pressure,
+ safety_valve_open_amount: Ratio,
+
+ constants: PhantomData,
+}
+
+impl SafetyValveSignal {
+ pub fn new() -> Self {
+ Self {
+ ambient_pressure: Pressure::new::(Air::P_0),
+ cabin_pressure: Pressure::new::(Air::P_0),
+ safety_valve_open_amount: Ratio::default(),
+
+ constants: PhantomData,
+ }
+ }
+
+ pub fn update(
+ &mut self,
+ context: &UpdateContext,
+ cabin_pressure: Pressure,
+ safety_valve_open_amount: Ratio,
+ ) {
+ self.ambient_pressure = context.ambient_pressure();
+ self.cabin_pressure = cabin_pressure;
+ self.safety_valve_open_amount = safety_valve_open_amount;
+ }
+}
+
+// Safety valve signal
+impl ControllerSignal for SafetyValveSignal {
+ fn signal(&self) -> Option {
+ let cabin_delta_p = self.cabin_pressure - self.ambient_pressure;
+ let open = Some(PressureValveSignal::Open(
+ Ratio::new::(100.),
+ Duration::from_secs(1),
+ ));
+ let closed = Some(PressureValveSignal::Close(
+ Ratio::new::(0.),
+ Duration::from_secs(1),
+ ));
+ if cabin_delta_p.get::() > C::MAX_SAFETY_DELTA_P {
+ if cabin_delta_p.get::() > C::MAX_SAFETY_DELTA_P + 0.5 {
+ open
+ } else {
+ Some(PressureValveSignal::Neutral)
+ }
+ } else if cabin_delta_p.get::() < C::MIN_SAFETY_DELTA_P {
+ if cabin_delta_p.get::() < C::MIN_SAFETY_DELTA_P - 0.5 {
+ open
+ } else {
+ Some(PressureValveSignal::Neutral)
+ }
+ } else if self.safety_valve_open_amount > Ratio::default() {
+ closed
+ } else {
+ Some(PressureValveSignal::Neutral)
+ }
+ }
+}
+
+impl Default for SafetyValveSignal {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+pub struct NegativeRelieveValveSignal {
+ ambient_pressure: Pressure,
+ cabin_pressure: Pressure,
+ safety_valve_open_amount: Ratio,
+
+ constants: PhantomData,
+}
+
+impl NegativeRelieveValveSignal {
+ pub fn new() -> Self {
+ Self {
+ ambient_pressure: Pressure::new::(Air::P_0),
+ cabin_pressure: Pressure::new::(Air::P_0),
+ safety_valve_open_amount: Ratio::default(),
+
+ constants: PhantomData,
+ }
+ }
+
+ pub fn update(
+ &mut self,
+ context: &UpdateContext,
+ cabin_pressure: Pressure,
+ safety_valve_open_amount: Ratio,
+ ) {
+ self.ambient_pressure = context.ambient_pressure();
+ self.cabin_pressure = cabin_pressure;
+ self.safety_valve_open_amount = safety_valve_open_amount;
+ }
+}
+
+// Negative relieve valves signal
+impl ControllerSignal
+ for NegativeRelieveValveSignal
+{
+ fn signal(&self) -> Option {
+ let cabin_delta_p = self.cabin_pressure - self.ambient_pressure;
+ let open = Some(PressureValveSignal::Open(
+ Ratio::new::(100.),
+ Duration::from_secs(1),
+ ));
+ let closed = Some(PressureValveSignal::Close(
+ Ratio::new::(0.),
+ Duration::from_secs(1),
+ ));
+ if cabin_delta_p.get::() < C::MIN_SAFETY_DELTA_P + 0.2 {
+ if cabin_delta_p.get::() < C::MIN_SAFETY_DELTA_P {
+ open
+ } else {
+ Some(PressureValveSignal::Neutral)
+ }
+ } else if self.safety_valve_open_amount.get::() > 0. {
+ closed
+ } else {
+ Some(PressureValveSignal::Neutral)
+ }
+ }
+}
+
+impl Default for NegativeRelieveValveSignal {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
pub struct PressureValve {
open_amount: Ratio,
}