Mostly complete engine protection (excl AFR)

This commit is contained in:
Josh Stewart 2020-06-06 14:27:46 +10:00
parent 56509b3a4a
commit 1ec7e7ee86
6 changed files with 147 additions and 67 deletions

View File

@ -542,7 +542,7 @@ page = 6
vvtCLDir = bits, U08, 6, [4:4], "Advance", "Retard"
vvtCLUseHold = bits, U08, 6, [5:5], "No", "Yes"
vvtCLAlterFuelTiming = bits, U08, 6, [6:6], "No", "Yes"
unused6-6 = bits, U08, 6, [7:7], "TPS", "MAP"
boostCutEnabled = bits, U08, 6, [7:7], "Off", "On"
egoLimit = scalar, U08, 7, "", 1, 0, 0, 16, 0
ego_min = scalar, U08, 8, "AFR", 0.1, 0.0, 7, 25, 1
ego_max = scalar, U08, 9, "AFR", 0.1, 0.0, 7, 25, 1
@ -1210,6 +1210,7 @@ page = 11
defaultValue = dfcoDelay, 0.1
defaultValue = dfcoMinCLT, 25
defaultValue = crankingEnrichTaper, 0.1
defaultValue = boostCutEnabled, 1
;Default pins
defaultValue = fanPin, 0
@ -1562,9 +1563,11 @@ menuDialog = main
flatSArm = "The RPM switch point that determines whether an eganged clutch is for launch control or flat shift. Below this figure, an engaged clutch is considered to be for launch, above this figure an active clutch input will be considered a flat shift. This should be set at least several hundred RPM above idle"
flatSSoftWin = "The number of RPM below the flat shift point where the softlimit will be applied (aka Soft limit window). Recommended values are 200-1000"
flatSRetard = "The absolute timing (BTDC) that will be used when within the soft limit window"
hardCutType = "How hard cuts should be performed for rev/launch limits. Full cut will stop all ignition events, Rolling cut will step through all ignition outputs, only cutting 1 per revolution"
engineProtectType = "Whether the engine protect an rev limiter will cut the fuel, the ignition or both"
hardCutType = "How the cuts should be performed for rev/launch limits. Full cut will stop all fuel/ignition events, Rolling cut will step through all ignition outputs, only cutting a limited number per revolution"
SoftLimitMode = "Fixed: the soft limiter will retard the ignition advance to the specified value.\nRelative: current timing advance will be retarted by the specified amount"
HardRevLim = "The hard rev limit is the point that the fuel or ignition (or both) will be cut completely to reduce increasing RPMs"
engineProtectMaxRPM = "The RPM point that engine protections will engage from. Below this RPM value, engine protections will NOT be active"
fuel2InputPin = "The Arduino pin that is being used to trigger the second fuel table to be active"
fuel2InputPolarity = "Whether the 2nd fuel table should be active when input is high or low. This should be LOW for a typical ground switching input"
@ -2298,8 +2301,8 @@ menuDialog = main
panel = rotaryTrailing_curve
dialog = boostCut, "Boost Cut"
field = "Boost Cut", boostCutType
field = "Boost Limit", boostLimit, { boostCutType }
field = "Enable Boost limit", boostCutEnabled
field = "Boost Limit", boostLimit, { boostCutEnabled }
dialog = boostLoad, ""
field = "Mode", boostType
@ -2307,16 +2310,38 @@ menuDialog = main
field = "In closed loop mode, the values are boost targets in kPa"
panel = boostTbl
dialog = RevLimiterS, "Rev Limiter", 4
topicHelp = "https://wiki.speeduino.com/en/configuration/Rev_Limits"
dialog = revLimiterDialog, "Rev Limiter"
field = "Rev Limiter"
field = "Soft rev limit", SoftRevLim
field = "Soft limiter mode", SoftLimitMode
field = "Soft limit timing", SoftLimRetard
field = "Soft limit max time", SoftLimMax
field = "Hard Rev limit", HardRevLim
field = "Hard limiter method", hardCutType
panel = boostCut
dialog = oilPressureProtection, "Oil Pressure"
field = "Oil Pressure Protection", oilPressureProtEnbl, { oilPressureEnable }
panel = oil_pressure_prot_curve, { oilPressureEnable && oilPressureProtEnbl }
indicatorPanel = protectIndicatorPanel, 1, { 1 }
indicator = { engineProtectStatus}, "Engine Protect OFF", "Engine Protect ON", green, black, red, black
indicator = { engineProtectRPM }, "Rev Limiter Off", "Rev Limiter ON", green, black, red, black
indicator = { engineProtectMAP }, "Boost Limit OFF", "Boost Limit ON", green, black, red, black
indicator = { engineProtectOil }, "Oil Pres. Protect OFF","Oil Pres. Protect ON",green, black, red, black
indicator = { engineProtectAFR }, "AFR Protect OFF", "AFR Protect ON", green, black, red, black
dialog = engineProtectionWest, ""
field = "Protection Cut", engineProtectType
field = "Engine Protection RPM min", engineProtectMaxRPM, { engineProtectType }
field = "Cut method", hardCutType, { engineProtectType }
panel = protectIndicatorPanel, { engineProtectType }
dialog = RevLimiterS, "Engine Protection and Limiters", xAxis
topicHelp = "https://wiki.speeduino.com/en/configuration/Rev_Limits"
panel = engineProtectionWest
panel = revLimiterDialog, { engineProtectType }
panel = boostCut, { engineProtectType }
panel = oilPressureProtection, { engineProtectType }
dialog = clutchInput, "Clutch input"
field = "Clutch Input Pin", launchPin, { launchEnable || flatSEnable }
@ -2482,8 +2507,6 @@ menuDialog = main
settingOption = "0-150 PSI", oilPressureMin=-18, oilPressureMax=168 ; Vout = VCC x (P x 0.8 / 150 + 0.1) https://aftermarketindustries.com.au/image/cache/data/aftermarket%20industries%20fuel%20pressure%20sensor%20data%202-500x500.png
field = "Pressure at 0v", oilPressureMin, { oilPressureEnable }
field = "Pressure at 5v", oilPressureMax, { oilPressureEnable }
field = "Oil Pressure Protection", oilPressureProtEnbl, { oilPressureEnable }
panel = oil_pressure_prot_curve, { oilPressureEnable }
dialog = oilPressureDialog, "Oil Pressure", xAxis
gauge = oilPressureGauge

View File

@ -3,6 +3,7 @@
byte checkEngineProtect();
byte checkRevLimit();
byte checkBoostLimit();
byte checkOilPressureLimit();
byte checkAFRLimit();

View File

@ -5,7 +5,7 @@
byte checkEngineProtect()
{
byte protectActive = 0;
if(checkBoostLimit() || checkOilPressureLimit() || checkAFRLimit())
if(checkRevLimit() || checkBoostLimit() || checkOilPressureLimit() || checkAFRLimit())
{
if(currentStatus.RPM > (configPage4.engineProtectMaxRPM*100U)) { protectActive = 1; }
}
@ -13,13 +13,32 @@ byte checkEngineProtect()
return protectActive;
}
byte checkRevLimit()
{
//Hardcut RPM limit
byte revLimiterActive = 0;
BIT_CLEAR(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_RPM);
if (currentStatus.RPM > ((unsigned int)(configPage4.HardRevLim) * 100) )
{
BIT_SET(currentStatus.spark, BIT_SPARK_HRDLIM); //Legacy and likely to be removed at some point
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_RPM);
revLimiterActive = 1;
}
else { BIT_CLEAR(currentStatus.spark, BIT_SPARK_HRDLIM); }
return revLimiterActive;
}
byte checkBoostLimit()
{
byte boostLimitActive = 0;
//Boost cutoff is very similar to launchControl, but with a check against MAP rather than a switch
if( (configPage6.boostCutType > 0) && (currentStatus.MAP > (configPage6.boostLimit * 2)) ) //The boost limit is divided by 2 to allow a limit up to 511kPa
if( (configPage6.boostCutEnabled > 0) && (currentStatus.MAP > (configPage6.boostLimit * 2)) ) //The boost limit is divided by 2 to allow a limit up to 511kPa
{
boostLimitActive = 1;
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_MAP);
/*
switch(configPage6.boostCutType)
{
case 1:
@ -40,6 +59,7 @@ byte checkBoostLimit()
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
BIT_CLEAR(currentStatus.spark, BIT_SPARK_BOOSTCUT);
}
*/
}
else
{
@ -70,6 +90,8 @@ byte checkOilPressureLimit()
byte checkAFRLimit()
{
byte checkAFRLimitActive = 0;
return checkAFRLimitActive ;
}

View File

@ -227,6 +227,11 @@
#define NITROUS_STAGE2 2
#define NITROUS_BOTH 3
#define PROTECT_CUT_OFF 0
#define PROTECT_CUT_IGN 1
#define PROTECT_CUT_FUEL 2
#define PROTECT_CUT_BOTH 3
#define AE_MODE_TPS 0
#define AE_MODE_MAP 1
@ -817,7 +822,7 @@ struct config6 {
byte egoType : 2;
byte boostEnabled : 1;
byte vvtEnabled : 1;
byte boostCutType : 2;
byte engineProtectType : 2;
byte egoKP;
byte egoKI;
@ -829,7 +834,7 @@ struct config6 {
byte vvtCLDir : 1; //VVT direction (advance or retard)
byte vvtCLUseHold : 1; //Whether or not to use a hold duty cycle (Most cases are Yes)
byte vvtCLAlterFuelTiming : 1;
byte unused6_6 : 1;
byte boostCutEnabled : 1;
byte egoLimit; //Maximum amount the closed loop will vary the fueling
byte ego_min; //AFR must be above this for closed loop to function
byte ego_max; //AFR must be below this for closed loop to function

View File

@ -574,6 +574,8 @@ byte getFuelPressure()
int16_t tempFuelPressure = 0;
uint16_t tempReading;
if(configPage10.fuelPressureEnable)
{
//Perform ADC read
tempReading = analogRead(pinFuelPressure);
tempReading = analogRead(pinFuelPressure);
@ -582,6 +584,8 @@ byte getFuelPressure()
//Sanity checks
if(tempFuelPressure < 0) { tempFuelPressure = 0; }
if(tempFuelPressure > configPage10.fuelPressureMax) { tempFuelPressure = configPage10.fuelPressureMax; }
}
return (byte)tempFuelPressure;
}
@ -591,6 +595,8 @@ byte getOilPressure()
int16_t tempOilPressure = 0;
uint16_t tempReading;
if(configPage10.oilPressureEnable)
{
//Perform ADC read
tempReading = analogRead(pinOilPressure);
tempReading = analogRead(pinOilPressure);
@ -600,6 +606,8 @@ byte getOilPressure()
//Sanity checks
if(tempOilPressure < 0) { tempOilPressure = 0; }
if(tempOilPressure > configPage10.oilPressureMax) { tempOilPressure = configPage10.oilPressureMax; }
}
return (byte)tempOilPressure;
}

View File

@ -677,9 +677,6 @@ void loop()
//***********************************************************************************************
//| BEGIN IGNITION CALCULATIONS
if (currentStatus.RPM > ((unsigned int)(configPage4.HardRevLim) * 100) ) { BIT_SET(currentStatus.spark, BIT_SPARK_HRDLIM); } //Hardcut RPM limit
else { BIT_CLEAR(currentStatus.spark, BIT_SPARK_HRDLIM); }
//Set dwell
//Dwell is stored as ms * 10. ie Dwell of 4.3ms would be 43 in configPage4. This number therefore needs to be multiplied by 100 to get dwell in uS
@ -723,6 +720,56 @@ void loop()
// }
// }
//Check for any of the engine protections or rev limiters being turned on
if(checkEngineProtect() || currentStatus.launchingHard || currentStatus.flatShiftingHard)
{
if(currentStatus.RPMdiv100 > configPage4.engineProtectMaxRPM)
{
if(configPage2.hardCutType == HARD_CUT_FULL)
{
switch(configPage6.engineProtectType)
{
case PROTECT_CUT_IGN:
ignitionOn = false;
break;
case PROTECT_CUT_FUEL:
fuelOn = false;
break;
case PROTECT_CUT_BOTH:
ignitionOn = false;
fuelOn = false;
break;
default:
ignitionOn = false;
fuelOn = false;
break;
}
}
else
{
if(rollingCutCounter >= 2) //Vary this number to change the intensity of the roll. The higher the number, the closer is it to full cut
{
//Rolls through each of the active ignition channels based on how many revolutions have taken place
//curRollingCut = ( (currentStatus.startRevolutions / 2) % maxIgnOutputs) + 1;
rollingCutCounter = 0;
ignitionOn = true;
curRollingCut = 0;
}
else
{
if(rollingCutLastRev == 0) { rollingCutLastRev = currentStatus.startRevolutions; } //
if (rollingCutLastRev != currentStatus.startRevolutions)
{
rollingCutLastRev = currentStatus.startRevolutions;
rollingCutCounter++;
}
ignitionOn = false; //Finally the ignition is fully cut completely
}
} //Hard/Rolling cut check
} //RPM Check
} //Protection active check
else { curRollingCut = 0; } //Disables the rolling hard cut
#if INJ_CHANNELS >= 1
if (fuelOn && !BIT_CHECK(currentStatus.status1, BIT_STATUS1_BOOSTCUT))
{
@ -899,40 +946,14 @@ void loop()
ignition2StartAngle -= 5;
ignition3StartAngle -= 5;
ignition4StartAngle -= 5;
ignition5StartAngle -= 5;
ignition6StartAngle -= 5;
ignition7StartAngle -= 5;
ignition8StartAngle -= 5;
}
}
else { fixedCrankingOverride = 0; }
//Perform an initial check to see if the ignition is turned on (Ignition only turns on after a preset number of cranking revolutions and:
//Check for any of the hard cut rev limits being on
if(checkEngineProtect() || currentStatus.launchingHard || BIT_CHECK(currentStatus.spark, BIT_SPARK_HRDLIM) || currentStatus.flatShiftingHard)
{
if(configPage2.hardCutType == HARD_CUT_FULL) { ignitionOn = false; }
else
{
if(rollingCutCounter >= 2) //Vary this number to change the intensity of the roll. The higher the number, the closer is it to full cut
{
//Rolls through each of the active ignition channels based on how many revolutions have taken place
//curRollingCut = ( (currentStatus.startRevolutions / 2) % maxIgnOutputs) + 1;
rollingCutCounter = 0;
ignitionOn = true;
curRollingCut = 0;
}
else
{
if(rollingCutLastRev == 0) { rollingCutLastRev = currentStatus.startRevolutions; } //
if (rollingCutLastRev != currentStatus.startRevolutions)
{
rollingCutLastRev = currentStatus.startRevolutions;
rollingCutCounter++;
}
ignitionOn = false; //Finally the ignition is fully cut completely
}
}
}
else { curRollingCut = 0; } //Disables the rolling hard cut
//if(ignitionOn && !currentStatus.launchingHard && !BIT_CHECK(currentStatus.spark, BIT_SPARK_BOOSTCUT) && !BIT_CHECK(currentStatus.spark, BIT_SPARK_HRDLIM) && !currentStatus.flatShiftingHard)
if(ignitionOn)
{
//Refresh the current crank angle info