New clt consumers part 1 (#1301)

* idle

* CLT test prep

* idle target

* header

* air interpolate

* ancient comment

* fuel cut

* fuel cut, idle tests

* cleanup
This commit is contained in:
Matthew Kennedy 2020-04-15 06:48:17 -07:00 committed by GitHub
parent ccee238867
commit 044766ec70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 55 additions and 46 deletions

View File

@ -353,9 +353,6 @@ static void printSensors(Logging *log) {
reportSensorF(log, GAUGE_NAME_DWELL_DUTY, "%", getCoilDutyCycle(rpm PASS_ENGINE_PARAMETER_SUFFIX), 2);
// debugFloat(&logger, "tch", getTCharge1(tps), 2);
for (int i = 0;i<FSIO_ANALOG_INPUT_COUNT;i++) {
if (engineConfiguration->fsioAdc[i] != EFI_ADC_NONE) {
strcpy(buf, "adcX");

View File

@ -318,8 +318,9 @@ static percent_t automaticIdleController(float tpsPos DECLARE_ENGINE_PARAMETER_S
int idlePidLowerRpm = targetRpm + CONFIG(idlePidRpmDeadZone);
if (CONFIG(idlePidRpmUpperLimit) > 0) {
engine->engineState.idle.idleState = PID_UPPER;
if (CONFIG(useIacTableForCoasting) && hasCltSensor()) {
percent_t iacPosForCoasting = interpolate2d("iacCoasting", getCoolantTemperature(), CONFIG(iacCoastingBins), CONFIG(iacCoasting));
const auto [cltValid, clt] = Sensor::get(SensorType::Clt);
if (CONFIG(useIacTableForCoasting) && cltValid) {
percent_t iacPosForCoasting = interpolate2d("iacCoasting", clt, CONFIG(iacCoastingBins), CONFIG(iacCoasting));
newValue = interpolateClamped(idlePidLowerRpm, newValue, idlePidLowerRpm + CONFIG(idlePidRpmUpperLimit), iacPosForCoasting, rpm);
} else {
// Well, just leave it as is, without PID regulation...
@ -390,7 +391,7 @@ static percent_t automaticIdleController(float tpsPos DECLARE_ENGINE_PARAMETER_S
finishIdleTestIfNeeded();
undoIdleBlipIfNeeded();
float clt = getCoolantTemperature();
const auto [cltValid, clt] = Sensor::get(SensorType::Clt);
#if EFI_SHAFT_POSITION_INPUT
bool isRunning = engine->rpmCalculator.isRunning(PASS_ENGINE_PARAMETER_SIGNATURE);
#else
@ -398,7 +399,7 @@ static percent_t automaticIdleController(float tpsPos DECLARE_ENGINE_PARAMETER_S
#endif /* EFI_SHAFT_POSITION_INPUT */
// cltCorrection is used only for cranking or running in manual mode
float cltCorrection;
if (!hasCltSensor())
if (!cltValid)
cltCorrection = 1.0f;
// Use separate CLT correction table for cranking
else if (engineConfiguration->overrideCrankingIacSetting && !isRunning) {

View File

@ -220,7 +220,7 @@ void EngineState::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
void EngineState::updateTChargeK(int rpm, float tps DECLARE_ENGINE_PARAMETER_SUFFIX) {
#if EFI_ENGINE_CONTROL
float newTCharge = getTCharge(rpm, tps, getCoolantTemperature(), getIntakeAirTemperature() PASS_ENGINE_PARAMETER_SUFFIX);
float newTCharge = getTCharge(rpm, tps PASS_ENGINE_PARAMETER_SUFFIX);
// convert to microsecs and then to seconds
efitick_t curTime = getTimeNowNt();
float secsPassed = (float)NT2US(curTime - timeSinceLastTChargeK) / 1000000.0f;

View File

@ -29,6 +29,7 @@
#include "engine_math.h"
#include "speed_density.h"
#include "advance_map.h"
#include "sensor.h"
#include "hip9011_lookup.h"
#if EFI_MEMS
@ -609,14 +610,11 @@ void setTargetRpmCurve(int rpm DECLARE_CONFIG_PARAMETER_SUFFIX) {
}
int getTargetRpmForIdleCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
float clt = getCoolantTemperature();
int targetRpm;
if (!hasCltSensor()) {
// error is already reported, let's take first value from the table should be good enough error handing solution
targetRpm = CONFIG(cltIdleRpm)[0];
} else {
targetRpm = interpolate2d("cltRpm", clt, CONFIG(cltIdleRpmBins), CONFIG(cltIdleRpm));
}
// error is already reported, let's take the value at 0C since that should be a nice high idle
float clt = Sensor::get(SensorType::Clt).value_or(0);
int targetRpm = interpolate2d("cltRpm", clt, CONFIG(cltIdleRpmBins), CONFIG(cltIdleRpm));
return targetRpm + engine->fsioState.fsioIdleTargetRPMAdjustment;
}

View File

@ -364,8 +364,13 @@ float getFuelCutOffCorrection(efitick_t nowNt, int rpm DECLARE_ENGINE_PARAMETER_
// coasting fuel cut-off correction
if (CONFIG(coastingFuelCutEnabled)) {
auto [valid, tpsPos] = Sensor::get(SensorType::Tps1);
if (!valid) {
auto [tpsValid, tpsPos] = Sensor::get(SensorType::Tps1);
if (!tpsValid) {
return 1.0f;
}
const auto [cltValid, clt] = Sensor::get(SensorType::Clt);
if (!cltValid) {
return 1.0f;
}
@ -375,7 +380,7 @@ float getFuelCutOffCorrection(efitick_t nowNt, int rpm DECLARE_ENGINE_PARAMETER_
bool mapDeactivate = (map >= CONFIG(coastingFuelCutMap));
bool tpsDeactivate = (tpsPos >= CONFIG(coastingFuelCutTps));
// If no CLT sensor (or broken), don't allow DFCO
bool cltDeactivate = hasCltSensor() ? (getCoolantTemperature() < (float)CONFIG(coastingFuelCutClt)) : true;
bool cltDeactivate = clt < (float)CONFIG(coastingFuelCutClt);
bool rpmDeactivate = (rpm < CONFIG(coastingFuelCutRpmLow));
bool rpmActivate = (rpm > CONFIG(coastingFuelCutRpmHigh));

View File

@ -16,6 +16,7 @@
#include "maf2map.h"
#include "config_engine_specs.h"
#include "perf_trace.h"
#include "sensor.h"
#if defined(HAS_OS_ACCESS)
#error "Unexpected OS ACCESS HERE"
@ -35,10 +36,13 @@ baroCorr_Map3D_t baroCorrMap("baro");
#define tpMax 100
// http://rusefi.com/math/t_charge.html
/***panel:Charge Temperature*/
temperature_t getTCharge(int rpm, float tps, float coolantTemp, float airTemp DECLARE_ENGINE_PARAMETER_SUFFIX) {
if (cisnan(coolantTemp) || cisnan(airTemp)) {
warning(CUSTOM_ERR_NAN_TCHARGE, "t-getTCharge NaN");
return coolantTemp;
temperature_t getTCharge(int rpm, float tps DECLARE_ENGINE_PARAMETER_SUFFIX) {
const auto [cltValid, coolantTemp] = Sensor::get(SensorType::Clt);
const auto [iatValid, airTemp] = Sensor::get(SensorType::Iat);
if (!cltValid || !iatValid) {
warning(CUSTOM_ERR_NAN_TCHARGE, "getTCharge invalid iat/clt");
return airTemp;
}
DISPLAY_STATE(Engine)

View File

@ -10,7 +10,7 @@
#define gramm_second_to_cc_minute(gs) ((gs) / 0.0119997981)
#define cc_minute_to_gramm_second(ccm) ((ccm) * 0.0119997981)
temperature_t getTCharge(int rpm, float tps, float coolantTemperature, float airTemperature DECLARE_ENGINE_PARAMETER_SUFFIX);
temperature_t getTCharge(int rpm, float tps DECLARE_ENGINE_PARAMETER_SUFFIX);
float getCylinderAirMass(float volumetricEfficiency, float MAP, float tempK DECLARE_ENGINE_PARAMETER_SUFFIX);
float sdMath(float airMass, float AFR DECLARE_ENGINE_PARAMETER_SUFFIX);

View File

@ -65,9 +65,10 @@ EngineTestHelper::EngineTestHelper(engine_type_e engineType, configuration_callb
engine->engineConfigurationPtr->iat.adcChannel = TEST_IAT_CHANNEL;
// magic voltage to get nice CLT
testCltValue = 1.492964;
//todosetMockCltVoltage(1.492964 PASS_ENGINE_PARAMETER_SUFFIX);
Sensor::setMockValue(SensorType::Clt, 70);
// magic voltage to get nice IAT
testIatValue = 4.03646;
Sensor::setMockValue(SensorType::Iat, 30);
// this is needed to have valid CLT and IAT.
//todo: reuse initPeriodicEvents(PASS_ENGINE_PARAMETER_SIGNATURE) method

View File

@ -12,6 +12,7 @@
#include "rpm_calculator.h"
#include "main_trigger_callback.h"
#include "unit_test_framework.h"
#include "sensor.h"
extern EnginePins enginePins;

View File

@ -41,14 +41,16 @@ TEST(misc, testEngineMath) {
ASSERT_NEAR( 50, getOneDegreeTimeMs(600) * 180, EPS4D) << "600 RPM";
ASSERT_EQ( 5, getOneDegreeTimeMs(6000) * 180) << "6000 RPM";
ASSERT_FLOAT_EQ(312.5, getTCharge(1000, 0, 300, 350 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(313.5833, getTCharge(1000, 50, 300, 350 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(314.6667, getTCharge(1000, 100, 300, 350 PASS_ENGINE_PARAMETER_SUFFIX));
Sensor::setMockValue(SensorType::Clt, 300);
Sensor::setMockValue(SensorType::Iat, 350);
ASSERT_FLOAT_EQ(312.5, getTCharge(1000, 0 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(313.5833, getTCharge(1000, 50 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(314.6667, getTCharge(1000, 100 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(312.5, getTCharge(4000, 0, 300, 350 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(320.0833, getTCharge(4000, 50, 300, 350 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(327.6667, getTCharge(4000, 100, 300, 350 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(312.5, getTCharge(4000, 0 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(320.0833, getTCharge(4000, 50 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(327.6667, getTCharge(4000, 100 PASS_ENGINE_PARAMETER_SUFFIX));
// test Air Interpolation mode
engineConfiguration->tChargeMode = TCHARGE_MODE_AIR_INTERP;
@ -58,8 +60,11 @@ TEST(misc, testEngineMath) {
// calc. some airMass given the engine displacement=1.839 and 4 cylinders (FORD_ESCORT_GT)
engine->engineState.sd.airMassInOneCylinder = getCylinderAirMass(/*VE*/1.0f, /*MAP*/100.0f, /*tChargeK*/273.15f + 20.0f PASS_ENGINE_PARAMETER_SUFFIX);
ASSERT_NEAR(0.5464f, engine->engineState.sd.airMassInOneCylinder, EPS4D);
Sensor::setMockValue(SensorType::Clt, 90);
Sensor::setMockValue(SensorType::Iat, 20);
// calc. airFlow using airMass, and find tCharge
ASSERT_FLOAT_EQ(59.1175f, getTCharge(/*RPM*/1000, /*TPS*/0, /*CLT*/90.0f, /*IAT*/20.0f PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(59.1175f, getTCharge(/*RPM*/1000, /*TPS*/0 PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_FLOAT_EQ(65.5625f/*kg/h*/, engine->engineState.airFlow);
}

View File

@ -12,8 +12,6 @@
#include "fsio_impl.h"
TEST(fuelCut, coasting) {
printf("*************************************************** testCoastingFuelCut\r\n");
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
// configure coastingFuelCut
@ -30,7 +28,8 @@ TEST(fuelCut, coasting) {
setupSimpleTestEngineWithMafAndTT_ONE_trigger(&eth);
// mock CLT - just above threshold ('hot engine')
float hotClt = engine->sensors.clt = engineConfiguration->coastingFuelCutClt + 1;
float hotClt = engineConfiguration->coastingFuelCutClt + 1;
Sensor::setMockValue(SensorType::Clt, hotClt);
// mock TPS - throttle is opened
Sensor::setMockValue(SensorType::Tps1, 60);
// set 'running' RPM - just above RpmHigh threshold
@ -57,14 +56,14 @@ TEST(fuelCut, coasting) {
assertEqualsM("inj dur#2 cut", 0.0f, ENGINE(injectionDuration));
// Now drop the CLT below threshold
engine->sensors.clt = engineConfiguration->coastingFuelCutClt - 1;
Sensor::setMockValue(SensorType::Clt, engineConfiguration->coastingFuelCutClt - 1);
eth.engine.periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
// Fuel cut-off should be diactivated - the engine is 'cold'
assertEqualsM("inj dur#3 clt", normalInjDuration, ENGINE(injectionDuration));
// restore CLT
engine->sensors.clt = hotClt;
Sensor::setMockValue(SensorType::Clt, hotClt);
// And set RPM - somewhere between RpmHigh and RpmLow threshold
engine->rpmCalculator.mockRpm = (engineConfiguration->coastingFuelCutRpmHigh + engineConfiguration->coastingFuelCutRpmLow) / 2;
eth.engine.periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
@ -115,6 +114,7 @@ TEST(fuelCut, criticalEngineTemperature) {
ASSERT_FALSE(engine->stopEngineRequestTimeNt > 0);
engine->sensors.mockClt = 200; // 200C is really hot!
Sensor::setMockValue(SensorType::Clt, 200);
eth.engine.periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
eth.engine.periodicSlowCallback(PASS_ENGINE_PARAMETER_SIGNATURE);

View File

@ -65,6 +65,9 @@ TEST(misc, testFuelMap) {
eth.engine.updateSlowSensors(PASS_ENGINE_PARAMETER_SIGNATURE);
Sensor::setMockValue(SensorType::Clt, 36.605f);
Sensor::setMockValue(SensorType::Iat, 30.0f);
// because all the correction tables are zero
printf("*************************************************** getRunningFuel 1\r\n");
eth.engine.periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
@ -86,10 +89,8 @@ TEST(misc, testFuelMap) {
setFlatInjectorLag(0 PASS_CONFIG_PARAMETER_SUFFIX);
ASSERT_FALSE(cisnan(getIntakeAirTemperature()));
float iatCorrection = getIatFuelCorrection(-KELV PASS_ENGINE_PARAMETER_SUFFIX);
ASSERT_EQ( 2, iatCorrection) << "IAT";
ASSERT_FALSE(cisnan(getCoolantTemperature()));
float cltCorrection = getCltFuelCorrection(PASS_ENGINE_PARAMETER_SIGNATURE);
ASSERT_EQ( 1, cltCorrection) << "CLT";
float injectorLag = getInjectorLag(getVBatt(PASS_ENGINE_PARAMETER_SIGNATURE) PASS_ENGINE_PARAMETER_SUFFIX);

View File

@ -51,8 +51,6 @@ TEST(idle, fsioPidParameters) {
// see also util.pid test
TEST(idle, timingPid) {
print("******************************************* testTimingPidController\r\n");
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
// set PID settings
@ -70,9 +68,9 @@ TEST(idle, timingPid) {
engineConfiguration->idleTimingPidWorkZone = 100;
engineConfiguration->idlePidFalloffDeltaRpm = 30;
// setup target rpm curve (we need only 1 value when CLT sensor is disabled)
// setup target rpm curve
const int idleRpmTarget = 700;
engineConfiguration->cltIdleRpm[0] = idleRpmTarget;
setArrayValues<float>(engineConfiguration->cltIdleRpm, idleRpmTarget);
// setup other settings
engineConfiguration->idleTimingPid = pidS;

View File

@ -31,8 +31,6 @@ TEST(engine, testPlainCrankingWithoutAdvancedFeatures) {
TEST(engine, testStartOfCrankingPrimingPulse) {
printf("*************************************************** testStartOfCrankingPrimingPulse\r\n");
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
engineConfiguration->startOfCrankingPrimingPulse = 4;
@ -43,8 +41,8 @@ TEST(engine, testStartOfCrankingPrimingPulse) {
ASSERT_NEAR( 70, engine->sensors.clt, EPS4D) << "CLT#1";
// we need below freezing temperature to get prime fuel
// todo: less cruel CLT value assignment which would survive 'updateSlowSensors'
engine->sensors.clt = -10;
Sensor::setMockValue(SensorType::Clt, -10);
// prod code invokes this on ECU start, here we have to mimic this behavior
startPrimeInjectionPulse(PASS_ENGINE_PARAMETER_SIGNATURE);