Skip to content

Commit

Permalink
feat(elec): a380 electrical improvements (#9683)
Browse files Browse the repository at this point in the history
* feat(elec): more accurate simulation of BCRU behavior

* feat: add missing EBHA for spoiler 5

* fix ac gnd service bus

* fix tests

* fix battery voltage indicator battery mapping

* Revert "feat: add missing EBHA for spoiler 5"

This reverts commit a7dbce2.

* add changelog
  • Loading branch information
Gurgel100 authored Jan 18, 2025
1 parent ce500c1 commit c837ab1
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 59 deletions.
1 change: 1 addition & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
1. [A380X/MFD] Add leading zero to altitude prediction and track from last waypoint on FPLN page - @bulenteroglu (senolitam)
1. [FMS] Improved nav database error handling, preserving as much valid data as possible - @tracernz (Mike)
1. [A32NX/FMS] Sort instrument procedures for display on the MCDU - @tracernz (Mike)
1. [A380X/ELEC] Various fixes in the electrical system (battery voltage indicator switchup, AC GND SVC BUS and correct behavior of battery contactors) - @Gurgel100 (Pascal)

## 0.12.0

Expand Down
2 changes: 1 addition & 1 deletion fbw-a380x/docs/a380-simvars.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
- Number
- The position of the battery display knob from left to right
- ESS=0, APU=1, OFF=2, BAT1=3, BAT2=4
- Mapped to battery voltage indexes: {bat_index} = ESS=4 | APU=3 | OFF=0 | BAT1=1 | BAT2=2
- Mapped to battery voltage indexes: {bat_index} = ESS=3 | APU=4 | OFF=0 | BAT1=1 | BAT2=2
- A32NX_ELEC_BAT_{bat_index}_POTENTIAL is used to get the voltage

- A32NX_NOSE_WHEEL_LEFT_ANIM_ANGLE
Expand Down
2 changes: 1 addition & 1 deletion fbw-a380x/src/systems/instruments/src/BAT/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const BatRoot = () => {
}

// mapping of knob (lvar) values to battery numbers to allow easy lvar and model values
const batteryMap = [4, 3, 0, 1, 2]; // ESS, APU, OFF, BAT1, BAT2
const batteryMap = [3, 4, 0, 1, 2]; // ESS, APU, OFF, BAT1, BAT2

return (
<svg className={`bat-svg${selectedBattery == 2 ? ' off' : ''}`} viewBox="0 0 200 100">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ impl A380AlternatingCurrentElectrical {
&self.ext_pwr_to_ac_gnd_flt_service_bus_and_tr_2_contactor,
);
electricity.flow(&self.ac_bus_3_to_tr_2_contactor, &self.ac_buses[2]);
electricity.flow(
&self.ac_bus_3_to_tr_2_contactor,
&self.ac_gnd_flt_service_bus,
);
electricity.flow(
&self.ext_pwr_to_ac_gnd_flt_service_bus_and_tr_2_contactor,
&self.ac_gnd_flt_service_bus,
Expand Down Expand Up @@ -276,6 +280,11 @@ impl SimulationElement for A380AlternatingCurrentElectrical {
self.ac_emer_bus.accept(visitor);
self.ac_eha_bus.accept(visitor);

self.ac_bus_3_to_tr_2_contactor.accept(visitor);
self.ext_pwr_to_ac_gnd_flt_service_bus_and_tr_2_contactor
.accept(visitor);
self.ac_gnd_flt_service_bus.accept(visitor);

visitor.visit(self);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,16 @@ impl A380DirectCurrentElectrical {
tr_1: BatteryChargeRectifierUnit::new(
context,
1,
ElectricalBusType::DirectCurrent(1),
ElectricalBusType::DirectCurrentHot(1),
),
tr_2: BatteryChargeRectifierUnit::new(
context,
2,
ElectricalBusType::DirectCurrent(2),
ElectricalBusType::DirectCurrentHot(2),
),
tr_ess: BatteryChargeRectifierUnit::new(
context,
3,
ElectricalBusType::DirectCurrentEssential,
ElectricalBusType::DirectCurrentHot(3),
),
tr_1_contactor: Contactor::new(context, "990PU1"),
Expand Down Expand Up @@ -214,7 +211,7 @@ impl A380DirectCurrentElectrical {
&& !self.tr_1.battery_nearly_empty()
&& !ac_state.any_non_essential_bus_powered(electricity)
|| rat.should_deploy();
self.tr_1.update(electricity, should_close_elc, false);
self.tr_1.update(should_close_elc);
self.battery_1_contactor
.close_when(self.tr_1.should_close_battery_connector());
self.battery_1_emergency_contactor
Expand All @@ -226,20 +223,27 @@ impl A380DirectCurrentElectrical {
electricity.flow(&self.battery_1_emergency_contactor, &self.dc_ess_bus);

electricity.supplied_by(&self.battery_2);
self.tr_2.update(electricity, false, false);
self.tr_2.update(false);
self.battery_2_contactor
.close_when(self.tr_2.should_close_battery_connector());
electricity.flow(&self.battery_2_contactor, &self.battery_2);
electricity.flow(&self.hot_bus_2, &self.battery_2);
electricity.flow(&self.battery_2_contactor, &self.dc_bus_2);

// TODO: should not close when battery failed (signal from BCRU)
// TODO: complete logic
let should_close_ess_bat_lc = overhead.bat_is_auto(1)
&& overhead.bat_is_auto(3)
&& !self.tr_ess.battery_nearly_empty()
&& !ac_state.any_non_essential_bus_powered(electricity)
|| rat.should_deploy();
let emergency_config = !electricity.is_powered(&self.dc_bus_1)
&& emergency_config.is_active()
|| rat.should_deploy();
electricity.supplied_by(&self.battery_ess);
self.tr_ess.update(electricity, false, emergency_config);
self.tr_ess.update(emergency_config);
self.battery_ess_contactor
.close_when(self.tr_ess.should_close_battery_connector());
.close_when(self.tr_ess.should_close_battery_connector() || should_close_ess_bat_lc);
electricity.flow(&self.battery_ess_contactor, &self.battery_ess);
electricity.flow(&self.hot_bus_ess, &self.battery_ess);
electricity.flow(&self.battery_ess_contactor, &self.dc_ess_bus);
Expand Down
98 changes: 71 additions & 27 deletions fbw-a380x/src/wasm/systems/a380_systems/src/electrical/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::ApuGenerator(2)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::ApuGenerator(2)));
assert!(test_bed.tr_1_input().is_single(PotentialOrigin::External));
assert!(test_bed
.tr_2_input()
Expand Down Expand Up @@ -942,7 +944,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::External));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::External));
assert!(test_bed.tr_1_input().is_single(PotentialOrigin::External));
assert!(test_bed.tr_2_input().is_single(PotentialOrigin::External));
assert!(test_bed.tr_ess_input().is_single(PotentialOrigin::External));
Expand Down Expand Up @@ -1016,7 +1020,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::External));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::External));
assert!(test_bed.tr_1_input().is_single(PotentialOrigin::External));
assert!(test_bed.tr_2_input().is_single(PotentialOrigin::External));
assert!(test_bed
Expand Down Expand Up @@ -1091,7 +1097,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::ApuGenerator(2)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::ApuGenerator(2)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::ApuGenerator(1)));
Expand Down Expand Up @@ -1171,7 +1179,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::ApuGenerator(2)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::ApuGenerator(2)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::ApuGenerator(1)));
Expand Down Expand Up @@ -1253,7 +1263,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::External));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::External));
assert!(test_bed.tr_1_input().is_single(PotentialOrigin::External));
assert!(test_bed.tr_2_input().is_single(PotentialOrigin::External));
assert!(test_bed
Expand Down Expand Up @@ -1321,7 +1333,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::ApuGenerator(2)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::ApuGenerator(2)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::ApuGenerator(2)));
Expand Down Expand Up @@ -1397,7 +1411,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(4)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(4)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::ApuGenerator(1)));
Expand Down Expand Up @@ -1467,7 +1483,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -1546,7 +1564,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -1624,7 +1644,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(3)));
Expand Down Expand Up @@ -1702,7 +1724,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -1781,7 +1805,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::ApuGenerator(1)));
Expand Down Expand Up @@ -1861,7 +1887,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::ApuGenerator(1)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::ApuGenerator(1)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -1930,7 +1958,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.tr_1_input().is_unpowered());
assert!(test_bed
.tr_2_input()
Expand Down Expand Up @@ -1958,7 +1988,7 @@ mod a380_electrical_circuit_tests {
.is_single(PotentialOrigin::TransformerRectifier(4)));
assert!(test_bed
.hot_bus_output(1)
.is_single(PotentialOrigin::TransformerRectifier(2)));
.is_single(PotentialOrigin::Battery(1)));
assert!(test_bed
.hot_bus_output(2)
.is_single(PotentialOrigin::TransformerRectifier(2)));
Expand Down Expand Up @@ -2006,7 +2036,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::ApuGenerator(1)));
Expand Down Expand Up @@ -2188,7 +2220,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -2218,7 +2252,7 @@ mod a380_electrical_circuit_tests {
.is_single(PotentialOrigin::TransformerRectifier(4)));
assert!(test_bed
.hot_bus_output(1)
.is_single(PotentialOrigin::TransformerRectifier(2)));
.is_single(PotentialOrigin::Battery(1)));
assert!(test_bed
.hot_bus_output(2)
.is_single(PotentialOrigin::TransformerRectifier(2)));
Expand Down Expand Up @@ -2259,7 +2293,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -2292,7 +2328,7 @@ mod a380_electrical_circuit_tests {
.is_single(PotentialOrigin::TransformerRectifier(1)));
assert!(test_bed
.hot_bus_output(2)
.is_single(PotentialOrigin::TransformerRectifier(1)));
.is_single(PotentialOrigin::Battery(2)));
assert!(test_bed
.hot_bus_output(3)
.is_single(PotentialOrigin::TransformerRectifier(3)));
Expand Down Expand Up @@ -2330,7 +2366,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -2366,7 +2404,7 @@ mod a380_electrical_circuit_tests {
.is_single(PotentialOrigin::TransformerRectifier(2)));
assert!(test_bed
.hot_bus_output(3)
.is_single(PotentialOrigin::TransformerRectifier(1)));
.is_single(PotentialOrigin::Battery(3)));
assert!(test_bed
.hot_bus_output(4)
.is_single(PotentialOrigin::Battery(4)));
Expand Down Expand Up @@ -2399,7 +2437,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -2471,7 +2511,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -2537,7 +2579,9 @@ mod a380_electrical_circuit_tests {
.ac_eha_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed.static_inverter_input().is_unpowered());
assert!(test_bed.ac_gnd_flt_service_bus_output().is_unpowered());
assert!(test_bed
.ac_gnd_flt_service_bus_output()
.is_single(PotentialOrigin::EngineGenerator(3)));
assert!(test_bed
.tr_1_input()
.is_single(PotentialOrigin::EngineGenerator(2)));
Expand Down Expand Up @@ -2568,7 +2612,7 @@ mod a380_electrical_circuit_tests {
.is_single(PotentialOrigin::TransformerRectifier(1)));
assert!(test_bed
.hot_bus_output(2)
.is_single(PotentialOrigin::TransformerRectifier(1)));
.is_single(PotentialOrigin::Battery(2)));
assert!(test_bed
.hot_bus_output(3)
.is_single(PotentialOrigin::Battery(3)));
Expand Down
Loading

0 comments on commit c837ab1

Please sign in to comment.