Added taper entering DFCO (#1118)

* Added taper for DFCO for ignition and fuel

Used 1 byte of RAM and 4 on page 9

* Moved data to be compatible with DFCO map thres

* Added taper for DFCO for ignition and fuel

Used 1 byte of RAM and 4 on page 9

* Moved data to be compatible with DFCO map thres

* Fixed potential overflow and DFCO tests

* Moved math into functions and added tests

---------

Co-authored-by: Josh Stewart <josh@noisymime.org>
This commit is contained in:
Vitor Moreno B. Sales 2023-10-24 20:09:57 -03:00 committed by GitHub
parent 602203d3e0
commit f8ffbb13da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 143 additions and 15 deletions

View File

@ -1075,7 +1075,15 @@ page = 9
coolantProtTemp = array, U08, 173, [6], "F", 1.8, -22.23, -40, 419, 0
#endif
unused179_184 = array, U08, 179, [6], "", 1, 0, 0, 255, 0
unused10_179 = scalar, U08, 179, "", 1, 0, 0, 255, 0
dfcoTaperTime = scalar, U08, 180, "S", 0.1, 0.0, 0.0, 25.5, 1
dfcoTaperFuel = scalar, U08, 181, "%", 1.0, 0.0, 0, 255, 0
dfcoTaperAdvance = scalar, U08, 182, "deg", 1.0, 0.0, 0, 40, 0
dfcoTaperEnable = bits, U08, 183, [0:0], "Off", "On"
unused10_182 = bits, U08, 183, [1:7], ""
unused10_184 = scalar, U08, 184, "", 1, 0, 0, 255, 0
; AFR engine protection
afrProtectEnabled = bits, U08, 185, [0:1], "Off", "Fixed mode", "Table mode", "INVALID"
@ -2594,6 +2602,10 @@ menuDialog = main
field = "Cutoff delay", dfcoDelay, { dfcoEnabled }
field = "Cutoff RPM", dfcoRPM, { dfcoEnabled }
field = "RPM Hysteresis", dfcoHyster, { dfcoEnabled }
field = "Enable cutoff taper", dfcoTaperEnable, { dfcoEnabled }
field = "Cutoff taper time", dfcoTaperTime, { dfcoEnabled && dfcoTaperEnable }
field = "Taper end fuel amount", dfcoTaperFuel, { dfcoEnabled && dfcoTaperEnable }
field = "Taper advance remove", dfcoTaperAdvance, { dfcoEnabled && dfcoTaperEnable }
dialog = accelEnrichments_north_south, ""
liveGraph = pump_ae_Graph, "AE Graph"

View File

@ -48,9 +48,10 @@ byte lastKnockCount;
int16_t knockWindowMin; //The current minimum crank angle for a knock pulse to be valid
int16_t knockWindowMax;//The current maximum crank angle for a knock pulse to be valid
uint8_t aseTaper;
uint8_t dfcoTaper;
uint8_t dfcoDelay;
uint8_t idleAdvTaper;
uint8_t crankingEnrichTaper;
uint8_t dfcoTaper;
/** Initialise instances and vars related to corrections (at ECU boot-up).
*/
@ -122,7 +123,9 @@ uint16_t correctionsFuel(void)
if (currentStatus.launchCorrection != 100) { sumCorrections = div100(sumCorrections * currentStatus.launchCorrection); }
bitWrite(currentStatus.status1, BIT_STATUS1_DFCO, correctionDFCO());
if ( BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) == 1 ) { sumCorrections = 0; }
byte dfcoTaperCorrection = correctionDFCOfuel();
if (dfcoTaperCorrection == 0) { sumCorrections = 0; }
else if (dfcoTaperCorrection != 100) { sumCorrections = div100(sumCorrections * dfcoTaperCorrection); }
if(sumCorrections > 1500) { sumCorrections = 1500; } //This is the maximum allowable increase during cranking
return (uint16_t)sumCorrections;
@ -539,6 +542,27 @@ byte correctionLaunch(void)
return launchValue;
}
/**
*/
byte correctionDFCOfuel(void)
{
byte scaleValue = 100;
if ( BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) )
{
if ( (configPage9.dfcoTaperEnable == 1) && (dfcoTaper != 0) )
{
//Do a check if the user reduced the duration while active to avoid overflow
if (dfcoTaper > configPage9.dfcoTaperTime) { dfcoTaper = configPage9.dfcoTaperTime; }
scaleValue = map(dfcoTaper, configPage9.dfcoTaperTime, 0, 100, configPage9.dfcoTaperFuel);
if( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) ) { dfcoTaper--; }
}
else { scaleValue = 0; } //Taper ended or disabled, disable fuel
}
else { dfcoTaper = configPage9.dfcoTaperTime; } //Keep updating the duration until DFCO is active
return scaleValue;
}
/*
* Returns true if deceleration fuel cutoff should be on, false if its off
*/
@ -550,19 +574,19 @@ bool correctionDFCO(void)
if ( BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) == 1 )
{
DFCOValue = ( currentStatus.RPM > ( configPage4.dfcoRPM * 10) ) && ( currentStatus.TPS < configPage4.dfcoTPSThresh );
if ( DFCOValue == false) { dfcoTaper = 0; }
if ( DFCOValue == false) { dfcoDelay = 0; }
}
else
{
if ( (currentStatus.TPS < configPage4.dfcoTPSThresh) && (currentStatus.coolant >= (int)(configPage2.dfcoMinCLT - CALIBRATION_TEMPERATURE_OFFSET)) && ( currentStatus.RPM > (unsigned int)( (configPage4.dfcoRPM * 10) + (configPage4.dfcoHyster * 2)) ) )
{
if( dfcoTaper < configPage2.dfcoDelay )
if( dfcoDelay < configPage2.dfcoDelay )
{
if( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) ) { dfcoTaper++; }
if( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) ) { dfcoDelay++; }
}
else { DFCOValue = true; }
}
else { dfcoTaper = 0; } //Prevent future activation right away if previous time wasn't activated
else { dfcoDelay = 0; } //Prevent future activation right away if previous time wasn't activated
} // DFCO active check
} // DFCO enabled check
return DFCOValue;
@ -702,6 +726,8 @@ int8_t correctionsIgn(int8_t base_advance)
advance = correctionSoftFlatShift(advance);
advance = correctionKnock(advance);
advance = correctionDFCOignition(advance);
//Fixed timing check must go last
advance = correctionFixedTiming(advance);
advance = correctionCrankingFixedTiming(advance); //This overrides the regular fixed timing, must come last
@ -936,6 +962,23 @@ int8_t correctionKnock(int8_t advance)
return advance - knockRetard;
}
/** Ignition DFCO taper correction.
*/
int8_t correctionDFCOignition(int8_t advance)
{
int8_t dfcoRetard = advance;
if ( (configPage9.dfcoTaperEnable == 1) && BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) )
{
if ( dfcoTaper != 0 )
{
dfcoRetard -= map(dfcoTaper, configPage9.dfcoTaperTime, 0, 0, configPage9.dfcoTaperAdvance);
}
else { dfcoRetard -= configPage9.dfcoTaperAdvance; } //Taper ended, use full value
}
else { dfcoTaper = configPage9.dfcoTaperTime; } //Keep updating the duration until DFCO is active
return dfcoRetard;
}
/** Ignition Dwell Correction.
*/
uint16_t correctionsDwell(uint16_t dwell)

View File

@ -21,6 +21,7 @@ byte correctionBatVoltage(void); //Battery voltage correction
byte correctionIATDensity(void); //Inlet temp density correction
byte correctionBaro(void); //Barometric pressure correction
byte correctionLaunch(void); //Launch control correction
byte correctionDFCOfuel(void); //DFCO taper correction
bool correctionDFCO(void); //Decelleration fuel cutoff
@ -37,6 +38,7 @@ int8_t correctionNitrous(int8_t advance);
int8_t correctionSoftLaunch(int8_t advance);
int8_t correctionSoftFlatShift(int8_t advance);
int8_t correctionKnock(int8_t advance);
int8_t correctionDFCOignition(int8_t advance);
uint16_t correctionsDwell(uint16_t dwell);
@ -49,8 +51,9 @@ extern byte lastKnockCount;
extern int16_t knockWindowMin; //The current minimum crank angle for a knock pulse to be valid
extern int16_t knockWindowMax;//The current maximum crank angle for a knock pulse to be valid
extern uint8_t aseTaper;
extern uint8_t dfcoTaper;
extern uint8_t dfcoDelay;
extern uint8_t idleAdvTaper;
extern uint8_t crankingEnrichTaper;
extern uint8_t dfcoTaper;
#endif // CORRECTIONS_H

View File

@ -1128,12 +1128,16 @@ struct config9 {
byte hardRevMode : 2;
byte coolantProtRPM[6];
byte coolantProtTemp[6];
byte unused10_179;
byte unused10_180;
byte unused10_181;
byte unused10_182;
byte unused10_183;
byte dfcoTaperTime;
byte dfcoTaperFuel;
byte dfcoTaperAdvance;
byte dfcoTaperEnable : 1;
byte unused10_183 : 6;
byte unused10_184;
byte afrProtectEnabled : 2; /* < AFR protection enabled status. 0 = disabled, 1 = fixed mode, 2 = table mode */
byte afrProtectMinMAP; /* < Minimum MAP. Stored value is divided by 2. Increments of 2 kPa, maximum 511 (?) kPa */
byte afrProtectMinRPM; /* < Minimum RPM. Stored value is divded by 100. Increments of 100 RPM, maximum 25500 RPM */

View File

@ -727,7 +727,11 @@ void doUpdates(void)
if(readEEPROMVersion() == 22)
{
//202311-dev
configPage9.dfcoTaperEnable = 0; //Disable
configPage9.dfcoTaperTime = 10; //1 second
configPage9.dfcoTaperFuel = 100; //Don't scale fuel
configPage9.dfcoTaperAdvance = 20; //Reduce 20deg until full fuel cut
//EGO MAP Limits
configPage9.egoMAPMax = 255, // 255 will be 510 kpa
configPage9.egoMAPMin = 0, // 0 will be 0 kpa

View File

@ -137,9 +137,9 @@ void setup_DFCO_on()
configPage2.dfcoMinCLT = 40; //Actually 0 with offset
configPage2.dfcoDelay = 10;
dfcoTaper = 1;
dfcoDelay = 1;
correctionDFCO();
dfcoTaper = 20;
dfcoDelay = 20;
}
//**********************************************************************************************************************
void test_corrections_dfco_on(void)
@ -178,6 +178,65 @@ void test_corrections_dfco_off_delay()
TEST_ASSERT_FALSE(correctionDFCO()); //Make sure DFCO does not come on
}
void setup_DFCO_taper_on()
{
//Test that DFCO comes will not activate if there has not been a long enough delay
//The steup function below simulates a 2 second delay
setup_DFCO_on();
configPage9.dfcoTaperEnable = 1; //Enable
configPage9.dfcoTaperTime = 20; //2.0 second
configPage9.dfcoTaperFuel = 0; //Scale fuel to 0%
configPage9.dfcoTaperAdvance = 20; //Reduce 20deg until full fuel cut
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_DFCO);
//Set the threshold to be 2.5 seconds, above the simulated delay of 2s
configPage2.dfcoDelay = 250;
}
void test_corrections_dfco_taper()
{
setup_DFCO_taper_on();
TEST_ASSERT_FALSE(correctionDFCO()); //Make sure DFCO does not come on
correctionDFCOfuel();
TEST_ASSERT_EQUAL(20, dfcoTaper); //Check if value was reset to setting
}
void test_corrections_dfco_taper_fuel()
{
setup_DFCO_taper_on();
correctionDFCOfuel();
TEST_ASSERT_EQUAL(20, dfcoTaper); //Check if value was reset to setting
BIT_SET(currentStatus.status1, BIT_STATUS1_DFCO);
dfcoTaper = 10;
TEST_ASSERT_EQUAL(50, correctionDFCOfuel());
dfcoTaper = 5;
TEST_ASSERT_EQUAL(25, correctionDFCOfuel());
configPage9.dfcoTaperTime = 10; //1.0 second
dfcoTaper = 15; //Check for overflow
TEST_ASSERT_EQUAL(100, correctionDFCOfuel());
configPage9.dfcoTaperEnable = 0; //Disable
TEST_ASSERT_EQUAL(0, correctionDFCOfuel());
}
void test_corrections_dfco_taper_ign()
{
setup_DFCO_taper_on();
dfcoTaper = 20;
BIT_SET(currentStatus.status1, BIT_STATUS1_DFCO);
TEST_ASSERT_EQUAL(20, correctionDFCOignition(20));
dfcoTaper = 15;
TEST_ASSERT_EQUAL(15, correctionDFCOignition(20));
dfcoTaper = 10;
TEST_ASSERT_EQUAL(10, correctionDFCOignition(20));
dfcoTaper = 5;
TEST_ASSERT_EQUAL(5, correctionDFCOignition(20));
configPage9.dfcoTaperEnable = 0; //Disable
TEST_ASSERT_EQUAL(20, correctionDFCOignition(20));
}
void test_corrections_dfco()
{
@ -185,6 +244,9 @@ void test_corrections_dfco()
RUN_TEST(test_corrections_dfco_off_RPM);
RUN_TEST(test_corrections_dfco_off_TPS);
RUN_TEST(test_corrections_dfco_off_delay);
RUN_TEST(test_corrections_dfco_taper);
RUN_TEST(test_corrections_dfco_taper_fuel);
RUN_TEST(test_corrections_dfco_taper_ign);
}
//**********************************************************************************************************************
//Setup a basic TAE enrichment curve, threshold etc that are common to all tests. Specifica values maybe updated in each individual test