Skip to content

Commit

Permalink
fix(a380x/fire): better engine fire response (#9109)
Browse files Browse the repository at this point in the history
* feat: better engine fire response

* Update fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx

Co-authored-by: Michael Corcoran <[email protected]>

* Update CHANGELOG.md
  • Loading branch information
mjuhe authored Nov 15, 2024
1 parent 0043ba0 commit 322ed63
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 34 deletions.
3 changes: 2 additions & 1 deletion .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
1. [A380X/AFS] Fixed CP V/S knob push levelling off the aircraft when it should have no action - @tracernz (Mike)
1. [A380X/MFD] MFD/SURV: Fixed TCAS not switching status when using DEFAULT SETTINGS button - @flogross89 (floridude)
1. [A380X/FUEL] Recalibrated inital fuel settings - @sschiphorst (Yahtzee94)
1. [A380X/ENGINES] Another adjustment to taxi thrust - @donstim (donbikes)
1. [A380X/ENG] Another adjustment to taxi thrust - @donstim (donbikes)
1. [A380X/ANIM] Animation of flaps now from FPPU position. Interim fix for spoiler low end animation - @Crocket63 (crocket)
1. [A380X/ENG] Improve oil pressure lookup table - @tracernz (Mike)
1. [A380X/WING_FLEX] Reduced stiffness of wings for more tip up bend - @Crocket63 (crocket)
Expand All @@ -55,6 +55,7 @@
1. [A380X/PFD] Fix CP VV button turning on VV on both PFDs - @heclak (Heclak)
1. [A380X/FMS] Fixed handling of window altitude constraints, deletion of constraints, and formatting - @tracernz (Mike)
1. [A380X/SD] Fix engine fuel flow and fuel used on cruise page still use only ENG 1 + 2 LVars @heclak (heclak)
1. [A380X/ENG] Improved engine fire behaviour - overhead fire pushbuttons silence aural warning and unpowers FADEC - @mjuhe (Miquel Juhe)

## 0.12.0

Expand Down
37 changes: 33 additions & 4 deletions fbw-a380x/src/systems/instruments/src/EWD/EWD.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus

private readonly abnormalSensedVisible = ConsumerSubject.create(null, false);

// Todo: This logic should be handled by the FADEC
private readonly engFirePb: ConsumerSubject<boolean>[] = [
ConsumerSubject.create(null, false),
ConsumerSubject.create(null, false),
ConsumerSubject.create(null, false),
ConsumerSubject.create(null, false),
];

private readonly memosLimitationVisible = MappedSubject.create(
SubscribableMapFunctions.nor(),
this.normalChecklistsVisible,
Expand All @@ -77,6 +85,11 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus
this.engineStateSubs[2].setConsumer(sub.on('engine_state_3').whenChanged());
this.engineStateSubs[3].setConsumer(sub.on('engine_state_4').whenChanged());

this.engFirePb[0].setConsumer(sub.on('engine_fire_pb_1'));
this.engFirePb[1].setConsumer(sub.on('engine_fire_pb_2'));
this.engFirePb[2].setConsumer(sub.on('engine_fire_pb_3'));
this.engFirePb[3].setConsumer(sub.on('engine_fire_pb_4'));

this.reverserSubs[0].setConsumer(sub.on('thrust_reverse_2').whenChanged());
this.reverserSubs[1].setConsumer(sub.on('thrust_reverse_3').whenChanged());

Expand Down Expand Up @@ -116,31 +129,47 @@ export class EngineWarningDisplay extends DisplayComponent<{ bus: ArincEventBus
x={93}
y={126}
engine={1}
active={this.engineRunningOrIgnitionOn}
active={MappedSubject.create(
([engineRunningOrIgnitionOn, engFirePb]) => engineRunningOrIgnitionOn && !engFirePb,
this.engineRunningOrIgnitionOn,
this.engFirePb[0],
)}
n1Degraded={this.n1Degraded[0]}
/>
<EngineGauge
bus={this.props.bus}
x={262}
y={126}
engine={2}
active={this.engineRunningOrIgnitionOn}
active={MappedSubject.create(
([engineRunningOrIgnitionOn, engFirePb]) => engineRunningOrIgnitionOn && !engFirePb,
this.engineRunningOrIgnitionOn,
this.engFirePb[1],
)}
n1Degraded={this.n1Degraded[1]}
/>
<EngineGauge
bus={this.props.bus}
x={497}
y={126}
engine={3}
active={this.engineRunningOrIgnitionOn}
active={MappedSubject.create(
([engineRunningOrIgnitionOn, engFirePb]) => engineRunningOrIgnitionOn && !engFirePb,
this.engineRunningOrIgnitionOn,
this.engFirePb[2],
)}
n1Degraded={this.n1Degraded[2]}
/>
<EngineGauge
bus={this.props.bus}
x={668}
y={126}
engine={4}
active={this.engineRunningOrIgnitionOn}
active={MappedSubject.create(
([engineRunningOrIgnitionOn, engFirePb]) => engineRunningOrIgnitionOn && !engFirePb,
this.engineRunningOrIgnitionOn,
this.engFirePb[3],
)}
n1Degraded={this.n1Degraded[3]}
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface BaseEwdSimvars {
memo_right: number;
abnormal_debug_line: number;
nose_gear_compressed: boolean;
engine_fire_pb: boolean;
}

type IndexedTopics =
Expand All @@ -59,7 +60,8 @@ type IndexedTopics =
| 'limitations_all'
| 'memo_left'
| 'memo_right'
| 'nose_gear_compressed';
| 'nose_gear_compressed'
| 'engine_fire_pb';
type EwdIndexedEvents = {
[P in keyof Pick<BaseEwdSimvars, IndexedTopics> as IndexedEventType<P>]: BaseEwdSimvars[P];
};
Expand Down Expand Up @@ -120,6 +122,7 @@ export class EwdSimvarPublisher extends SimVarPublisher<EwdSimvars> {
'nose_gear_compressed',
{ name: 'L:A32NX_LGCIU_#index#_NOSE_GEAR_COMPRESSED', type: SimVarValueType.Bool, indexed: true },
],
['engine_fire_pb', { name: 'L:A32NX_FIRE_BUTTON_ENG#index#', type: SimVarValueType.Bool, indexed: true }],
];

super(new Map(simvars), bus, pacer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ const EngineColumn: FC<Position & EngineNumber & IgnitionActive & EngineColumnPr
const [starterValveOpen] = useSimVar(`L:A32NX_PNEU_ENG_${engine}_STARTER_VALVE_OPEN`, 'number', 500); // TODO: Update with correct SimVars
const starting = !!(N2 < 58.5 && ignition && starterValveOpen); // TODO Should be N3
const [fadecManuallyPowered] = useSimVar(`L:A32NX_OVHD_FADEC_${engine}`, 'bool', 500);
const [engineFirePbReleased] = useSimVar(`L:A32NX_FIRE_BUTTON_ENG${engine}`, 'bool', 500);

const fadecPowered = ignition || anyEngineRunning || fadecManuallyPowered;
const fadecPowered = (ignition || anyEngineRunning || fadecManuallyPowered) && !engineFirePbReleased;

const [fuelFlow] = useSimVar(`L:A32NX_ENGINE_FF:${engine}`, 'number', 100);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1654,6 +1654,7 @@ export class FwsAbnormalSensed {
// APU FIRE
flightPhaseInhib: [5, 6],
simVarIsActive: this.fws.apuFireDetected,
auralWarning: this.fws.apuFireDetectedAural.map((on) => (on ? FwcAuralWarning.Crc : FwcAuralWarning.None)),
notActiveWhenFaults: [],
whichItemsToShow: () => [!this.fws.fireTestPb.get(), !this.fws.fireTestPb.get(), !this.fws.fireTestPb.get()],
whichItemsChecked: () => [
Expand Down Expand Up @@ -1709,10 +1710,12 @@ export class FwsAbnormalSensed {
this.fws.aircraftOnGround,
this.fws.eng1FireDetected,
),
auralWarning: this.fws.eng1FireDetectedAural.map((on) => (on ? FwcAuralWarning.Crc : FwcAuralWarning.None)),
notActiveWhenFaults: [],
whichItemsToShow: () => [true, true, true, true, true, true, true, true, true],
whichItemsChecked: () => [
this.fws.throttle1Position.get() == 0,
// When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition
this.fws.throttle1Position.get() == 0 && !this.fws.fireButtonEng1.get(),
!this.fws.engine1ValueSwitch.get(),
this.fws.fireButtonEng1.get(),
!this.fws.apuBleedValveOpen.get(),
Expand All @@ -1735,10 +1738,12 @@ export class FwsAbnormalSensed {
this.fws.aircraftOnGround,
this.fws.eng2FireDetected,
),
auralWarning: this.fws.eng2FireDetectedAural.map((on) => (on ? FwcAuralWarning.Crc : FwcAuralWarning.None)),
notActiveWhenFaults: [],
whichItemsToShow: () => [true, true, true, true, true, true, true],
whichItemsChecked: () => [
this.fws.throttle2Position.get() == 0,
// When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition
this.fws.throttle2Position.get() == 0 && !this.fws.fireButtonEng2.get(),
!this.fws.engine2ValueSwitch.get(),
this.fws.fireButtonEng2.get(),
this.fws.eng2Agent1Discharged.get(),
Expand All @@ -1758,10 +1763,12 @@ export class FwsAbnormalSensed {
this.fws.aircraftOnGround,
this.fws.eng3FireDetected,
),
auralWarning: this.fws.eng3FireDetectedAural.map((on) => (on ? FwcAuralWarning.Crc : FwcAuralWarning.None)),
notActiveWhenFaults: [],
whichItemsToShow: () => [true, true, true, true, true, true, true],
whichItemsChecked: () => [
this.fws.throttle3Position.get() == 0,
// When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition
this.fws.throttle3Position.get() == 0 && !this.fws.fireButtonEng3.get(),
!this.fws.engine3ValueSwitch.get(),
this.fws.fireButtonEng3.get(),
this.fws.eng3Agent1Discharged.get(),
Expand All @@ -1781,10 +1788,12 @@ export class FwsAbnormalSensed {
this.fws.aircraftOnGround,
this.fws.eng4FireDetected,
),
auralWarning: this.fws.eng4FireDetectedAural.map((on) => (on ? FwcAuralWarning.Crc : FwcAuralWarning.None)),
notActiveWhenFaults: [],
whichItemsToShow: () => [true, true, true, true, true, true, true],
whichItemsChecked: () => [
this.fws.throttle4Position.get() == 0,
// When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition
this.fws.throttle4Position.get() == 0 && !this.fws.fireButtonEng4.get(),
!this.fws.engine4ValueSwitch.get(),
this.fws.fireButtonEng4.get(),
this.fws.eng4Agent1Discharged.get(),
Expand All @@ -1804,6 +1813,7 @@ export class FwsAbnormalSensed {
this.fws.aircraftOnGround,
this.fws.eng1FireDetected,
),
auralWarning: this.fws.eng1FireDetectedAural.map((on) => (on ? FwcAuralWarning.Crc : FwcAuralWarning.None)),
notActiveWhenFaults: [],
whichItemsToShow: () => [
!this.fws.fireTestPb.get(),
Expand All @@ -1824,7 +1834,8 @@ export class FwsAbnormalSensed {
!this.fws.fireTestPb.get(),
],
whichItemsChecked: () => [
this.fws.allThrottleIdle.get(),
// When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition
this.fws.allThrottleIdle.get() && !this.fws.fireButtonEng1.get(),
false,
this.fws.parkBrake.get(),
false,
Expand Down Expand Up @@ -1853,6 +1864,7 @@ export class FwsAbnormalSensed {
this.fws.aircraftOnGround,
this.fws.eng2FireDetected,
),
auralWarning: this.fws.eng2FireDetectedAural.map((on) => (on ? FwcAuralWarning.Crc : FwcAuralWarning.None)),
notActiveWhenFaults: [],
whichItemsToShow: () => [
!this.fws.fireTestPb.get(),
Expand All @@ -1873,7 +1885,8 @@ export class FwsAbnormalSensed {
!this.fws.fireTestPb.get(),
],
whichItemsChecked: () => [
this.fws.allThrottleIdle.get(),
// When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition
this.fws.allThrottleIdle.get() && !this.fws.fireButtonEng2.get(),
false,
this.fws.parkBrake.get(),
false,
Expand Down Expand Up @@ -1902,6 +1915,7 @@ export class FwsAbnormalSensed {
this.fws.aircraftOnGround,
this.fws.eng3FireDetected,
),
auralWarning: this.fws.eng3FireDetectedAural.map((on) => (on ? FwcAuralWarning.Crc : FwcAuralWarning.None)),
notActiveWhenFaults: [],
whichItemsToShow: () => [
!this.fws.fireTestPb.get(),
Expand All @@ -1922,7 +1936,8 @@ export class FwsAbnormalSensed {
!this.fws.fireTestPb.get(),
],
whichItemsChecked: () => [
this.fws.allThrottleIdle.get(),
// When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition
this.fws.allThrottleIdle.get() && !this.fws.fireButtonEng3.get(),
false,
this.fws.parkBrake.get(),
false,
Expand Down Expand Up @@ -1951,6 +1966,7 @@ export class FwsAbnormalSensed {
this.fws.aircraftOnGround,
this.fws.eng4FireDetected,
),
auralWarning: this.fws.eng4FireDetectedAural.map((on) => (on ? FwcAuralWarning.Crc : FwcAuralWarning.None)),
notActiveWhenFaults: [],
whichItemsToShow: () => [
!this.fws.fireTestPb.get(),
Expand All @@ -1971,7 +1987,8 @@ export class FwsAbnormalSensed {
!this.fws.fireTestPb.get(),
],
whichItemsChecked: () => [
this.fws.allThrottleIdle.get(),
// When the fire pb is released, the FADEC is not powered and the throttle position is unknown which resets this condition
this.fws.allThrottleIdle.get() && !this.fws.fireButtonEng4.get(),
false,
this.fws.parkBrake.get(),
false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,6 @@ export class FwsCore {

public readonly masterCaution = Subject.create(false);

public readonly fireActive = Subject.create(false);

private nonCancellableWarningCount = 0;

public readonly stallWarning = Subject.create(false);
Expand All @@ -262,17 +260,15 @@ export class FwsCore {
);

public readonly masterWarningOutput = MappedSubject.create(
([mw, fire, stall, startup]) => (mw || fire || stall) && startup,
([mw, stall, startup]) => (mw || stall) && startup,
this.masterWarning,
this.fireActive,
this.stallWarning,
this.startupCompleted,
);

public readonly auralCrcOutput = MappedSubject.create(
([auralCrc, fireActive, startup]) => (auralCrc || fireActive) && startup,
([auralCrc, startup]) => auralCrc && startup,
this.auralCrcActive,
this.fireActive,
this.startupCompleted,
);

Expand Down Expand Up @@ -586,6 +582,16 @@ export class FwsCore {

public readonly eng4FireDetected = Subject.create(false);

public readonly apuFireDetectedAural = Subject.create(false);

public readonly eng1FireDetectedAural = Subject.create(false);

public readonly eng2FireDetectedAural = Subject.create(false);

public readonly eng3FireDetectedAural = Subject.create(false);

public readonly eng4FireDetectedAural = Subject.create(false);

public readonly mlgFireDetected = Subject.create(false);

public readonly apuAgentDischarged = Subject.create(false);
Expand Down Expand Up @@ -3623,6 +3629,12 @@ export class FwsCore {
this.fireButtonAPU.get(),
);

this.apuFireDetectedAural.set(this.apuFireDetected.get() && !this.fireButtonAPU.get());
this.eng1FireDetectedAural.set(this.eng1FireDetected.get() && !this.fireButtonEng1.get());
this.eng2FireDetectedAural.set(this.eng2FireDetected.get() && !this.fireButtonEng2.get());
this.eng3FireDetectedAural.set(this.eng3FireDetected.get() && !this.fireButtonEng3.get());
this.eng4FireDetectedAural.set(this.eng4FireDetected.get() && !this.fireButtonEng4.get());

this.evacCommand.set(SimVar.GetSimVarValue('L:A32NX_EVAC_COMMAND_TOGGLE', 'bool'));

this.cargoFireTest.set(SimVar.GetSimVarValue('L:A32NX_FIRE_TEST_CARGO', 'bool'));
Expand Down Expand Up @@ -3741,19 +3753,6 @@ export class FwsCore {
(this.engine1State.get() === 0 && this.engine2State.get() === 0)),
);

// fire always forces the master warning and SC aural on
this.fireActive.set(
[
this.apuFireDetected.get(),
this.eng1FireDetected.get(),
this.eng2FireDetected.get(),
this.eng3FireDetected.get(),
this.eng4FireDetected.get(),
this.mlgFireDetected.get(),
this.cargoFireTest.get(),
].some((e) => e),
);

const flightPhase = this.fwcFlightPhase.get();
let tempMemoArrayLeft: string[] = [];
let tempMemoArrayRight: string[] = [];
Expand Down

0 comments on commit 322ed63

Please sign in to comment.