From 942403cec20baf7653e6d871b6a1adbf9d0ff4fc Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Sat, 18 Apr 2020 15:45:30 -0700 Subject: [PATCH] Fuel/ign correctino on new temp sensors (#1318) * corrections * test * adv map * tests * cleanup * lcd * fsio * unneeded * more math * last consumer * cleanup * fix kinetis --- firmware/controllers/algo/advance_map.cpp | 8 +++-- firmware/controllers/algo/engine2.cpp | 2 +- firmware/controllers/algo/fuel_math.cpp | 23 ++++++++---- firmware/controllers/algo/fuel_math.h | 2 +- firmware/controllers/core/fsio_impl.cpp | 7 ++-- .../engine_cycle/main_trigger_callback.cpp | 4 +-- .../controllers/gauges/lcd_controller.cpp | 4 +-- firmware/controllers/sensors/thermistors.cpp | 35 ++----------------- firmware/controllers/sensors/thermistors.h | 15 -------- unit_tests/tests/test_fuel_map.cpp | 23 +++++++----- unit_tests/tests/test_idle_controller.cpp | 4 --- unit_tests/tests/test_trigger_decoder.cpp | 2 ++ 12 files changed, 50 insertions(+), 79 deletions(-) diff --git a/firmware/controllers/algo/advance_map.cpp b/firmware/controllers/algo/advance_map.cpp index 0f7eeb35a5..68fc648fbe 100644 --- a/firmware/controllers/algo/advance_map.cpp +++ b/firmware/controllers/algo/advance_map.cpp @@ -124,11 +124,15 @@ static angle_t getRunningAdvance(int rpm, float engineLoad DECLARE_ENGINE_PARAME angle_t getAdvanceCorrections(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX) { float iatCorrection; - if (!hasIatSensor()) { + + const auto [iatValid, iat] = Sensor::get(SensorType::Iat); + + if (!iatValid) { iatCorrection = 0; } else { - iatCorrection = iatAdvanceCorrectionMap.getValue((float) rpm, getIntakeAirTemperature()); + iatCorrection = iatAdvanceCorrectionMap.getValue((float) rpm, iat); } + // PID Ignition Advance angle correction float pidTimingCorrection = 0.0f; if (CONFIG(useIdleTimingPidControl)) { diff --git a/firmware/controllers/algo/engine2.cpp b/firmware/controllers/algo/engine2.cpp index 3b623586b9..b3aedd9c0f 100644 --- a/firmware/controllers/algo/engine2.cpp +++ b/firmware/controllers/algo/engine2.cpp @@ -154,7 +154,7 @@ void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) { } // todo: move this into slow callback, no reason for IAT corr to be here - running.intakeTemperatureCoefficient = getIatFuelCorrection(getIntakeAirTemperature() PASS_ENGINE_PARAMETER_SUFFIX); + running.intakeTemperatureCoefficient = getIatFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); // todo: move this into slow callback, no reason for CLT corr to be here running.coolantTemperatureCoefficient = getCltFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); diff --git a/firmware/controllers/algo/fuel_math.cpp b/firmware/controllers/algo/fuel_math.cpp index 90242f5af7..0561c5c1e0 100644 --- a/firmware/controllers/algo/fuel_math.cpp +++ b/firmware/controllers/algo/fuel_math.cpp @@ -336,20 +336,29 @@ void initFuelMap(DECLARE_ENGINE_PARAMETER_SIGNATURE) { * @brief Engine warm-up fuel correction. */ float getCltFuelCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE) { - if (!hasCltSensor()) + const auto [valid, clt] = Sensor::get(SensorType::Clt); + + if (!valid) return 1; // this error should be already reported somewhere else, let's just handle it - return interpolate2d("cltf", getCoolantTemperature(), config->cltFuelCorrBins, config->cltFuelCorr); + + return interpolate2d("cltf", clt, config->cltFuelCorrBins, config->cltFuelCorr); } angle_t getCltTimingCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE) { - if (!hasCltSensor()) + const auto [valid, clt] = Sensor::get(SensorType::Clt); + + if (!valid) return 0; // this error should be already reported somewhere else, let's just handle it - return interpolate2d("timc", getCoolantTemperature(), engineConfiguration->cltTimingBins, engineConfiguration->cltTimingExtra); + + return interpolate2d("timc", clt, engineConfiguration->cltTimingBins, engineConfiguration->cltTimingExtra); } -float getIatFuelCorrection(float iat DECLARE_ENGINE_PARAMETER_SUFFIX) { - if (cisnan(iat)) +float getIatFuelCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE) { + const auto [valid, iat] = Sensor::get(SensorType::Iat); + + if (!valid) return 1; // this error should be already reported somewhere else, let's just handle it + return interpolate2d("iatc", iat, config->iatFuelCorrBins, config->iatFuelCorr); } @@ -440,7 +449,7 @@ float getBaroCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE) { * @return Duration of fuel injection while craning */ floatms_t getCrankingFuel(DECLARE_ENGINE_PARAMETER_SIGNATURE) { - return getCrankingFuel3(getCoolantTemperature(), + return getCrankingFuel3(Sensor::get(SensorType::Clt).value_or(20), engine->rpmCalculator.getRevolutionCounterSinceStart() PASS_ENGINE_PARAMETER_SUFFIX); } #endif diff --git a/firmware/controllers/algo/fuel_math.h b/firmware/controllers/algo/fuel_math.h index 2cb54e0524..2680a94be3 100644 --- a/firmware/controllers/algo/fuel_math.h +++ b/firmware/controllers/algo/fuel_math.h @@ -27,7 +27,7 @@ floatms_t getBaseTableFuel(int rpm, float engineLoad); float getBaroCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE); int getNumberOfInjections(injection_mode_e mode DECLARE_ENGINE_PARAMETER_SUFFIX); angle_t getInjectionOffset(float rpm DECLARE_ENGINE_PARAMETER_SUFFIX); -float getIatFuelCorrection(float iat DECLARE_ENGINE_PARAMETER_SUFFIX); +float getIatFuelCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE); floatms_t getInjectorLag(float vBatt DECLARE_ENGINE_PARAMETER_SUFFIX); float getCltFuelCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE); float getFuelCutOffCorrection(efitick_t nowNt, int rpm DECLARE_ENGINE_PARAMETER_SUFFIX); diff --git a/firmware/controllers/core/fsio_impl.cpp b/firmware/controllers/core/fsio_impl.cpp index 7bf260de94..5486e1bb3f 100644 --- a/firmware/controllers/core/fsio_impl.cpp +++ b/firmware/controllers/core/fsio_impl.cpp @@ -14,6 +14,7 @@ #include "global.h" #include "fsio_impl.h" #include "allsensors.h" +#include "sensor.h" EXTERN_ENGINE; @@ -24,7 +25,6 @@ EXTERN_ENGINE; #include "rpm_calculator.h" #include "efi_gpio.h" #include "pwm_generator_logic.h" -#include "sensor.h" /** * in case of zero frequency pin is operating as simple on/off. '1' for ON and '0' for OFF @@ -748,8 +748,9 @@ void runHardcodedFsio(DECLARE_ENGINE_PARAMETER_SIGNATURE) { } // see FAN_CONTROL_LOGIC if (CONFIG(fanPin) != GPIO_UNASSIGNED) { - enginePins.fanRelay.setValue((enginePins.fanRelay.getLogicValue() && (getCoolantTemperature() > engineConfiguration->fanOffTemperature)) || - (getCoolantTemperature() > engineConfiguration->fanOnTemperature) || engine->isCltBroken); + auto clt = Sensor::get(SensorType::Clt); + enginePins.fanRelay.setValue(!clt.Valid || (enginePins.fanRelay.getLogicValue() && (clt.Value > engineConfiguration->fanOffTemperature)) || + (clt.Value > engineConfiguration->fanOnTemperature) || engine->isCltBroken); } // see AC_RELAY_LOGIC if (CONFIG(acRelayPin) != GPIO_UNASSIGNED) { diff --git a/firmware/controllers/engine_cycle/main_trigger_callback.cpp b/firmware/controllers/engine_cycle/main_trigger_callback.cpp index 2051a0b892..5d1c2c9ed8 100644 --- a/firmware/controllers/engine_cycle/main_trigger_callback.cpp +++ b/firmware/controllers/engine_cycle/main_trigger_callback.cpp @@ -276,7 +276,7 @@ static ALWAYS_INLINE void handleFuelInjectionEvent(int injEventIndex, InjectionE static void fuelClosedLoopCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE) { #if ! EFI_UNIT_TEST if (GET_RPM_VALUE < CONFIG(fuelClosedLoopRpmThreshold) || - getCoolantTemperature() < CONFIG(fuelClosedLoopCltThreshold) || + Sensor::get(SensorType::Clt).value_or(0) < CONFIG(fuelClosedLoopCltThreshold) || Sensor::get(SensorType::Tps1).value_or(100) > CONFIG(fuelClosedLoopTpsThreshold) || ENGINE(sensors.currentAfr) < CONFIG(fuelClosedLoopAfrLowThreshold) || ENGINE(sensors.currentAfr) > engineConfiguration->fuelClosedLoopAfrHighThreshold) { @@ -491,7 +491,7 @@ void startPrimeInjectionPulse(DECLARE_ENGINE_PARAMETER_SIGNATURE) { // If 'primeInjFalloffTemperature' is not specified (by default), we have a prime pulse deactivation at zero celsius degrees, which is okay. const float maxPrimeInjAtTemperature = -40.0f; // at this temperature the pulse is maximal. floatms_t pulseLength = interpolateClamped(maxPrimeInjAtTemperature, CONFIG(startOfCrankingPrimingPulse), - CONFIG(primeInjFalloffTemperature), 0.0f, getCoolantTemperature()); + CONFIG(primeInjFalloffTemperature), 0.0f, Sensor::get(SensorType::Clt).value_or(70)); if (pulseLength > 0) { startSimultaniousInjection(engine); efitimeus_t turnOffDelayUs = (efitimeus_t)efiRound(MS2US(pulseLength), 1.0f); diff --git a/firmware/controllers/gauges/lcd_controller.cpp b/firmware/controllers/gauges/lcd_controller.cpp index d3480fba4f..669a080830 100644 --- a/firmware/controllers/gauges/lcd_controller.cpp +++ b/firmware/controllers/gauges/lcd_controller.cpp @@ -174,7 +174,7 @@ static void showLine(lcd_line_e line, int screenY) { lcdPrintf("Coolant %.2f", Sensor::get(SensorType::Clt).value_or(0)); return; case LL_IAT_TEMPERATURE: - lcdPrintf("Intake Air %.2f", getIntakeAirTemperature()); + lcdPrintf("Intake Air %.2f", Sensor::get(SensorType::Iat).value_or(0)); return; case LL_ALGORITHM: lcdPrintf(getEngine_load_mode_e(engineConfiguration->fuelAlgorithm)); @@ -197,7 +197,7 @@ static void showLine(lcd_line_e line, int screenY) { lcdPrintf("CLT corr %.2f", getCltFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE)); return; case LL_FUEL_IAT_CORRECTION: - lcdPrintf("IAT corr %.2f", getIatFuelCorrection(getIntakeAirTemperature() PASS_ENGINE_PARAMETER_SIGNATURE)); + lcdPrintf("IAT corr %.2f", getIatFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE)); return; case LL_FUEL_INJECTOR_LAG: lcdPrintf("ING LAG %.2f", getInjectorLag(engine->sensors.vBatt PASS_ENGINE_PARAMETER_SIGNATURE)); diff --git a/firmware/controllers/sensors/thermistors.cpp b/firmware/controllers/sensors/thermistors.cpp index 1d83d9eca9..e102ce05c7 100644 --- a/firmware/controllers/sensors/thermistors.cpp +++ b/firmware/controllers/sensors/thermistors.cpp @@ -55,21 +55,6 @@ float ThermistorMath::getKelvinTemperatureByResistance(float resistance) const { return 1 / (s_h_a + s_h_b * logR + s_h_c * logR * logR * logR); } -/* -float convertCelsiustoF(temperature_t tempC) { - return tempC * 9 / 5 + 32; -} - -temperature_t convertFtoCelsius(float tempF) { - return (tempF - 32) / 9 * 5; -} - -float convertKelvinToFahrenheit(float kelvin) { - float tempC = convertKelvinToCelcius(kelvin); - return convertCelsiustoF(tempC); -} -*/ - float getResistance(ThermistorConf *config, float voltage) { efiAssert(CUSTOM_ERR_ASSERT, config != NULL, "thermistor config is null", NAN); thermistor_conf_s *tc = &config->config; @@ -113,24 +98,16 @@ temperature_t getTemperatureC(ThermistorConf *cfg, ThermistorMath *tm, bool useL return convertKelvinToCelcius(kelvinTemperature); } -bool isValidCoolantTemperature(temperature_t temperature) { +static bool isValidCoolantTemperature(temperature_t temperature) { // I hope magic constants are appropriate here return !cisnan(temperature) && temperature > -50 && temperature < 250; } -bool isValidIntakeAirTemperature(temperature_t temperature) { +static bool isValidIntakeAirTemperature(temperature_t temperature) { // I hope magic constants are appropriate here return !cisnan(temperature) && temperature > -50 && temperature < 100; } -bool hasCltSensorM(DECLARE_ENGINE_PARAMETER_SIGNATURE) { - bool haveSensorChannel = engineConfiguration->clt.adcChannel != EFI_ADC_NONE; - if (!haveSensorChannel) { - return false; - } - return !cisnan(engine->sensors.clt); -} - /** * @return coolant temperature, in Celsius */ @@ -209,14 +186,6 @@ void ThermistorMath::prepareThermistorCurve(thermistor_conf_s *tc) { #endif } -bool hasIatSensorM(DECLARE_ENGINE_PARAMETER_SIGNATURE) { - bool haveSensorChannel = engineConfiguration->iat.adcChannel != EFI_ADC_NONE; - if (!haveSensorChannel) { - return false; - } - return !cisnan(engine->sensors.iat); -} - /** * @return Celsius value */ diff --git a/firmware/controllers/sensors/thermistors.h b/firmware/controllers/sensors/thermistors.h index 79e1cf5ce0..ee3e1e2c5d 100644 --- a/firmware/controllers/sensors/thermistors.h +++ b/firmware/controllers/sensors/thermistors.h @@ -32,23 +32,8 @@ float getKelvinTemperature(float resistance, ThermistorMath *tm); float getResistance(ThermistorConf *cfg, float voltage); temperature_t getTemperatureC(ThermistorConf *cfg, ThermistorMath *tm, bool useLinear DECLARE_ENGINE_PARAMETER_SUFFIX); temperature_t getCoolantTemperatureM(DECLARE_ENGINE_PARAMETER_SIGNATURE); -bool isValidCoolantTemperature(temperature_t temperature); temperature_t getIntakeAirTemperatureM(DECLARE_ENGINE_PARAMETER_SIGNATURE); -/** - * This macro points to readily-available pre-calculated value - * for actual slow calculation see 'getCoolantTemperatureM' - */ -#define getCoolantTemperature() engine->sensors.clt -#define getIntakeAirTemperature() engine->sensors.iat - -bool isValidIntakeAirTemperature(temperature_t temperature); -bool hasIatSensorM(DECLARE_ENGINE_PARAMETER_SIGNATURE); -bool hasCltSensorM(DECLARE_ENGINE_PARAMETER_SIGNATURE); - -#define hasIatSensor() hasIatSensorM(PASS_ENGINE_PARAMETER_SIGNATURE) -#define hasCltSensor() hasCltSensorM(PASS_ENGINE_PARAMETER_SIGNATURE) - void initThermistors(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX); void setCommonNTCSensor(ThermistorConf *thermistorConf, float pullup); diff --git a/unit_tests/tests/test_fuel_map.cpp b/unit_tests/tests/test_fuel_map.cpp index d283338255..ba5d1ca698 100644 --- a/unit_tests/tests/test_fuel_map.cpp +++ b/unit_tests/tests/test_fuel_map.cpp @@ -33,8 +33,6 @@ TEST(misc, testMafFuelMath) { } TEST(misc, testFuelMap) { - printf("====================================================================================== testFuelMap\r\n"); - printf("Setting up FORD_ASPIRE_1996\r\n"); WITH_ENGINE_TEST_HELPER(FORD_ASPIRE_1996); @@ -76,23 +74,26 @@ TEST(misc, testFuelMap) { printf("*************************************************** setting IAT table\r\n"); for (int i = 0; i < IAT_CURVE_SIZE; i++) { - eth.engine.config->iatFuelCorrBins[i] = i; + eth.engine.config->iatFuelCorrBins[i] = i * 10; eth.engine.config->iatFuelCorr[i] = 2 * i; } eth.engine.config->iatFuelCorr[0] = 2; printf("*************************************************** setting CLT table\r\n"); for (int i = 0; i < CLT_CURVE_SIZE; i++) { - eth.engine.config->cltFuelCorrBins[i] = i; - eth.engine.config->cltFuelCorr[i] = 1; + eth.engine.config->cltFuelCorrBins[i] = i * 10; + eth.engine.config->cltFuelCorr[i] = i; } + Sensor::setMockValue(SensorType::Clt, 70.0f); + Sensor::setMockValue(SensorType::Iat, 30.0f); + setFlatInjectorLag(0 PASS_CONFIG_PARAMETER_SUFFIX); - float iatCorrection = getIatFuelCorrection(-KELV PASS_ENGINE_PARAMETER_SUFFIX); - ASSERT_EQ( 2, iatCorrection) << "IAT"; + float iatCorrection = getIatFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); + ASSERT_EQ( 6, iatCorrection) << "IAT"; float cltCorrection = getCltFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE); - ASSERT_EQ( 1, cltCorrection) << "CLT"; + ASSERT_EQ( 7, cltCorrection) << "CLT"; float injectorLag = getInjectorLag(getVBatt(PASS_ENGINE_PARAMETER_SIGNATURE) PASS_ENGINE_PARAMETER_SUFFIX); ASSERT_EQ( 0, injectorLag) << "injectorLag"; @@ -102,7 +103,11 @@ TEST(misc, testFuelMap) { printf("*************************************************** getRunningFuel 2\r\n"); eth.engine.periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE); baseFuel = getBaseTableFuel(5, getEngineLoadT(PASS_ENGINE_PARAMETER_SIGNATURE)); - ASSERT_EQ( 30150, getRunningFuel(baseFuel PASS_ENGINE_PARAMETER_SUFFIX)) << "v1"; + EXPECT_EQ(baseFuel, 1005); + + // Check that runningFuel corrects appropriately + EXPECT_EQ( 42, getRunningFuel(1 PASS_ENGINE_PARAMETER_SUFFIX)) << "v1"; + EXPECT_EQ( 84, getRunningFuel(2 PASS_ENGINE_PARAMETER_SUFFIX)) << "v1"; testMafValue = 0; diff --git a/unit_tests/tests/test_idle_controller.cpp b/unit_tests/tests/test_idle_controller.cpp index 47332d085d..2dc487cc5c 100644 --- a/unit_tests/tests/test_idle_controller.cpp +++ b/unit_tests/tests/test_idle_controller.cpp @@ -82,10 +82,6 @@ TEST(idle, timingPid) { engineConfiguration->idlePidDeactivationTpsThreshold = 10; Sensor::setMockValue(SensorType::Tps1, 0); - // disable temperature sensors - eth.engine.sensors.clt = NAN; - eth.engine.sensors.iat = NAN; - // all corrections disabled, should be 0 engineConfiguration->useIdleTimingPidControl = false; angle_t corr = getAdvanceCorrections(idleRpmTarget PASS_ENGINE_PARAMETER_SUFFIX); diff --git a/unit_tests/tests/test_trigger_decoder.cpp b/unit_tests/tests/test_trigger_decoder.cpp index d65e8d0dd5..73c9728749 100644 --- a/unit_tests/tests/test_trigger_decoder.cpp +++ b/unit_tests/tests/test_trigger_decoder.cpp @@ -153,6 +153,8 @@ TEST(misc, test1995FordInline6TriggerDecoder) { WITH_ENGINE_TEST_HELPER(FORD_INLINE_6_1995); + Sensor::setMockValue(SensorType::Iat, 49.579071f); + TriggerWaveform * shape = &engine->triggerCentral.triggerShape; ASSERT_EQ( 0, shape->getTriggerWaveformSynchPointIndex()) << "triggerShapeSynchPointIndex";