Usable fuel consumption data/gauges (#2474)
* fuel consumption * gauge names * consumers * obd * binary logging * doesn't need explicit constructor * getters * it works * correct for injections per cycle * datalog Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
b0948589ac
commit
650d148008
|
@ -158,7 +158,8 @@ typedef struct {
|
|||
|
||||
// Fuel system
|
||||
scaled_percent fuelTankLevel; // 98
|
||||
float fuelConsumptionPerHour; // 100
|
||||
scaled_channel<uint16_t> totalFuelConsumption; // 100
|
||||
scaled_channel<uint16_t, PACK_MULT_FUEL_FLOW> fuelFlowRate; // 102
|
||||
|
||||
// Y axis values for selectable tables
|
||||
scaled_channel<uint16_t, 100> veTableYAxis; // 104
|
||||
|
|
|
@ -64,6 +64,8 @@ static const LogField fields[] = {
|
|||
{tsOutputChannels.ignitionLoad, GAUGE_NAME_IGNITION_LOAD, "%", 1},
|
||||
{tsOutputChannels.massAirFlow, GAUGE_NAME_AIR_FLOW, "kg/h", 1},
|
||||
{tsOutputChannels.flexPercent, GAUGE_NAME_FLEX, "%", 1},
|
||||
{tsOutputChannels.fuelFlowRate, GAUGE_NAME_FUEL_FLOW, "g/s", 3},
|
||||
{tsOutputChannels.totalFuelConsumption, GAUGE_NAME_FUEL_CONSUMPTION, "g", 1},
|
||||
};
|
||||
|
||||
void writeHeader(Writer& outBuffer) {
|
||||
|
|
|
@ -705,7 +705,8 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_
|
|||
#endif /* EFI_VEHICLE_SPEED */
|
||||
#endif /* EFI_PROD_CODE */
|
||||
|
||||
tsOutputChannels->fuelConsumptionPerHour = engine->engineState.fuelConsumption.perSecondConsumption;
|
||||
tsOutputChannels->fuelFlowRate = engine->engineState.fuelConsumption.getConsumptionGramPerSecond();
|
||||
tsOutputChannels->totalFuelConsumption = engine->engineState.fuelConsumption.getConsumedGrams();
|
||||
|
||||
tsOutputChannels->warningCounter = engine->engineState.warnings.warningCounter;
|
||||
tsOutputChannels->lastErrorCode = engine->engineState.warnings.lastErrorCode;
|
||||
|
|
|
@ -76,34 +76,25 @@ void MockAdcState::setMockVoltage(int hwChannel, float voltage DECLARE_ENGINE_PA
|
|||
}
|
||||
#endif /* EFI_ENABLE_MOCK_ADC */
|
||||
|
||||
FuelConsumptionState::FuelConsumptionState() {
|
||||
accumulatedSecondPrevNt = accumulatedMinutePrevNt = getTimeNowNt();
|
||||
}
|
||||
void FuelConsumptionState::consumeFuel(float grams, efitick_t nowNt) {
|
||||
m_consumedGrams += grams;
|
||||
|
||||
void FuelConsumptionState::addData(float durationMs) {
|
||||
if (durationMs > 0.0f) {
|
||||
perSecondAccumulator += durationMs;
|
||||
perMinuteAccumulator += durationMs;
|
||||
float elapsedSecond = m_timer.getElapsedSecondsAndReset(nowNt);
|
||||
|
||||
// If it's been a long time since last injection, ignore this pulse
|
||||
if (elapsedSecond > 0.2f) {
|
||||
m_rate = 0;
|
||||
} else {
|
||||
m_rate = grams / elapsedSecond;
|
||||
}
|
||||
}
|
||||
|
||||
void FuelConsumptionState::update(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||
efitick_t deltaNt = nowNt - accumulatedSecondPrevNt;
|
||||
if (deltaNt >= NT_PER_SECOND) {
|
||||
perSecondConsumption = getFuelRate(perSecondAccumulator, deltaNt PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
perSecondAccumulator = 0;
|
||||
accumulatedSecondPrevNt = nowNt;
|
||||
}
|
||||
|
||||
deltaNt = nowNt - accumulatedMinutePrevNt;
|
||||
if (deltaNt >= NT_PER_SECOND * 60) {
|
||||
perMinuteConsumption = getFuelRate(perMinuteAccumulator, deltaNt PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
perMinuteAccumulator = 0;
|
||||
accumulatedMinutePrevNt = nowNt;
|
||||
}
|
||||
float FuelConsumptionState::getConsumedGrams() const {
|
||||
return m_consumedGrams;
|
||||
}
|
||||
|
||||
TransmissionState::TransmissionState() {
|
||||
float FuelConsumptionState::getConsumptionGramPerSecond() const {
|
||||
return m_rate;
|
||||
}
|
||||
|
||||
EngineState::EngineState() {
|
||||
|
@ -144,9 +135,6 @@ void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|||
auto clResult = fuelClosedLoopCorrection(PASS_ENGINE_PARAMETER_SIGNATURE);
|
||||
running.pidCorrection = clResult.banks[0];
|
||||
|
||||
// update fuel consumption states
|
||||
fuelConsumption.update(nowNt PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
|
||||
// Fuel cut-off isn't just 0 or 1, it can be tapered
|
||||
fuelCutoffCorrection = getFuelCutOffCorrection(nowNt, rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "global.h"
|
||||
#include "engine_configuration_generated_structures.h"
|
||||
#include "cyclic_buffer.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define MOCK_ADC_SIZE 26
|
||||
|
||||
|
@ -39,20 +40,20 @@ public:
|
|||
|
||||
class FuelConsumptionState {
|
||||
public:
|
||||
FuelConsumptionState();
|
||||
void addData(float durationMs);
|
||||
void update(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX);
|
||||
float perSecondConsumption = 0;
|
||||
float perMinuteConsumption = 0;
|
||||
float perSecondAccumulator = 0;
|
||||
float perMinuteAccumulator = 0;
|
||||
efitick_t accumulatedSecondPrevNt;
|
||||
efitick_t accumulatedMinutePrevNt;
|
||||
void consumeFuel(float grams, efitick_t nowNt);
|
||||
|
||||
float getConsumedGrams() const;
|
||||
float getConsumptionGramPerSecond() const;
|
||||
|
||||
private:
|
||||
float m_consumedGrams = 0;
|
||||
float m_rate = 0;
|
||||
|
||||
Timer m_timer;
|
||||
};
|
||||
|
||||
class TransmissionState {
|
||||
public:
|
||||
TransmissionState();
|
||||
gear_e gearSelectorPosition;
|
||||
};
|
||||
|
||||
|
|
|
@ -477,14 +477,4 @@ float getStandardAirCharge(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
float getFuelRate(floatms_t totalInjDuration, efitick_t timePeriod DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||
if (timePeriod <= 0.0f)
|
||||
return 0.0f;
|
||||
float timePeriodMs = (float)NT2US(timePeriod) / 1000.0f;
|
||||
float fuelRate = totalInjDuration / timePeriodMs;
|
||||
const float cc_min_to_L_h = 60.0f / 1000.0f;
|
||||
return fuelRate * CONFIG(injector.flow) * cc_min_to_L_h;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,3 @@ floatms_t getInjectionMass(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX);
|
|||
percent_t getInjectorDutyCycle(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX);
|
||||
|
||||
float getStandardAirCharge(DECLARE_ENGINE_PARAMETER_SIGNATURE);
|
||||
|
||||
// convert injection duration (Ms/Nt) to fuel rate (L/h)
|
||||
float getFuelRate(floatms_t totalInjDuration, efitick_t timePeriod DECLARE_ENGINE_PARAMETER_SUFFIX);
|
||||
|
|
|
@ -171,10 +171,13 @@ static void handleGetDataRequest(const CANRxFrame& rx) {
|
|||
|
||||
obdSendPacket(1, pid, 4, scaled << 16);
|
||||
break;
|
||||
} case PID_FUEL_RATE:
|
||||
obdSendValue(_1_MODE, pid, 2, engine->engineState.fuelConsumption.perSecondConsumption * 20.0f); // L/h. (A*256+B)/20
|
||||
} case PID_FUEL_RATE: {
|
||||
float gPerSecond = engine->engineState.fuelConsumption.getConsumptionGramPerSecond();
|
||||
float gPerHour = gPerSecond * 3600;
|
||||
float literPerHour = gPerHour * 0.00139f;
|
||||
obdSendValue(_1_MODE, pid, 2, literPerHour * 20.0f); // L/h. (A*256+B)/20
|
||||
break;
|
||||
default:
|
||||
} default:
|
||||
// ignore unhandled PIDs
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -206,8 +206,8 @@ void InjectionEvent::onTriggerTooth(size_t trgEventIndex, int rpm, efitick_t now
|
|||
|
||||
// Perform wall wetting adjustment on fuel mass, not duration, so that
|
||||
// it's correct during fuel pressure (injector flow) or battery voltage (deadtime) transients
|
||||
const float injectionMass = wallFuel.adjust(ENGINE(injectionMass) PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
const floatms_t injectionDuration = ENGINE(injectorModel)->getInjectionDuration(injectionMass);
|
||||
const float injectionMassGrams = wallFuel.adjust(ENGINE(injectionMass) PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
const floatms_t injectionDuration = ENGINE(injectorModel)->getInjectionDuration(injectionMassGrams);
|
||||
|
||||
#if EFI_PRINTF_FUEL_DETAILS
|
||||
if (printFuelDebug) {
|
||||
|
@ -223,15 +223,13 @@ void InjectionEvent::onTriggerTooth(size_t trgEventIndex, int rpm, efitick_t now
|
|||
* todo: pre-calculate 'numberOfInjections'
|
||||
* see also injectorDutyCycle
|
||||
*/
|
||||
if (!isCranking && injectionDuration * getNumberOfInjections(engineConfiguration->injectionMode PASS_ENGINE_PARAMETER_SUFFIX) > getEngineCycleDuration(rpm PASS_ENGINE_PARAMETER_SUFFIX)) {
|
||||
int numberOfInjections = isCranking ? getNumberOfInjections(engineConfiguration->crankingInjectionMode PASS_ENGINE_PARAMETER_SUFFIX) : getNumberOfInjections(engineConfiguration->injectionMode PASS_ENGINE_PARAMETER_SUFFIX);
|
||||
if (injectionDuration * numberOfInjections > getEngineCycleDuration(rpm PASS_ENGINE_PARAMETER_SUFFIX)) {
|
||||
warning(CUSTOM_TOO_LONG_FUEL_INJECTION, "Too long fuel injection %.2fms", injectionDuration);
|
||||
} else if (isCranking && injectionDuration * getNumberOfInjections(engineConfiguration->crankingInjectionMode PASS_ENGINE_PARAMETER_SUFFIX) > getEngineCycleDuration(rpm PASS_ENGINE_PARAMETER_SUFFIX)) {
|
||||
warning(CUSTOM_TOO_LONG_CRANKING_FUEL_INJECTION, "Too long cranking fuel injection %.2fms", injectionDuration);
|
||||
}
|
||||
|
||||
// Store 'pure' injection duration (w/o injector lag) for fuel rate calc.
|
||||
engine->engineState.fuelConsumption.addData(injectionDuration - ENGINE(engineState.running.injectorLag));
|
||||
|
||||
ENGINE(engineState.fuelConsumption).consumeFuel(injectionMassGrams * numberOfInjections, nowNt);
|
||||
|
||||
ENGINE(actualLastInjection) = injectionDuration;
|
||||
if (cisnan(injectionDuration)) {
|
||||
warning(CUSTOM_OBD_NAN_INJECTION, "NaN injection pulse");
|
||||
|
|
|
@ -194,6 +194,7 @@ struct_no_prefix engine_configuration_s
|
|||
#define PACK_MULT_AFR_CFG 10
|
||||
#define PACK_MULT_LAMBDA_CFG 147
|
||||
#define PACK_MULT_FUEL_MASS 100
|
||||
#define PACK_MULT_FUEL_FLOW 200
|
||||
#define FSIO_TABLE_8 8
|
||||
|
||||
#define FSIO_CURVE_8 8
|
||||
|
@ -1716,6 +1717,8 @@ end_struct
|
|||
#define GAUGE_NAME_FUEL_WALL_AMOUNT "fuel: wall amount"
|
||||
#define GAUGE_NAME_FUEL_WALL_CORRECTION "fuel: wall corr ms"
|
||||
#define GAUGE_NAME_FUEL_LOAD "fuel: load"
|
||||
#define GAUGE_NAME_FUEL_CONSUMPTION "fuel: Total consumed"
|
||||
#define GAUGE_NAME_FUEL_FLOW "fuel: Flow rate"
|
||||
|
||||
#define GAUGE_NAME_FUEL_INJ_DUTY "fuel: injector duty cycle"
|
||||
#define GAUGE_NAME_TCHARGE "fuel: SD tCharge"
|
||||
|
|
|
@ -283,8 +283,9 @@ enable2ndByteCanID = false
|
|||
etb1Error = scalar, S16, 96, "%",{1/@@PACK_MULT_PERCENT@@}, 0
|
||||
|
||||
; Fuel system
|
||||
fuelTankLevel = scalar, S16, 98, "%",{1/@@PACK_MULT_PERCENT@@}, 0
|
||||
fuelConsumptionPerHour=scalar,F32, 100, "kPa", 1, 0.0
|
||||
fuelTankLevel = scalar, U16, 98, "%",{1/@@PACK_MULT_PERCENT@@}, 0
|
||||
totalFuelConsumption=scalar,U16, 100, "grams", 1, 0
|
||||
fuelFlowRate = scalar, U16, 102, "gram/s",{1/@@PACK_MULT_FUEL_FLOW@@}, 0
|
||||
|
||||
; Y axis values for selectable tables
|
||||
veTableYAxis = scalar, U16, 104, "%", 0.01, 0
|
||||
|
@ -1064,6 +1065,8 @@ gaugeCategory = Fueling
|
|||
baseFuelGauge = baseFuel, @@GAUGE_NAME_FUEL_BASE@@, "mg", 0, 100, 0, 0, 100, 100, 2, 0
|
||||
fuelPidCorrectionGauge = fuelPidCorrection, @@GAUGE_NAME_FUEL_PID_CORR@@, "%", -10, 10, -8, -5, 5, 8, 3, 1
|
||||
fuelingLoadGauge = fuelingLoad, @@GAUGE_NAME_FUEL_LOAD@@, "%", 0, 300, 0, 0, 300, 300, 1, 1
|
||||
totalFuelConsumptionGauge = totalFuelConsumption, @@GAUGE_NAME_FUEL_CONSUMPTION@@, "g", 0, 10000, 0, 0, 10000, 10000, 0, 0
|
||||
fuelFlowRateGauge = fuelFlowRate, @@GAUGE_NAME_FUEL_FLOW@@, "g/s", 0, 50, 0, 0, 50, 50, 2, 0
|
||||
|
||||
gaugeCategory = Throttle Body (incl. ETB)
|
||||
pedalPositionGauge = throttlePedalPosition, @@GAUGE_NAME_THROTTLE_PEDAL@@, "%", 0, 120, 0, 0, 100, 100, 1, 1
|
||||
|
@ -1258,6 +1261,8 @@ gaugeCategory = DynoView
|
|||
entry = coilDutyCycle, @@GAUGE_NAME_DWELL_DUTY@@, float,"%.3f"
|
||||
entry = currentTargetAfr,@@GAUGE_NAME_TARGET_AFR@@, float,"%.3f"
|
||||
entry = targetLambda, @@GAUGE_NAME_TARGET_LAMBDA@@, float,"%.4f"
|
||||
entry = totalFuelConsumption, @@GAUGE_NAME_FUEL_CONSUMPTION@@, int, "%d"
|
||||
entry = fuelFlowRate, @@GAUGE_NAME_FUEL_FLOW@@, float, "%.2f"
|
||||
|
||||
entry = accelerationX, @@GAUGE_NAME_ACCEL_X@@, float,"%.2f", { LIS302DLCsPin != 0 }
|
||||
entry = accelerationY, @@GAUGE_NAME_ACCEL_Y@@, float,"%.2f", { LIS302DLCsPin != 0 }
|
||||
|
|
Loading…
Reference in New Issue