From 861393d211b4a588bea0c398ad1179e7300bb441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20St=C3=B6rzbach?= Date: Sat, 25 Jan 2025 20:55:50 +0100 Subject: [PATCH 1/2] fix: fix that bat 2 is connected in ground servicing mode --- .../src/electrical/alternating_current.rs | 5 +- .../src/electrical/direct_current.rs | 2 +- .../a380_systems/src/electrical/mod.rs | 56 ++++++++++++++++++- .../battery_charge_rectifier_unit.rs | 11 +++- 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/alternating_current.rs b/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/alternating_current.rs index 796c0f63370..78429774bd6 100644 --- a/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/alternating_current.rs +++ b/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/alternating_current.rs @@ -237,8 +237,9 @@ impl A380AlternatingCurrentElectricalSystem for A380AlternatingCurrentElectrical &self.tr_apu } - fn tr_2_powered_by_ac_bus(&self) -> bool { - self.ac_bus_3_to_tr_2_contactor.is_closed() + fn ground_servicing_active(&self) -> bool { + self.ext_pwr_to_ac_gnd_flt_service_bus_and_tr_2_contactor + .is_closed() } fn power_tr_1(&self, electricity: &mut Electricity, tr: &impl ElectricalElement) { diff --git a/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/direct_current.rs b/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/direct_current.rs index 89a0880d28c..305f9dc0d05 100644 --- a/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/direct_current.rs +++ b/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/direct_current.rs @@ -157,7 +157,7 @@ impl A380DirectCurrentElectrical { &self.battery_2, &mut self.tr_2_contactor, &self.dc_bus_2, - !ac_state.tr_2_powered_by_ac_bus(), + ac_state.ground_servicing_active(), ), ( &mut self.tr_ess, diff --git a/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/mod.rs b/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/mod.rs index d7c98463fad..6ce1c0da9c7 100644 --- a/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/mod.rs +++ b/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/mod.rs @@ -325,7 +325,7 @@ trait A380AlternatingCurrentElectricalSystem: AlternatingCurrentElectricalSystem fn ac_bus_powered(&self, electricity: &Electricity, number: usize) -> bool; fn ac_ess_bus_powered(&self, electricity: &Electricity) -> bool; fn tr_apu(&self) -> &TransformerRectifier; - fn tr_2_powered_by_ac_bus(&self) -> bool; + fn ground_servicing_active(&self) -> bool; fn power_tr_1(&self, electricity: &mut Electricity, tr: &impl ElectricalElement); fn power_tr_2(&self, electricity: &mut Electricity, tr: &impl ElectricalElement); fn power_tr_ess(&self, electricity: &mut Electricity, tr: &impl ElectricalElement); @@ -715,6 +715,60 @@ mod a380_electrical_circuit_tests { .is_single(PotentialOrigin::TransformerRectifier(2))); } + #[test] + fn distribution_batteries_only_with_ext_power_connected() { + let test_bed = test_bed_with() + .all_bats_auto() + .connected_external_power() + .on_the_ground() + .and() + .airspeed(Velocity::default()) + .run(); + + for i in 1..=4 { + assert!(test_bed.ac_bus_output(i).is_unpowered()); + } + assert!(test_bed + .ac_ess_bus_output() + .is_single(PotentialOrigin::StaticInverter)); + assert!(test_bed.ac_ess_shed_bus_output().is_unpowered()); + assert!(test_bed.ac_eha_bus_output().is_unpowered()); + assert!(test_bed + .static_inverter_input() + .is_pair(PotentialOrigin::Battery(1), PotentialOrigin::Battery(3))); + assert!(test_bed + .ac_gnd_flt_service_bus_output() + .is_single(PotentialOrigin::External)); + assert!(test_bed.tr_1_input().is_unpowered()); + assert!(test_bed.tr_2_input().is_single(PotentialOrigin::External)); + assert!(test_bed.tr_ess_input().is_unpowered()); + assert!(test_bed.tr_apu_input().is_unpowered()); + assert!(test_bed.dc_bus_output(1).is_unpowered()); + assert!(test_bed.dc_bus_output(2).is_unpowered()); + assert!(test_bed + .dc_ess_bus_output() + .is_pair(PotentialOrigin::Battery(1), PotentialOrigin::Battery(3))); + assert!(test_bed.dc_eha_bus_output().is_unpowered()); + assert!(test_bed + .dc_apu_bus_output() + .is_single(PotentialOrigin::Battery(4))); + assert!(test_bed + .hot_bus_output(1) + .is_pair(PotentialOrigin::Battery(1), PotentialOrigin::Battery(3))); + assert!(test_bed + .hot_bus_output(2) + .is_single(PotentialOrigin::Battery(2))); + assert!(test_bed + .hot_bus_output(3) + .is_pair(PotentialOrigin::Battery(1), PotentialOrigin::Battery(3))); + assert!(test_bed + .hot_bus_output(4) + .is_single(PotentialOrigin::Battery(4))); + assert!(test_bed + .dc_gnd_flt_service_bus_output() + .is_single(PotentialOrigin::TransformerRectifier(2))); + } + /// # Source /// A380 FCOM #[test] diff --git a/fbw-common/src/wasm/systems/systems/src/electrical/battery_charge_rectifier_unit.rs b/fbw-common/src/wasm/systems/systems/src/electrical/battery_charge_rectifier_unit.rs index 32a74ea8e8e..c61fb506047 100644 --- a/fbw-common/src/wasm/systems/systems/src/electrical/battery_charge_rectifier_unit.rs +++ b/fbw-common/src/wasm/systems/systems/src/electrical/battery_charge_rectifier_unit.rs @@ -28,6 +28,7 @@ pub struct BatteryChargeRectifierUnit { battery_pb_is_auto: bool, backup_is_powered: bool, contactor_closed: bool, + ground_servicing: bool, loss_of_ac_duration: Duration, overcurrent_duration: Duration, failed_time: Duration, @@ -54,6 +55,7 @@ impl BatteryChargeRectifierUnit { battery_pb_is_auto: false, backup_is_powered: false, contactor_closed: false, + ground_servicing: false, loss_of_ac_duration: Duration::default(), overcurrent_duration: Duration::default(), failed_time: Duration::default(), @@ -72,7 +74,7 @@ impl BatteryChargeRectifierUnit { self.battery_pb_is_auto = battery_push_buttons.bat_is_auto(self.number); let ac_bus_powered = electricity.is_powered(self); - self.loss_of_ac_duration = if ac_bus_powered { + self.loss_of_ac_duration = if ac_bus_powered || self.ground_servicing && !ground_servicing { Duration::default() } else { self.loss_of_ac_duration + context.delta() @@ -88,9 +90,11 @@ impl BatteryChargeRectifierUnit { Duration::default() }; + self.ground_servicing = ground_servicing; self.contactor_closed = !ground_servicing && (ac_bus_powered || self.contactor_closed && self.loss_of_ac_duration < Duration::from_secs(3)); + self.ground_service_contactor_closed = ground_servicing && ac_bus_powered; // The battery contactor opens when the battery SOC < 20% self.battery_soc_20 = battery.potential().get::() < 24.5; @@ -101,6 +105,7 @@ impl BatteryChargeRectifierUnit { self.battery_pb_is_auto, emergency_config, self.loss_of_ac_duration, + self.ground_servicing, ); } @@ -222,6 +227,7 @@ impl State { battery_is_auto: bool, emergency_config: bool, loss_of_ac_duration: Duration, + ground_servicing: bool, ) -> Self { match self { Self::BatOff => { @@ -232,7 +238,7 @@ impl State { } } Self::Open => { - if emergency_config { + if emergency_config || ground_servicing { Self::Open } else if !battery_is_auto { Self::BatOff @@ -244,6 +250,7 @@ impl State { } Self::Closed => { if emergency_config + || ground_servicing || loss_of_ac_duration >= Self::OPEN_BAT_LC_AFTER_AC_LOST_DURATION { Self::Open From 68e89fe71f00f97c8efee26a4647ec0ec72a3ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20St=C3=B6rzbach?= Date: Sat, 25 Jan 2025 21:02:01 +0100 Subject: [PATCH 2/2] fix: move ground service contactor control to BCRU --- .../a380_systems/src/electrical/direct_current.rs | 10 ++++++---- .../src/electrical/battery_charge_rectifier_unit.rs | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/direct_current.rs b/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/direct_current.rs index 305f9dc0d05..891346caeb8 100644 --- a/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/direct_current.rs +++ b/fbw-a380x/src/wasm/systems/a380_systems/src/electrical/direct_current.rs @@ -291,11 +291,13 @@ impl A380DirectCurrentElectrical { electricity.flow(&self.dc_bus_2_to_dc_eha_contactor, &self.dc_eha_bus); electricity.flow(&self.inter_bus_line_ess_contactor, &self.dc_eha_bus); - self.tr_2_to_dc_gnd_flt_service_bus_contactor.close_when( - electricity.is_powered(&self.tr_2) && !electricity.is_powered(&self.dc_bus_2), - ); + self.tr_2_to_dc_gnd_flt_service_bus_contactor + .close_when(self.tr_2.should_close_ground_service_line_contactor()); self.dc_bus_2_to_dc_gnd_flt_service_bus_contactor - .close_when(electricity.is_powered(&self.dc_bus_2)); + .close_when( + electricity.is_powered(&self.dc_bus_2) + && self.tr_2_to_dc_gnd_flt_service_bus_contactor.is_open(), + ); electricity.flow(&self.tr_2, &self.tr_2_to_dc_gnd_flt_service_bus_contactor); electricity.flow( &self.dc_bus_2, diff --git a/fbw-common/src/wasm/systems/systems/src/electrical/battery_charge_rectifier_unit.rs b/fbw-common/src/wasm/systems/systems/src/electrical/battery_charge_rectifier_unit.rs index c61fb506047..5f4493da709 100644 --- a/fbw-common/src/wasm/systems/systems/src/electrical/battery_charge_rectifier_unit.rs +++ b/fbw-common/src/wasm/systems/systems/src/electrical/battery_charge_rectifier_unit.rs @@ -28,6 +28,7 @@ pub struct BatteryChargeRectifierUnit { battery_pb_is_auto: bool, backup_is_powered: bool, contactor_closed: bool, + ground_service_contactor_closed: bool, ground_servicing: bool, loss_of_ac_duration: Duration, overcurrent_duration: Duration, @@ -55,6 +56,7 @@ impl BatteryChargeRectifierUnit { battery_pb_is_auto: false, backup_is_powered: false, contactor_closed: false, + ground_service_contactor_closed: false, ground_servicing: false, loss_of_ac_duration: Duration::default(), overcurrent_duration: Duration::default(), @@ -113,6 +115,10 @@ impl BatteryChargeRectifierUnit { self.contactor_closed } + pub fn should_close_ground_service_line_contactor(&self) -> bool { + self.ground_service_contactor_closed + } + pub fn should_close_battery_connector(&self) -> bool { self.state.should_close_battery_connector() }