rusefi/firmware/controllers/algo/advance_map.cpp

220 lines
8.0 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file advance_map.cpp
*
* @date Mar 27, 2013
2017-01-03 03:05:22 -08:00
* @author Andrey Belomutskiy, (c) 2012-2017
2015-07-10 06:01:56 -07:00
*
* This file is part of rusEfi - see http://rusefi.com
*
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include "advance_map.h"
#include "interpolation.h"
#include "efilib2.h"
#include "engine_math.h"
EXTERN_ENGINE;
2017-01-06 08:02:49 -08:00
#if !EFI_UNIT_TEST || defined(__DOXYGEN__)
2017-01-05 18:12:06 -08:00
extern TunerStudioOutputChannels tsOutputChannels;
2017-01-06 08:02:49 -08:00
#endif
2017-01-05 18:12:06 -08:00
2015-12-27 09:01:53 -08:00
static ign_Map3D_t advanceMap("advance");
static ign_Map3D_t iatAdvanceCorrectionMap("iat corr");
2015-07-10 06:01:56 -07:00
static int minCrankingRpm = 0;
2015-07-10 06:01:56 -07:00
static const float iatTimingRpmBins[IGN_LOAD_COUNT] = {880, 1260, 1640, 2020, 2400, 2780, 3000, 3380, 3760, 4140, 4520, 5000, 5700, 6500, 7200, 8000};
//880 1260 1640 2020 2400 2780 3000 3380 3760 4140 4520 5000 5700 6500 7200 8000
static const ignition_table_t defaultIatTiming = {
{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2},
{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2},
{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2},
{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2},
{3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 3.5, 2, 2, 2, 2, 2},
{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2},
{ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, -0.9, -0.9, -0.9, -0.9, -0.9, -0.9, -0.9, -0.9, -0.9, -0.9, -0.9, -0.9, -0.9, -0.9},
{ -3.3, -3.4, -4.9, -4.9, -4.9, -4.9, -4.4, -4.4, -4.4, -4.4, -4.4, -0.9, -0.9, -0.9, -0.9, -0.9},
{ -4.4, -4.9, -5.9, -5.9, -5.9, -5.9, -4.9, -4.9, -4.9, -4.9, -4.9, -2.4, -2.4, -2.4, -2.4, -2.4},
{ -4.4, -4.9, -5.9, -5.9, -5.9, -5.9, -4.9, -4.9, -4.9, -4.9, -4.9, -2.9, -2.9, -2.9, -2.9, -2.9},
{-4.4, -4.9, -5.9, -5.9, -5.9, -5.9, -4.9, -4.9, -4.9, -4.9, -4.9, -3.9, -3.9, -3.9, -3.9, -3.9},
{-4.4, -4.9, -5.9, -5.9, -5.9, -5.9, -4.9, -4.9, -4.9, -4.9, -4.9, -3.9, -3.9, -3.9, -3.9, -3.9},
{-4.4, -4.9, -5.9, -5.9, -5.9, -5.9, -4.9, -4.9, -4.9, -4.9, -4.9, -3.9, -3.9, -3.9, -3.9, -3.9},
};
2017-05-15 20:28:49 -07:00
bool isStep1Condition(int rpm DECLARE_ENGINE_PARAMETER_SUFFIX) {
2015-07-10 06:01:56 -07:00
return boardConfiguration->enabledStep1Limiter && rpm >= engineConfiguration->step1rpm;
}
/**
* @return ignition timing angle advance before TDC
*/
2017-05-15 20:28:49 -07:00
static angle_t getRunningAdvance(int rpm, float engineLoad DECLARE_ENGINE_PARAMETER_SUFFIX) {
2017-12-03 10:22:29 -08:00
if (CONFIG(timingMode) == TM_FIXED)
return engineConfiguration->fixedTiming;
2015-07-10 06:01:56 -07:00
engine->m.beforeAdvance = GET_TIMESTAMP();
if (cisnan(engineLoad)) {
2016-11-02 20:01:48 -07:00
warning(CUSTOM_NAN_ENGINE_LOAD, "NaN engine load");
2015-07-10 06:01:56 -07:00
return NAN;
}
efiAssert(!cisnan(engineLoad), "invalid el", NAN);
efiAssert(!cisnan(engineLoad), "invalid rpm", NAN);
engine->m.beforeZeroTest = GET_TIMESTAMP();
engine->m.zeroTestTime = GET_TIMESTAMP() - engine->m.beforeZeroTest;
2017-05-15 20:28:49 -07:00
if (isStep1Condition(rpm PASS_ENGINE_PARAMETER_SUFFIX)) {
2015-07-10 06:01:56 -07:00
return engineConfiguration->step1timing;
}
2016-05-17 21:03:11 -07:00
float iatCorrection;
if (cisnan(engine->sensors.iat)) {
2016-05-17 21:03:11 -07:00
iatCorrection = 0;
} else {
iatCorrection = iatAdvanceCorrectionMap.getValue((float) rpm, engine->sensors.iat);
2016-05-17 21:03:11 -07:00
}
2017-02-09 09:03:46 -08:00
if (engineConfiguration->debugMode == DBG_IGNITION_TIMING) {
2017-01-06 08:02:49 -08:00
#if !EFI_UNIT_TEST || defined(__DOXYGEN__)
2017-01-05 18:12:06 -08:00
tsOutputChannels.debugFloatField1 = iatCorrection;
tsOutputChannels.debugFloatField2 = engine->engineState.cltTimingCorrection;
2017-08-03 18:21:16 -07:00
tsOutputChannels.debugFloatField3 = engine->fsioTimingAdjustment;
2017-01-06 08:02:49 -08:00
#endif
2017-01-05 18:12:06 -08:00
}
2015-07-10 06:01:56 -07:00
2017-01-05 18:12:06 -08:00
float result = advanceMap.getValue((float) rpm, engineLoad)
+ iatCorrection
2017-08-03 18:21:16 -07:00
+ engine->fsioTimingAdjustment
2017-01-05 18:12:06 -08:00
+ engine->engineState.cltTimingCorrection
2015-07-10 06:01:56 -07:00
// todo: uncomment once we get useable knock - engine->knockCount
;
engine->m.advanceLookupTime = GET_TIMESTAMP() - engine->m.beforeAdvance;
return result;
}
2017-05-15 20:28:49 -07:00
angle_t getAdvance(int rpm, float engineLoad DECLARE_ENGINE_PARAMETER_SUFFIX) {
2017-12-03 13:16:15 -08:00
efiAssert(!cisnan(engineLoad), "engineLoad", 0);
2015-07-10 06:01:56 -07:00
angle_t angle;
2017-07-06 05:43:15 -07:00
if (ENGINE(rpmCalculator).isCranking(PASS_ENGINE_PARAMETER_SIGNATURE)) {
// Interpolate the cranking timing angle to the earlier running angle for faster engine start
angle_t crankingToRunningTransitionAngle = getRunningAdvance(CONFIG(cranking.rpm), engineLoad PASS_ENGINE_PARAMETER_SUFFIX);
// interpolate not from zero, but starting from min. possible rpm detected
if (rpm < minCrankingRpm || minCrankingRpm == 0)
minCrankingRpm = rpm;
angle = interpolateClamped(minCrankingRpm, engineConfiguration->crankingTimingAngle, CONFIG(cranking.rpm), crankingToRunningTransitionAngle, rpm);
2015-07-10 06:01:56 -07:00
} else {
2017-12-03 10:22:29 -08:00
angle = getRunningAdvance(rpm, engineLoad PASS_ENGINE_PARAMETER_SUFFIX);
2015-07-10 06:01:56 -07:00
}
angle -= engineConfiguration->ignitionOffset;
2016-12-05 19:01:54 -08:00
fixAngle(angle, "getAdvance");
2015-07-10 06:01:56 -07:00
return angle;
}
2017-05-15 20:28:49 -07:00
void setDefaultIatTimingCorrection(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
2015-07-10 06:01:56 -07:00
setTableBin2(config->ignitionIatCorrLoadBins, IGN_LOAD_COUNT, -40, 110, 1);
memcpy(config->ignitionIatCorrRpmBins, iatTimingRpmBins, sizeof(iatTimingRpmBins));
copyTimingTable(defaultIatTiming, config->ignitionIatCorrTable);
}
2017-05-15 20:28:49 -07:00
void prepareTimingMap(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
2015-07-10 06:01:56 -07:00
advanceMap.init(config->ignitionTable, config->ignitionLoadBins,
config->ignitionRpmBins);
iatAdvanceCorrectionMap.init(config->ignitionIatCorrTable, config->ignitionIatCorrLoadBins,
config->ignitionIatCorrRpmBins);
}
2015-12-24 11:02:03 -08:00
/**
* @param octane gas octane number
* @param bore in mm
*/
float getTopAdvanceForBore(chamber_style_e style, int octane, double compression, double bore) {
int octaneCorrection;
if ( octane <= 90) {
octaneCorrection = -2;
} else if (octane < 94) {
octaneCorrection = -1;
} else {
octaneCorrection = 0;
}
int compressionCorrection;
if (compression <= 9) {
compressionCorrection = 2;
} else if (compression <= 10) {
compressionCorrection = 1;
} else if (compression <= 11) {
compressionCorrection = 0;
} else {
// compression ratio above 11
compressionCorrection = -2;
}
int base;
if (style == CS_OPEN) {
base = 33;
} else if (style == CS_CLOSED) {
base = 28;
} else {
// CS_SWIRL_TUMBLE
base = 22;
}
float boreCorrection = (bore - 4 * 25.4) / 25.4 * 6;
float result = base + octaneCorrection + compressionCorrection + boreCorrection;
return ((int)(result * 10)) / 10.0;
}
2015-12-31 10:02:19 -08:00
float getAdvanceForRpm(int rpm, float advanceMax) {
if (rpm >= 3000)
return advanceMax;
if (rpm < 600)
return 10;
return interpolate(600, 10, 3000, advanceMax, rpm);
}
#define round10(x) efiRound(x, 0.1)
float getInitialAdvance(int rpm, float map, float advanceMax) {
2016-01-21 19:01:31 -08:00
map = minF(map, 100);
2015-12-31 10:02:19 -08:00
float advance = getAdvanceForRpm(rpm, advanceMax);
2016-01-21 19:01:31 -08:00
if (rpm >= 3000)
return round10(advance + 0.1 * (100 - map));
return round10(advance + 0.1 * (100 - map) * rpm / 3000);
2015-12-31 10:02:19 -08:00
}
2016-01-21 14:02:40 -08:00
/**
* this method builds a good-enough base timing advance map bases on a number of heuristics
*/
2017-05-15 20:28:49 -07:00
void buildTimingMap(float advanceMax DECLARE_ENGINE_PARAMETER_SUFFIX) {
2016-08-28 13:02:34 -07:00
if (engineConfiguration->fuelAlgorithm != LM_SPEED_DENSITY &&
engineConfiguration->fuelAlgorithm != LM_MAP) {
2016-11-02 20:01:48 -07:00
warning(CUSTOM_WRONG_ALGORITHM, "wrong algorithm for MAP-based timing");
2015-12-31 10:02:19 -08:00
return;
}
/**
* good enough (but do not trust us!) default timing map in case of MAP-based engine load
*/
for (int loadIndex = 0; loadIndex < IGN_LOAD_COUNT; loadIndex++) {
float load = config->ignitionLoadBins[loadIndex];
for (int rpmIndex = 0;rpmIndex<IGN_RPM_COUNT;rpmIndex++) {
2016-01-21 19:01:31 -08:00
float rpm = config->ignitionRpmBins[rpmIndex];
2015-12-31 10:02:19 -08:00
config->ignitionTable[loadIndex][rpmIndex] = getInitialAdvance(rpm, load, advanceMax);
}
}
}