Skip to content
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

feat(a32nx): hook up engine oil sim #9795

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
1. [A380X/FMS] Use cruise mach above crossover altitude - @flogross89 (floridude)
1. [A380X/SD] Display oil quantity on ENG page - @flogross89 (floridude)
1. [A380X/FMS] Accept KCCU plus/minus key as first entry into field - @flogross89 (floridude)
1. [A32NX/SD] Use oil quantity and pressure simulation on ENG page - @tracernz (Mike)

## 0.12.0

Expand Down
18 changes: 14 additions & 4 deletions fbw-a32nx/docs/a320-simvars.md
Original file line number Diff line number Diff line change
Expand Up @@ -2380,14 +2380,24 @@ In the variables below, {number} should be replaced with one item in the set: {
- Number (lbs)
- Previous deltaTime fuel for the center tank

- A32NX_ENGINE_OIL_TOTAL:{index}
- Number (quarts)
- Total engine {index} oil quantity in the oil system (tank + circuit)
- `A32NX_ENGINE_OIL_PRESS:{index}`
- Number (psi)
- Engine {index} oil pressure

- A32NX_ENGINE_OIL_QTY:{index}
- `A32NX_ENGINE_OIL_QTY:{index}`
- Number (quarts)
- Total engine {index} oil quantity in the oil tank

- `A32NX_ENGINE_OIL_TEMP:{index}`
- Number (celsius)
- Engine {index} oil temperature

- `A32NX_ENGINE_OIL_TOTAL:{index}`
- Number (quarts)
- Total engine {index} oil quantity in the oil system (tank + circuit)



## Air Conditioning / Pressurisation / Ventilation

- A32NX_COND_ACSC_{number}_DISCRETE_WORD_1
Expand Down
12 changes: 6 additions & 6 deletions fbw-a32nx/src/systems/instruments/src/SD/Pages/Eng/Eng.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import React, { FC, useState, useEffect } from 'react';
import { Arc, Needle } from '@instruments/common/gauges';
import { usePersistentProperty, useSimVar } from '@flybywiresim/fbw-sdk';
import { MathUtils, usePersistentProperty, useSimVar } from '@flybywiresim/fbw-sdk';
import { PageTitle } from '../../Common/PageTitle';
import { EcamPage } from '../../Common/EcamPage';
import { SvgGroup } from '../../Common/SvgGroup';
Expand Down Expand Up @@ -87,13 +87,14 @@ function getNeedleValue(value: any, max: number): number {
interface ComponentPositionProps {
x: number;
y: number;
/** 1-based index of the engine.*/
engineNumber: number;
fadecOn: boolean;
}

const PressureGauge = ({ x, y, engineNumber, fadecOn }: ComponentPositionProps) => {
const [engineOilPressure] = useSimVar(`ENG OIL PRESSURE:${engineNumber}`, 'psi', 100);
const displayedEngineOilPressure = Math.round(engineOilPressure / 2) * 2; // Engine oil pressure has a step of 2
const [engineOilPressure] = useSimVar(`L:A32NX_ENGINE_OIL_PRESS:${engineNumber}`, 'number', 100);
const displayedEngineOilPressure = MathUtils.round(engineOilPressure, 2); // Engine oil pressure has a step of 2
const OIL_PSI_MAX = 130;
const OIL_PSI_HIGH_LIMIT = 130;
const OIL_PSI_LOW_LIMIT = 14; // TODO FIXME: standin value
Expand Down Expand Up @@ -190,11 +191,10 @@ const PressureGauge = ({ x, y, engineNumber, fadecOn }: ComponentPositionProps)
};

const QuantityGauge = ({ x, y, engineNumber, fadecOn }: ComponentPositionProps) => {
const [engineOilQuantity] = useSimVar(`ENG OIL QUANTITY:${engineNumber}`, 'percent', 100);
const [engineOilQuantity] = useSimVar(`L:A32NX_ENGINE_OIL_QTY:${engineNumber}`, 'number', 100);
const OIL_QTY_MAX = 24.25;
const OIL_QTY_LOW_ADVISORY = 1.35;
const displayedEngineOilQuantity =
engineOilQuantity === 100 ? OIL_QTY_MAX : Math.round(((engineOilQuantity / 100) * OIL_QTY_MAX) / 0.5) * 0.5; // Engine oil quantity has a step of 0.2
const displayedEngineOilQuantity = MathUtils.clamp(MathUtils.round(engineOilQuantity, 0.5), 0, OIL_QTY_MAX); // Engine oil quantity has a step of 0.5
const [quantityAtOrBelowLow, setQuantityAtOrBelowLow] = useState(false);
const [shouldQuantityPulse, setShouldQuantityPulse] = useState(false);

Expand Down
165 changes: 65 additions & 100 deletions fbw-a32nx/src/wasm/fadec_a32nx/src/Fadec/EngineControlA32NX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ void EngineControl_A32NX::update() {
const double correctedFuelFlow = updateFF(engine, imbalance, simCN1, mach, pressureAltitude, ambientTemperature, ambientPressure);
updateEGT(engine, imbalance, deltaTime, msfsHandlerPtr->getSimOnGround(), engineState, simCN1, correctedFuelFlow, mach,
pressureAltitude, ambientTemperature);
// updateOil(engine, imbalance, thrust, simN2, deltaN2, deltaTime, ambientTemp);
const double thrust = simData.simVarsDataPtr->data().simEngineThrust[engineIdx];
updateOil(engineIdx, engineState, imbalance, thrust, simN2, deltaTime, msfsHandlerPtr->getSimOnGround(), ambientTemperature);
}

// set highest N1 from either engine
Expand Down Expand Up @@ -178,9 +179,9 @@ void EngineControl_A32NX::initializeEngineControlData() {

// Setting initial Oil with some randomness and imbalance
const double idleOilL = (rand() % (MAX_OIL - MIN_OIL + 1) + MIN_OIL) / 10;
simData.engineOilTotal[L]->set(idleOilL - ((engineImbalanced == 1) ? oilQtyImbalance : 0));
simData.engineOilTotalQuantity[L]->set(idleOilL - ((engineImbalanced == 1) ? oilQtyImbalance : 0));
const double idleOilR = (rand() % (MAX_OIL - MIN_OIL + 1) + MIN_OIL) / 10;
simData.engineOilTotal[R]->set(idleOilR - ((engineImbalanced == 2) ? oilQtyImbalance : 0));
simData.engineOilTotalQuantity[R]->set(idleOilR - ((engineImbalanced == 2) ? oilQtyImbalance : 0));

const bool engine1Combustion = static_cast<bool>(simData.engineCombustion[L]->updateFromSim(timeStamp, tickCounter));
const bool engine2Combustion = static_cast<bool>(simData.engineCombustion[R]->updateFromSim(timeStamp, tickCounter));
Expand All @@ -196,10 +197,8 @@ void EngineControl_A32NX::initializeEngineControlData() {
oilTemperaturePre[L] = simData.simVarsDataPtr->data().ambientTemperature;
oilTemperaturePre[R] = simData.simVarsDataPtr->data().ambientTemperature;
}
simData.oilTempDataPtr[L]->data().oilTemp = oilTemperaturePre[L];
simData.oilTempDataPtr[L]->writeDataToSim();
simData.oilTempDataPtr[R]->data().oilTemp = oilTemperaturePre[R];
simData.oilTempDataPtr[R]->writeDataToSim();
simData.engineOilTemperature[L]->setAndWriteToSim(oilTemperaturePre[L]);
simData.engineOilTemperature[L]->setAndWriteToSim(oilTemperaturePre[R]);

// Initialize Engine State
simData.engineState[L]->set(OFF);
Expand Down Expand Up @@ -1109,103 +1108,69 @@ void EngineControl_A32NX::updateThrustLimits(double simulationT
#endif
}

/*
* Previous code - call to it was already commented out and this function was not in use.
* Keeping it to make completing/fixing it easier.
* It is not migrated to the cpp framework yet.
*
* /// <summary>
/// <summary>
/// FBW Oil Qty, Pressure and Temperature (in Quarts, PSI and degree Celsius)
/// Updates Oil with realistic values visualized in the SD
/// </summary>
void updateOil(int engine, double imbalance, double thrust, double simN2, double deltaN2, double deltaTime, double ambientTemp) {
double steadyTemperature;
double thermalEnergy;
double oilTemperaturePre;
double oilQtyActual;
double oilTotalActual;
double oilQtyObjective;
double oilBurn;
double oilIdleRandom;
double oilPressure;

//--------------------------------------------
// Engine Reading
//--------------------------------------------
if (engine == 1) {
steadyTemperature = simVars->getEngine1EGT();
thermalEnergy = thermalEnergy1;
oilTemperaturePre = oilTemperatureLeftPre;
oilQtyActual = simVars->getEngine1Oil();
oilTotalActual = simVars->getEngine1OilTotal();
} else {
steadyTemperature = simVars->getEngine2EGT();
thermalEnergy = thermalEnergy2;
oilTemperaturePre = oilTemperatureRightPre;
oilQtyActual = simVars->getEngine2Oil();
oilTotalActual = simVars->getEngine2OilTotal();
}
void EngineControl_A32NX::updateOil(int engineIdx,
EngineState engineState,
double imbalance,
double thrust,
double simN2,
double deltaTime,
bool isOnGround,
double ambientTemp) {
const int engineImbalanced = imbalanceExtractor(imbalance, 1);

//--------------------------------------------
// Oil Temperature
//--------------------------------------------
if (simOnGround == 1 && engineState == 0 && ambientTemp > oilTemperaturePre - 10) {
oilTemperature = ambientTemp;
} else {
if (steadyTemperature > oilTemperatureMax) {
steadyTemperature = oilTemperatureMax;
}
thermalEnergy = (0.995 * thermalEnergy) + (deltaN2 / deltaTime);
oilTemperature = poly->oilTemperature(thermalEnergy, oilTemperaturePre, steadyTemperature, deltaTime);
}
//--------------------------------------------
// Oil Temperature
//--------------------------------------------
const double egt = simData.engineEgt[engineIdx]->get();
const double oilTemperaturePre = simData.engineOilTemperature[engineIdx]->get();
const double oilTemperatureMax = MAX_OIL_TEMP_NOMINAL + (engineIdx + 1) == engineImbalanced ? imbalanceExtractor(imbalance, 8) : 0;
double oilTemperature;
if (isOnGround && engineState == EngineState::OFF && ambientTemp > oilTemperaturePre - 10) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also doesn't really make sense to me. It shouldn't really matter whether the plane is on the ground or not?

Copy link
Member Author

@tracernz tracernz Jan 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't really looking to work on the code any further than needed, only re-enable it, but it ended up needing a bit of work due to changes in the FADEC code 😬 . I think this does make some sense as a sanity check for spawn situations where the Lvar might have an old value.

oilTemperature = ambientTemp;
} else {
double deltaN2 = simN2 - simData.engineN2[engineIdx]->get();
// FIXME this makes zero sense, implies perpetual decay at steady-state
thermalEnergy[engineIdx] = (0.995 * thermalEnergy[engineIdx]) + (deltaN2 / deltaTime);
oilTemperature = Polynomial_A32NX::oilTemperature(thermalEnergy[engineIdx], std::max(ambientTemp, oilTemperaturePre),
std::min(egt, oilTemperatureMax), deltaTime);
}
simData.engineOilTemperature[engineIdx]->set(oilTemperature);

//--------------------------------------------
// Oil Quantity
//--------------------------------------------
// Calculating Oil Qty as a function of thrust
oilQtyObjective = oilTotalActual * (1 - poly->oilGulpPct(thrust));
oilQtyActual = oilQtyActual - (oilTemperature - oilTemperaturePre);

// Oil burnt taken into account for tank and total oil
oilBurn = (0.00011111 * deltaTime);
oilQtyActual = oilQtyActual - oilBurn;
oilTotalActual = oilTotalActual - oilBurn;

//--------------------------------------------
// Oil Pressure
//--------------------------------------------
// Engine imbalance
engineImbalanced = imbalanceExtractor(imbalance, 1);
paramImbalance = imbalanceExtractor(imbalance, 6) / 10;
oilIdleRandom = imbalanceExtractor(imbalance, 7) - 6;

// Checking engine imbalance
if (engineImbalanced != engine) {
paramImbalance = 0;
}
//--------------------------------------------
// Oil Quantity
//--------------------------------------------
// Calculating Oil Qty as a function of thrust
double oilTotalActual = simData.engineOilTotalQuantity[engineIdx]->get();
double oilQtyActual = oilTotalActual * (1 - Polynomial_A32NX::oilGulpPct(thrust));

oilPressure = poly->oilPressure(simN2) - paramImbalance + oilIdleRandom;

//--------------------------------------------
// Engine Writing
//--------------------------------------------
if (engine == 1) {
thermalEnergy1 = thermalEnergy;
oilTemperatureLeftPre = oilTemperature;
simVars->setEngine1Oil(oilQtyActual);
simVars->setEngine1OilTotal(oilTotalActual);
SimConnect_SetDataOnSimObject(hSimConnect, DataTypesID::OilTempLeft, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(double),
&oilTemperature);
SimConnect_SetDataOnSimObject(hSimConnect, DataTypesID::OilPsiLeft, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(double), &oilPressure);
} else {
thermalEnergy2 = thermalEnergy;
oilTemperatureRightPre = oilTemperature;
simVars->setEngine2Oil(oilQtyActual);
simVars->setEngine2OilTotal(oilTotalActual);
SimConnect_SetDataOnSimObject(hSimConnect, DataTypesID::OilTempRight, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(double),
&oilTemperature);
SimConnect_SetDataOnSimObject(hSimConnect, DataTypesID::OilPsiRight, SIMCONNECT_OBJECT_ID_USER, 0, 0, sizeof(double), &oilPressure);
}
}
// Oil burnt taken into account for tank and total oil
double oilBurn = (0.00011111 * deltaTime);
oilQtyActual = oilQtyActual - oilBurn;
oilTotalActual = oilTotalActual - oilBurn;

*/
//--------------------------------------------
// Oil Pressure
//--------------------------------------------
// Engine imbalance
double paramImbalance = imbalanceExtractor(imbalance, 6) / 10;
double oilIdleRandom = imbalanceExtractor(imbalance, 7) - 6;

// Checking engine imbalance
if (engineImbalanced != (engineIdx + 1)) {
paramImbalance = 0;
}

double oilPressure = Polynomial_A32NX::oilPressure(simN2) - paramImbalance + oilIdleRandom;

//--------------------------------------------
// Engine Writing
//--------------------------------------------
simData.engineOilTankQuantity[engineIdx]->set(oilQtyActual);
simData.engineOilTotalQuantity[engineIdx]->set(oilTotalActual);
simData.engineOilTemperature[engineIdx]->set(oilTemperature);
simData.engineOilPressure[engineIdx]->set(oilPressure);
}
20 changes: 17 additions & 3 deletions fbw-a32nx/src/wasm/fadec_a32nx/src/Fadec/EngineControlA32NX.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,21 @@ class EngineControl_A32NX {
double prevThrustLimitType = 0.0;
double prevEngineMasterPos[2] = {0, 0};
bool prevEngineStarterState[2] = {false, false};
double thermalEnergy[2] = {
0.,
0.,
};

// FLX->CLB thrust limit transition
double transitionStartTime;
double transitionFactor;
bool wasFlexActive = false;

// additional constants
static constexpr int MAX_OIL = 200;
static constexpr int MIN_OIL = 140;
static constexpr double FUEL_RATE_THRESHOLD = 661; // lbs/sec for determining fuel ui tampering
static constexpr int MAX_OIL = 200;
static constexpr int MIN_OIL = 140;
static constexpr int MAX_OIL_TEMP_NOMINAL = 86;
static constexpr double FUEL_RATE_THRESHOLD = 661; // lbs/sec for determining fuel ui tampering

/**
* @enum EngineState
Expand Down Expand Up @@ -335,6 +340,15 @@ class EngineControl_A32NX {
int packs,
int nai,
int wai);

void updateOil(int engine,
EngineState engineState,
double imbalance,
double thrust,
double simN2,
double deltaTime,
bool isOnGround,
double ambientTemp);
};

#endif // FLYBYWIRE_AIRCRAFT_ENGINECONTROL_A32NX_H
31 changes: 21 additions & 10 deletions fbw-a32nx/src/wasm/fadec_a32nx/src/Fadec/FadecSimData_A32NX.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class FadecSimData_A32NX {
FLOAT64 pressureAltitude; // Feet
FLOAT64 simEngineN1[2]; // Percent
FLOAT64 simEngineN2[2]; // Percent
FLOAT64 simEngineThrust[2]; // Percent
FLOAT64 xFeedValve; // Number
FLOAT64 xfrCenterManual[2]; // Number
FLOAT64 xfrValveCenterAuto[2]; // Number
Expand Down Expand Up @@ -158,6 +159,8 @@ class FadecSimData_A32NX {
{"TURB ENG N1", 2, UNITS.Percent }, // simEngineN1[1]
{"TURB ENG N2", 1, UNITS.Percent }, // simEngineN2[0]
{"TURB ENG N2", 2, UNITS.Percent }, // simEngineN2[1]
{"TURB ENG JET THRUST", 1, UNITS.Pounds }, // simEngineThrust[0]
{"TURB ENG JET THRUST", 2, UNITS.Pounds }, // simEngineThrust[1]
{"FUELSYSTEM VALVE OPEN", 3, UNITS.Number }, // xFeedValve
{"FUELSYSTEM JUNCTION SETTING", 4, UNITS.Number }, // xfrCenterManual[0]
{"FUELSYSTEM JUNCTION SETTING", 5, UNITS.Number }, // xfrCenterManual[1]
Expand Down Expand Up @@ -197,8 +200,10 @@ class FadecSimData_A32NX {
NamedVariablePtr engineImbalance;
NamedVariablePtr engineN1[2];
NamedVariablePtr engineN2[2];
NamedVariablePtr engineOilTotal[2];
NamedVariablePtr engineOil[2];
NamedVariablePtr engineOilPressure[2];
NamedVariablePtr engineOilTankQuantity[2];
NamedVariablePtr engineOilTemperature[2];
NamedVariablePtr engineOilTotalQuantity[2];
NamedVariablePtr enginePreFF[2];
NamedVariablePtr engineStarterPressurized[2];
NamedVariablePtr engineState[2];
Expand Down Expand Up @@ -314,11 +319,17 @@ class FadecSimData_A32NX {
engineN2[L] = dm->make_named_var("A32NX_ENGINE_N2:1", UNITS.Number, AUTO_READ_WRITE);
engineN2[R] = dm->make_named_var("A32NX_ENGINE_N2:2", UNITS.Number, AUTO_READ_WRITE);

engineOil[L] = dm->make_named_var("A32NX_ENGINE_OIL_QTY:1", UNITS.Number, AUTO_READ_WRITE);
engineOil[R] = dm->make_named_var("A32NX_ENGINE_OIL_QTY:2", UNITS.Number, AUTO_READ_WRITE);
engineOilPressure[L] = dm->make_named_var("A32NX_ENGINE_OIL_PRESS:1", UNITS.Number, AUTO_READ_WRITE);
engineOilPressure[R] = dm->make_named_var("A32NX_ENGINE_OIL_PRESS:2", UNITS.Number, AUTO_READ_WRITE);

engineOilTotal[L] = dm->make_named_var("A32NX_ENGINE_OIL_TOTAL:1", UNITS.Number, AUTO_READ_WRITE);
engineOilTotal[R] = dm->make_named_var("A32NX_ENGINE_OIL_TOTAL:2", UNITS.Number, AUTO_READ_WRITE);
engineOilTankQuantity[L] = dm->make_named_var("A32NX_ENGINE_OIL_QTY:1", UNITS.Number, AUTO_READ_WRITE);
engineOilTankQuantity[R] = dm->make_named_var("A32NX_ENGINE_OIL_QTY:2", UNITS.Number, AUTO_READ_WRITE);

engineOilTemperature[L] = dm->make_named_var("A32NX_ENGINE_OIL_TEMP:1", UNITS.Number, AUTO_READ_WRITE);
engineOilTemperature[R] = dm->make_named_var("A32NX_ENGINE_OIL_TEMP:2", UNITS.Number, AUTO_READ_WRITE);

engineOilTotalQuantity[L] = dm->make_named_var("A32NX_ENGINE_OIL_TOTAL:1", UNITS.Number, AUTO_READ_WRITE);
engineOilTotalQuantity[R] = dm->make_named_var("A32NX_ENGINE_OIL_TOTAL:2", UNITS.Number, AUTO_READ_WRITE);

enginePreFF[L] = dm->make_named_var("A32NX_ENGINE_PRE_FF:1", UNITS.Number, AUTO_READ_WRITE);
enginePreFF[R] = dm->make_named_var("A32NX_ENGINE_PRE_FF:2", UNITS.Number, AUTO_READ_WRITE);
Expand Down Expand Up @@ -374,10 +385,10 @@ class FadecSimData_A32NX {
engineN1[R]->setAndWriteToSim(0);
engineN2[L]->setAndWriteToSim(0);
engineN2[R]->setAndWriteToSim(0);
engineOilTotal[L]->setAndWriteToSim(0);
engineOilTotal[R]->setAndWriteToSim(0);
engineOil[L]->setAndWriteToSim(0);
engineOil[R]->setAndWriteToSim(0);
engineOilTotalQuantity[L]->setAndWriteToSim(0);
engineOilTotalQuantity[R]->setAndWriteToSim(0);
engineOilTankQuantity[L]->setAndWriteToSim(0);
engineOilTankQuantity[R]->setAndWriteToSim(0);
enginePreFF[L]->setAndWriteToSim(0);
enginePreFF[R]->setAndWriteToSim(0);
engineState[L]->setAndWriteToSim(0);
Expand Down
Loading