2021-07-25 22:05:17 -07:00
|
|
|
#include "pch.h"
|
|
|
|
|
2020-08-17 02:22:25 -07:00
|
|
|
#include "injector_model.h"
|
2021-11-05 19:29:56 -07:00
|
|
|
#include "fuel_computer.h"
|
2020-08-17 02:22:25 -07:00
|
|
|
|
|
|
|
void InjectorModelBase::prepare() {
|
|
|
|
m_massFlowRate = getInjectorMassFlowRate();
|
2020-10-23 17:25:47 -07:00
|
|
|
float deadtime = getDeadtime();
|
|
|
|
m_deadtime = deadtime;
|
|
|
|
|
|
|
|
postState(deadtime);
|
2020-08-17 02:22:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
constexpr float convertToGramsPerSecond(float ccPerMinute) {
|
2021-11-05 19:29:56 -07:00
|
|
|
return ccPerMinute * (fuelDensity / 60.f);
|
2020-08-17 02:22:25 -07:00
|
|
|
}
|
|
|
|
|
2020-11-10 20:11:22 -08:00
|
|
|
expected<float> InjectorModel::getAbsoluteRailPressure() const {
|
2021-11-17 00:54:21 -08:00
|
|
|
switch (engineConfiguration->injectorCompensationMode) {
|
2020-11-10 20:11:22 -08:00
|
|
|
case ICM_FixedRailPressure:
|
2021-05-30 16:23:29 -07:00
|
|
|
// Add barometric pressure, as "fixed" really means "fixed pressure above atmosphere"
|
2021-11-17 00:54:21 -08:00
|
|
|
return engineConfiguration->fuelReferencePressure + Sensor::get(SensorType::BarometricPressure).value_or(101.325f);
|
2020-11-10 20:11:22 -08:00
|
|
|
case ICM_SensedRailPressure:
|
2021-03-12 20:32:41 -08:00
|
|
|
if (!Sensor::hasSensor(SensorType::FuelPressureInjector)) {
|
|
|
|
firmwareError(OBD_PCM_Processor_Fault, "Fuel pressure compensation is set to use a pressure sensor, but none is configured.");
|
|
|
|
return unexpected;
|
|
|
|
}
|
|
|
|
|
2020-11-10 20:11:22 -08:00
|
|
|
// TODO: what happens when the sensor fails?
|
|
|
|
return Sensor::get(SensorType::FuelPressureInjector);
|
|
|
|
default: return unexpected;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-26 09:59:53 -08:00
|
|
|
float InjectorModel::getInjectorFlowRatio() {
|
2020-11-10 20:11:22 -08:00
|
|
|
// Compensation disabled, use reference flow.
|
2021-11-17 00:54:21 -08:00
|
|
|
if (engineConfiguration->injectorCompensationMode == ICM_None) {
|
2020-11-10 20:11:22 -08:00
|
|
|
return 1.0f;
|
|
|
|
}
|
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
float referencePressure = engineConfiguration->fuelReferencePressure;
|
2020-11-10 20:11:22 -08:00
|
|
|
expected<float> absRailPressure = getAbsoluteRailPressure();
|
|
|
|
|
|
|
|
// If sensor failed, best we can do is disable correction
|
|
|
|
if (!absRailPressure) {
|
|
|
|
return 1.0f;
|
|
|
|
}
|
|
|
|
|
2021-01-02 16:13:10 -08:00
|
|
|
auto map = Sensor::get(SensorType::Map);
|
|
|
|
|
|
|
|
// Map has failed, assume nominal pressure
|
|
|
|
if (!map) {
|
|
|
|
return 1.0f;
|
|
|
|
}
|
2020-11-10 20:11:22 -08:00
|
|
|
|
2021-12-26 09:59:53 -08:00
|
|
|
pressureDelta = absRailPressure.Value - map.Value;
|
2021-03-12 20:32:41 -08:00
|
|
|
|
|
|
|
// Somehow pressure delta is less than 0, assume failed sensor and return default flow
|
|
|
|
if (pressureDelta <= 0) {
|
|
|
|
return 1.0f;
|
|
|
|
}
|
|
|
|
|
2021-12-26 09:59:53 -08:00
|
|
|
pressureRatio = pressureDelta / referencePressure;
|
|
|
|
// todo: live data model?
|
2020-11-10 20:11:22 -08:00
|
|
|
float flowRatio = sqrtf(pressureRatio);
|
|
|
|
|
|
|
|
#if EFI_TUNER_STUDIO
|
2021-12-07 17:18:47 -08:00
|
|
|
engine->outputChannels.injectorFlowPressureDelta = pressureDelta;
|
|
|
|
engine->outputChannels.injectorFlowPressureRatio = pressureRatio;
|
2020-11-10 20:11:22 -08:00
|
|
|
#endif // EFI_TUNER_STUDIO
|
|
|
|
|
|
|
|
// TODO: should the flow ratio be clamped?
|
|
|
|
return flowRatio;
|
|
|
|
}
|
|
|
|
|
2021-12-26 09:59:53 -08:00
|
|
|
float InjectorModel::getInjectorMassFlowRate() {
|
2020-11-10 20:11:22 -08:00
|
|
|
// TODO: injector flow dependent upon temperature/ethanol content?
|
2021-11-17 00:54:21 -08:00
|
|
|
auto injectorVolumeFlow = engineConfiguration->injector.flow;
|
2020-11-10 20:11:22 -08:00
|
|
|
|
|
|
|
float flowRatio = getInjectorFlowRatio();
|
|
|
|
|
|
|
|
return flowRatio * convertToGramsPerSecond(injectorVolumeFlow);
|
2020-08-17 02:22:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
float InjectorModel::getDeadtime() const {
|
|
|
|
return interpolate2d(
|
2021-03-11 20:07:18 -08:00
|
|
|
Sensor::get(SensorType::BatteryVoltage).value_or(VBAT_FALLBACK_VALUE),
|
2020-08-17 02:22:25 -07:00
|
|
|
engineConfiguration->injector.battLagCorrBins,
|
|
|
|
engineConfiguration->injector.battLagCorr
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-10-23 17:25:47 -07:00
|
|
|
void InjectorModel::postState(float deadtime) const {
|
|
|
|
engine->engineState.running.injectorLag = deadtime;
|
|
|
|
}
|
|
|
|
|
2020-08-17 02:22:25 -07:00
|
|
|
float InjectorModelBase::getInjectionDuration(float fuelMassGram) const {
|
|
|
|
// TODO: support injector nonlinearity correction
|
|
|
|
|
|
|
|
floatms_t baseDuration = fuelMassGram / m_massFlowRate * 1000;
|
2020-10-26 04:23:13 -07:00
|
|
|
|
|
|
|
if (baseDuration <= 0) {
|
2021-07-07 20:46:44 -07:00
|
|
|
// If 0 duration, don't correct or add deadtime, just skip the injection.
|
2020-10-26 04:23:13 -07:00
|
|
|
return 0.0f;
|
|
|
|
}
|
2021-07-07 20:46:44 -07:00
|
|
|
|
|
|
|
// Correct short pulses (if enabled)
|
|
|
|
baseDuration = correctShortPulse(baseDuration);
|
|
|
|
|
|
|
|
return baseDuration + m_deadtime;
|
2020-08-17 02:22:25 -07:00
|
|
|
}
|
2021-03-03 04:30:56 -08:00
|
|
|
|
|
|
|
float InjectorModelBase::getFuelMassForDuration(floatms_t duration) const {
|
|
|
|
// Convert from ms -> grams
|
|
|
|
return duration * m_massFlowRate * 0.001f;
|
|
|
|
}
|
2021-07-07 20:46:44 -07:00
|
|
|
|
|
|
|
float InjectorModel::correctShortPulse(float baseDuration) const {
|
2021-11-17 00:54:21 -08:00
|
|
|
switch (engineConfiguration->injectorNonlinearMode) {
|
2021-07-07 20:46:44 -07:00
|
|
|
case INJ_PolynomialAdder:
|
|
|
|
return correctInjectionPolynomial(baseDuration);
|
|
|
|
case INJ_None:
|
|
|
|
default:
|
|
|
|
return baseDuration;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float InjectorModel::correctInjectionPolynomial(float baseDuration) const {
|
2022-04-28 05:16:02 -07:00
|
|
|
if (baseDuration > engineConfiguration->applyNonlinearBelowPulse) {
|
2021-07-07 20:46:44 -07:00
|
|
|
// Large pulse, skip correction.
|
|
|
|
return baseDuration;
|
|
|
|
}
|
|
|
|
|
2021-11-17 00:54:21 -08:00
|
|
|
auto& is = engineConfiguration->injectorCorrectionPolynomial;
|
2021-07-07 20:46:44 -07:00
|
|
|
float xi = 1;
|
|
|
|
|
|
|
|
float adder = 0;
|
|
|
|
|
|
|
|
// Add polynomial terms, starting with x^0
|
|
|
|
for (size_t i = 0; i < efi::size(is); i++) {
|
|
|
|
adder += is[i] * xi;
|
|
|
|
xi *= baseDuration;
|
|
|
|
}
|
|
|
|
|
|
|
|
return baseDuration + adder;
|
|
|
|
}
|