mirror of https://github.com/rusefi/rusefi-1.git
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
|
// Fuel system
|
||||||
scaled_percent fuelTankLevel; // 98
|
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
|
// Y axis values for selectable tables
|
||||||
scaled_channel<uint16_t, 100> veTableYAxis; // 104
|
scaled_channel<uint16_t, 100> veTableYAxis; // 104
|
||||||
|
|
|
@ -64,6 +64,8 @@ static const LogField fields[] = {
|
||||||
{tsOutputChannels.ignitionLoad, GAUGE_NAME_IGNITION_LOAD, "%", 1},
|
{tsOutputChannels.ignitionLoad, GAUGE_NAME_IGNITION_LOAD, "%", 1},
|
||||||
{tsOutputChannels.massAirFlow, GAUGE_NAME_AIR_FLOW, "kg/h", 1},
|
{tsOutputChannels.massAirFlow, GAUGE_NAME_AIR_FLOW, "kg/h", 1},
|
||||||
{tsOutputChannels.flexPercent, GAUGE_NAME_FLEX, "%", 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) {
|
void writeHeader(Writer& outBuffer) {
|
||||||
|
|
|
@ -705,7 +705,8 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_
|
||||||
#endif /* EFI_VEHICLE_SPEED */
|
#endif /* EFI_VEHICLE_SPEED */
|
||||||
#endif /* EFI_PROD_CODE */
|
#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->warningCounter = engine->engineState.warnings.warningCounter;
|
||||||
tsOutputChannels->lastErrorCode = engine->engineState.warnings.lastErrorCode;
|
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 */
|
#endif /* EFI_ENABLE_MOCK_ADC */
|
||||||
|
|
||||||
FuelConsumptionState::FuelConsumptionState() {
|
void FuelConsumptionState::consumeFuel(float grams, efitick_t nowNt) {
|
||||||
accumulatedSecondPrevNt = accumulatedMinutePrevNt = getTimeNowNt();
|
m_consumedGrams += grams;
|
||||||
}
|
|
||||||
|
|
||||||
void FuelConsumptionState::addData(float durationMs) {
|
float elapsedSecond = m_timer.getElapsedSecondsAndReset(nowNt);
|
||||||
if (durationMs > 0.0f) {
|
|
||||||
perSecondAccumulator += durationMs;
|
// If it's been a long time since last injection, ignore this pulse
|
||||||
perMinuteAccumulator += durationMs;
|
if (elapsedSecond > 0.2f) {
|
||||||
|
m_rate = 0;
|
||||||
|
} else {
|
||||||
|
m_rate = grams / elapsedSecond;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuelConsumptionState::update(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
float FuelConsumptionState::getConsumedGrams() const {
|
||||||
efitick_t deltaNt = nowNt - accumulatedSecondPrevNt;
|
return m_consumedGrams;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TransmissionState::TransmissionState() {
|
float FuelConsumptionState::getConsumptionGramPerSecond() const {
|
||||||
|
return m_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineState::EngineState() {
|
EngineState::EngineState() {
|
||||||
|
@ -144,9 +135,6 @@ void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
||||||
auto clResult = fuelClosedLoopCorrection(PASS_ENGINE_PARAMETER_SIGNATURE);
|
auto clResult = fuelClosedLoopCorrection(PASS_ENGINE_PARAMETER_SIGNATURE);
|
||||||
running.pidCorrection = clResult.banks[0];
|
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
|
// Fuel cut-off isn't just 0 or 1, it can be tapered
|
||||||
fuelCutoffCorrection = getFuelCutOffCorrection(nowNt, rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
fuelCutoffCorrection = getFuelCutOffCorrection(nowNt, rpm PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "engine_configuration_generated_structures.h"
|
#include "engine_configuration_generated_structures.h"
|
||||||
#include "cyclic_buffer.h"
|
#include "cyclic_buffer.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
#define MOCK_ADC_SIZE 26
|
#define MOCK_ADC_SIZE 26
|
||||||
|
|
||||||
|
@ -39,20 +40,20 @@ public:
|
||||||
|
|
||||||
class FuelConsumptionState {
|
class FuelConsumptionState {
|
||||||
public:
|
public:
|
||||||
FuelConsumptionState();
|
void consumeFuel(float grams, efitick_t nowNt);
|
||||||
void addData(float durationMs);
|
|
||||||
void update(efitick_t nowNt DECLARE_ENGINE_PARAMETER_SUFFIX);
|
float getConsumedGrams() const;
|
||||||
float perSecondConsumption = 0;
|
float getConsumptionGramPerSecond() const;
|
||||||
float perMinuteConsumption = 0;
|
|
||||||
float perSecondAccumulator = 0;
|
private:
|
||||||
float perMinuteAccumulator = 0;
|
float m_consumedGrams = 0;
|
||||||
efitick_t accumulatedSecondPrevNt;
|
float m_rate = 0;
|
||||||
efitick_t accumulatedMinutePrevNt;
|
|
||||||
|
Timer m_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TransmissionState {
|
class TransmissionState {
|
||||||
public:
|
public:
|
||||||
TransmissionState();
|
|
||||||
gear_e gearSelectorPosition;
|
gear_e gearSelectorPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -477,14 +477,4 @@ float getStandardAirCharge(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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
|
#endif
|
||||||
|
|
|
@ -31,6 +31,3 @@ floatms_t getInjectionMass(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX);
|
||||||
percent_t getInjectorDutyCycle(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX);
|
percent_t getInjectorDutyCycle(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX);
|
||||||
|
|
||||||
float getStandardAirCharge(DECLARE_ENGINE_PARAMETER_SIGNATURE);
|
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);
|
obdSendPacket(1, pid, 4, scaled << 16);
|
||||||
break;
|
break;
|
||||||
} case PID_FUEL_RATE:
|
} case PID_FUEL_RATE: {
|
||||||
obdSendValue(_1_MODE, pid, 2, engine->engineState.fuelConsumption.perSecondConsumption * 20.0f); // L/h. (A*256+B)/20
|
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;
|
break;
|
||||||
default:
|
} default:
|
||||||
// ignore unhandled PIDs
|
// ignore unhandled PIDs
|
||||||
break;
|
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
|
// Perform wall wetting adjustment on fuel mass, not duration, so that
|
||||||
// it's correct during fuel pressure (injector flow) or battery voltage (deadtime) transients
|
// 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 float injectionMassGrams = wallFuel.adjust(ENGINE(injectionMass) PASS_ENGINE_PARAMETER_SUFFIX);
|
||||||
const floatms_t injectionDuration = ENGINE(injectorModel)->getInjectionDuration(injectionMass);
|
const floatms_t injectionDuration = ENGINE(injectorModel)->getInjectionDuration(injectionMassGrams);
|
||||||
|
|
||||||
#if EFI_PRINTF_FUEL_DETAILS
|
#if EFI_PRINTF_FUEL_DETAILS
|
||||||
if (printFuelDebug) {
|
if (printFuelDebug) {
|
||||||
|
@ -223,15 +223,13 @@ void InjectionEvent::onTriggerTooth(size_t trgEventIndex, int rpm, efitick_t now
|
||||||
* todo: pre-calculate 'numberOfInjections'
|
* todo: pre-calculate 'numberOfInjections'
|
||||||
* see also injectorDutyCycle
|
* 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);
|
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).consumeFuel(injectionMassGrams * numberOfInjections, nowNt);
|
||||||
engine->engineState.fuelConsumption.addData(injectionDuration - ENGINE(engineState.running.injectorLag));
|
|
||||||
|
|
||||||
ENGINE(actualLastInjection) = injectionDuration;
|
ENGINE(actualLastInjection) = injectionDuration;
|
||||||
if (cisnan(injectionDuration)) {
|
if (cisnan(injectionDuration)) {
|
||||||
warning(CUSTOM_OBD_NAN_INJECTION, "NaN injection pulse");
|
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_AFR_CFG 10
|
||||||
#define PACK_MULT_LAMBDA_CFG 147
|
#define PACK_MULT_LAMBDA_CFG 147
|
||||||
#define PACK_MULT_FUEL_MASS 100
|
#define PACK_MULT_FUEL_MASS 100
|
||||||
|
#define PACK_MULT_FUEL_FLOW 200
|
||||||
#define FSIO_TABLE_8 8
|
#define FSIO_TABLE_8 8
|
||||||
|
|
||||||
#define FSIO_CURVE_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_AMOUNT "fuel: wall amount"
|
||||||
#define GAUGE_NAME_FUEL_WALL_CORRECTION "fuel: wall corr ms"
|
#define GAUGE_NAME_FUEL_WALL_CORRECTION "fuel: wall corr ms"
|
||||||
#define GAUGE_NAME_FUEL_LOAD "fuel: load"
|
#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_FUEL_INJ_DUTY "fuel: injector duty cycle"
|
||||||
#define GAUGE_NAME_TCHARGE "fuel: SD tCharge"
|
#define GAUGE_NAME_TCHARGE "fuel: SD tCharge"
|
||||||
|
|
|
@ -283,8 +283,9 @@ enable2ndByteCanID = false
|
||||||
etb1Error = scalar, S16, 96, "%",{1/@@PACK_MULT_PERCENT@@}, 0
|
etb1Error = scalar, S16, 96, "%",{1/@@PACK_MULT_PERCENT@@}, 0
|
||||||
|
|
||||||
; Fuel system
|
; Fuel system
|
||||||
fuelTankLevel = scalar, S16, 98, "%",{1/@@PACK_MULT_PERCENT@@}, 0
|
fuelTankLevel = scalar, U16, 98, "%",{1/@@PACK_MULT_PERCENT@@}, 0
|
||||||
fuelConsumptionPerHour=scalar,F32, 100, "kPa", 1, 0.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
|
; Y axis values for selectable tables
|
||||||
veTableYAxis = scalar, U16, 104, "%", 0.01, 0
|
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
|
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
|
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
|
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)
|
gaugeCategory = Throttle Body (incl. ETB)
|
||||||
pedalPositionGauge = throttlePedalPosition, @@GAUGE_NAME_THROTTLE_PEDAL@@, "%", 0, 120, 0, 0, 100, 100, 1, 1
|
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 = coilDutyCycle, @@GAUGE_NAME_DWELL_DUTY@@, float,"%.3f"
|
||||||
entry = currentTargetAfr,@@GAUGE_NAME_TARGET_AFR@@, float,"%.3f"
|
entry = currentTargetAfr,@@GAUGE_NAME_TARGET_AFR@@, float,"%.3f"
|
||||||
entry = targetLambda, @@GAUGE_NAME_TARGET_LAMBDA@@, float,"%.4f"
|
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 = accelerationX, @@GAUGE_NAME_ACCEL_X@@, float,"%.2f", { LIS302DLCsPin != 0 }
|
||||||
entry = accelerationY, @@GAUGE_NAME_ACCEL_Y@@, float,"%.2f", { LIS302DLCsPin != 0 }
|
entry = accelerationY, @@GAUGE_NAME_ACCEL_Y@@, float,"%.2f", { LIS302DLCsPin != 0 }
|
||||||
|
|
Loading…
Reference in New Issue