Initial work on engine protection system

This commit is contained in:
Josh Stewart 2020-06-06 10:52:27 +10:00
parent 2368b8890d
commit 940a6826b5
9 changed files with 151 additions and 48 deletions

View File

@ -500,7 +500,9 @@ page = 4
idleAdvBins = array, U08, 108, [6], "RPM", 10.0, -50, -500, 500, 0
idleAdvValues = array, U08, 114, [6], "deg", 1.0, -15, -15, 50, 0
unused4-120 = array, U08, 120, [8], "%", 1.0, 0.0, 0.0, 255, 0
engineProtectMaxRPM = scalar, U08, 120, "rpm", 100, 0.0, 100, 25500, 0
unused4-120 = array, U08, 121, [7], "%", 1.0, 0.0, 0.0, 255, 0
;--------------------------------------------------
;Start AFR page
@ -524,7 +526,7 @@ page = 6
egoType = bits , U08, 0, [2:3], "Disabled", "Narrow Band", "Wide Band", "INVALID" ; egoOption
boostEnabled = bits, U08, 0, [4:4], "Off", "On"
vvtEnabled = bits, U08, 0, [5:5], "Off", "On"
boostCutType = bits, U08, 0, [6:7], "Off", "Spark Only", "Fuel Only","Both"
engineProtectType = bits, U08, 0, [6:7], "Off", "Spark Only", "Fuel Only","Both"
egoKP = scalar, U08, 1, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
egoKI = scalar, U08, 2, "%", 1.0, 0.0, 0.0, 200.0, 0 ; * ( 1 byte)
@ -1031,17 +1033,20 @@ page = 10
;Pressure transducers
fuelPressureEnable = bits, U08, 135, [0:0], "Off", "On"
oilPressureEnable = bits, U08, 135, [1:1], "Off", "On"
oilPressureProtEnbl = bits, U08, 135, [2:2], "Off", "On"
fuelPressurePin = bits, U08, 136, [0:3], "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A8", "A10", "A11", "A12", "A13", "A14", "A15"
oilPressurePin = bits, U08, 136, [4:7], "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A8", "A10", "A11", "A12", "A13", "A14", "A15"
fuelPressureMin = scalar, S08, 137, "kpa", 1.0, 0.0, -100, 127, 0 ;Note signed int
fuelPressureMax = scalar, U08, 138, "kpa", 1.0, 0.0, 0.0, 255, 0
oilPressureMin = scalar, S08, 139, "kpa", 1.0, 0.0, -100, 127, 0 ;Note signed int
oilPressureMax = scalar, U08, 140, "kpa", 1.0, 0.0, 0.0, 255, 0
fuelPressureMin = scalar, S08, 137, "psi", 1.0, 0.0, -100, 127, 0 ;Note signed int
fuelPressureMax = scalar, U08, 138, "psi", 1.0, 0.0, 0.0, 255, 0
oilPressureMin = scalar, S08, 139, "psi", 1.0, 0.0, -100, 127, 0 ;Note signed int
oilPressureMax = scalar, U08, 140, "psi", 1.0, 0.0, 0.0, 255, 0
oilPressureProtRPM = array, U08, 141, [ 4], "RPM", 100.0, 0.0, 100.0, 25500, 0
oilPressureProtMins = array, U08, 145, [ 4], "psi", 1.0, 0.0, 0.0, 255, 0
unused11_135_191 = array, U08, 141, [50], "RPM", 100.0, 0.0, 100, 25500, 0
;unused11_135_191 = array, U08, 135, [56], "RPM", 100.0, 0.0, 100, 25500, 0
unused11_135_191 = array, U08, 149, [42], "RPM", 100.0, 0.0, 100, 25500, 0
;Page 11 is the fuel map and axis bins only
page = 11
@ -2477,6 +2482,8 @@ 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
@ -3530,6 +3537,15 @@ cmdVSSratio6 = "E\x99\x06"
yBins = knock_window_dur
size = 400, 200
; Oil Pressure protection curve
curve = oil_pressure_prot_curve, "Oil Pressure Protection"
columnLabel = "RPM", "Minimum PSI"
xAxis = 0, 8000, 9
yAxis = 0, 150, 3
xBins = oilPressureProtRPM, rpm
yBins = oilPressureProtMins
size = 400, 200
; Warmup enrichment VEAL AFR adjustment curves
curve = warmup_afr_curve, "Target Adjustment"
columnLabel = "Coolant", "Offset"
@ -3815,6 +3831,12 @@ cmdVSSratio6 = "E\x99\x06"
indicator = { resetLockOn }, "Reset Lock OFF","Reset Lock ON", red, black, green, black
indicator = { bootloaderCaps > 0 }, "Std. Boot", "Custom Boot", white, black, white, black
indicator = { nitrousOn }, "Nitrous Off", "Nitrous On", white, black, red, black
;Engine Protection status indicators
indicator = { engineProtectStatus}, "Engine Protect OFF", "Engine Protect ON", white, black, red, black
indicator = { engineProtectRPM }, "Rev Limiter Off", "Rev Limiter ON", white, black, red, black
indicator = { engineProtectMAP }, "Boost Limit OFF", "Boost Limit ON", white, black, red, black
indicator = { engineProtectOil }, "Oil Pres. Protect OFF","Oil Pres. Protect ON",white, black, red, black
indicator = { engineProtectAFR }, "AFR Protect OFF", "AFR Protect ON", white, black, red, black
;-------------------------------------------------------------------------------
@ -3920,6 +3942,12 @@ cmdVSSratio6 = "E\x99\x06"
vssRefresh = bits, U08, 83, [3:3]
unused81_4 = bits, U08, 83, [4:4]
nSquirts = bits, U08, 83, [5:7]
engineProtectStatus = scalar, U08, 84, "bits", 1.000, 0.000
engineProtectRPM = bits, U08, 84, [0:0]
engineProtectMAP = bits, U08, 84, [1:1]
engineProtectOil = bits, U08, 84, [2:2]
engineProtectAFR = bits, U08, 84, [3:3]
engineProtectOth = bits, U08, 84, [4:7] ; Unused for now
unused1 = scalar, U08, 84, "ADC",1.000, 0.000
fuelLoad = scalar, S16, 85, { bitStringValue( algorithmUnits , algorithm ) }, 1.000, 0.000
ignLoad = scalar, S16, 87, { bitStringValue( algorithmUnits , ignAlgorithm ) }, 1.000, 0.000

View File

@ -629,8 +629,7 @@ void sendValues(uint16_t offset, uint16_t packetLength, byte cmd, byte portNum)
fullStatus[82] = highByte(currentStatus.PW4); //Pulsewidth 4 multiplied by 10 in ms. Have to convert from uS to mS.
fullStatus[83] = currentStatus.status3;
fullStatus[84] = currentStatus.nChannels; //THIS IS CURRENTLY UNUSED!
fullStatus[84] = currentStatus.engineProtectStatus;
fullStatus[85] = lowByte(currentStatus.fuelLoad);
fullStatus[86] = highByte(currentStatus.fuelLoad);
fullStatus[87] = lowByte(currentStatus.ignLoad);

View File

@ -773,8 +773,8 @@ int8_t correctionKnock(int8_t advance)
//First check is to do the window calculations (ASsuming knock is enabled)
if( configPage10.knock_mode != KNOCK_MODE_OFF )
{
knockWindowMin = table2D_getValue(&knockWindowStartTable, currentStatus.RPM);
knockWindowMax = knockWindowMin + table2D_getValue(&knockWindowDurationTable, currentStatus.RPM);
knockWindowMin = table2D_getValue(&knockWindowStartTable, currentStatus.RPMdiv100);
knockWindowMax = knockWindowMin + table2D_getValue(&knockWindowDurationTable, currentStatus.RPMdiv100);
}

View File

@ -0,0 +1,8 @@
byte checkEngineProtect();
byte checkBoostLimit();
byte checkOilPressureLimit();
byte checkAFRLimit();

View File

@ -0,0 +1,75 @@
#include "globals.h"
#include "engineProtection.h"
byte checkEngineProtect()
{
byte protectActive = 0;
if(checkBoostLimit() || checkOilPressureLimit() || checkAFRLimit())
{
if(currentStatus.RPM > (configPage4.engineProtectMaxRPM*100U)) { protectActive = 1; }
}
return protectActive;
}
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
{
boostLimitActive = 1;
switch(configPage6.boostCutType)
{
case 1:
BIT_SET(currentStatus.spark, BIT_SPARK_BOOSTCUT);
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_MAP);
break;
case 2:
BIT_SET(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
BIT_CLEAR(currentStatus.spark, BIT_SPARK_BOOSTCUT);
break;
case 3:
BIT_SET(currentStatus.spark, BIT_SPARK_BOOSTCUT);
BIT_SET(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
break;
default:
//Shouldn't ever happen, but just in case, disable all cuts
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
BIT_CLEAR(currentStatus.spark, BIT_SPARK_BOOSTCUT);
}
}
else
{
BIT_CLEAR(currentStatus.spark, BIT_SPARK_BOOSTCUT);
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
}
return boostLimitActive;
}
byte checkOilPressureLimit()
{
byte oilProtectActive = 0;
BIT_CLEAR(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_OIL); //Will be set true below if required
if(configPage10.oilPressureProtEnbl == true)
{
byte oilLimit = table2D_getValue(&oilPressureProtectTable, currentStatus.RPMdiv100);
if(currentStatus.oilPressure < oilLimit)
{
BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_OIL);
oilProtectActive = 1;
}
}
return oilProtectActive;
}
byte checkAFRLimit()
{
}

View File

@ -288,6 +288,11 @@
#define IGN7_CMD_BIT 6
#define IGN8_CMD_BIT 7
#define ENGINE_PROTECT_BIT_RPM 0
#define ENGINE_PROTECT_BIT_MAP 1
#define ENGINE_PROTECT_BIT_OIL 2
#define ENGINE_PROTECT_BIT_AFR 3
//Table sizes
#define CALIBRATION_TABLE_SIZE 512
#define CALIBRATION_TEMPERATURE_OFFSET 40 // All temperature measurements are stored offset by 40 degrees. This is so we can use an unsigned byte (0-255) to represent temperature ranges from -40 to 215
@ -339,6 +344,7 @@ extern struct table2D flexAdvTable; //6 bin flex fuel correction table for tim
extern struct table2D flexBoostTable; //6 bin flex fuel correction table for boost adjustments (2D)
extern struct table2D knockWindowStartTable;
extern struct table2D knockWindowDurationTable;
extern struct table2D oilPressureProtectTable;
//These are for the direct port manipulation of the injectors, coils and aux outputs
extern volatile PORT_TYPE *inj1_pin_port;
@ -460,6 +466,7 @@ extern volatile byte LOOP_TIMER;
struct statuses {
volatile bool hasSync;
uint16_t RPM;
byte RPMdiv100;
long longRPM;
int mapADC;
int baroADC;
@ -559,6 +566,7 @@ struct statuses {
byte gear; /**< Current gear (Calculated from vss) */
byte fuelPressure; /**< Fuel pressure in PSI */
byte oilPressure; /**< Oil pressure in PSI */
byte engineProtectStatus;
};
/**
@ -791,7 +799,9 @@ struct config4 {
byte idleAdvBins[6];
byte idleAdvValues[6];
byte unused4_120[8];
byte engineProtectMaxRPM;
byte unused4_120[7];
#if defined(CORE_AVR)
};
@ -1088,7 +1098,8 @@ struct config10 {
byte fuelPressureEnable : 1;
byte oilPressureEnable : 1;
byte unused10_135 : 6;
byte oilPressureProtEnbl : 1;
byte unused10_135 : 5;
byte fuelPressurePin : 4;
byte oilPressurePin : 4;
@ -1098,7 +1109,10 @@ struct config10 {
int8_t oilPressureMin;
byte oilPressureMax;
byte unused11_135_191[51]; //Bytes 135-191
byte oilPressureProtRPM[4];
byte oilPressureProtMins[4];
byte unused11_135_191[43]; //Bytes 135-191
#if defined(CORE_AVR)
};

View File

@ -38,6 +38,7 @@ struct table2D flexAdvTable; //6 bin flex fuel correction table for timing adv
struct table2D flexBoostTable; //6 bin flex fuel correction table for boost adjustments (2D)
struct table2D knockWindowStartTable;
struct table2D knockWindowDurationTable;
struct table2D oilPressureProtectTable;
//These are for the direct port manipulation of the injectors, coils and aux outputs
volatile PORT_TYPE *inj1_pin_port;

View File

@ -182,6 +182,12 @@ void initialiseAll()
knockWindowDurationTable.values = configPage10.knock_window_dur;
knockWindowDurationTable.axisX = configPage10.knock_window_rpms;
oilPressureProtectTable.valueSize = SIZE_BYTE;
oilPressureProtectTable.axisSize = SIZE_BYTE; //Set this table to use byte axis bins
oilPressureProtectTable.xSize = 4;
oilPressureProtectTable.values = configPage10.oilPressureProtMins;
oilPressureProtectTable.axisX = configPage10.oilPressureProtRPM;
//Setup the calibration tables
loadCalibration();
@ -316,6 +322,7 @@ void initialiseAll()
currentStatus.launchingHard = false;
currentStatus.crankRPM = ((unsigned int)configPage4.crankRPM * 10); //Crank RPM limit (Saves us calculating this over and over again. It's updated once per second in timers.ino)
currentStatus.fuelPumpOn = false;
currentStatus.engineProtectStatus = 0;
triggerFilterTime = 0; //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be disgarded as noise. This is simply a default value, the actual values are set in the setup() functinos of each decoder
dwellLimit_uS = (1000 * configPage4.dwellLimit);
currentStatus.nChannels = ((uint8_t)INJ_CHANNELS << 4) + IGN_CHANNELS; //First 4 bits store the number of injection channels, 2nd 4 store the number of ignition channels
@ -325,7 +332,7 @@ void initialiseAll()
timer5_overflow_count = 0;
toothHistoryIndex = 0;
toothHistorySerialIndex = 0;
noInterrupts();
initialiseTriggers();

View File

@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "storage.h"
#include "crankMaths.h"
#include "init.h"
#include "engineProtection.h"
#include BOARD_H //Note that this is not a real file, it is defined in globals.h.
int ignition1StartAngle = 0;
@ -145,6 +146,7 @@ void loop()
{
currentStatus.longRPM = getRPM(); //Long RPM is included here
currentStatus.RPM = currentStatus.longRPM;
currentStatus.RPMdiv100 = currentStatus.RPM / 100;
FUEL_PUMP_ON();
currentStatus.fuelPumpOn = true; //Not sure if this is needed.
}
@ -228,37 +230,6 @@ void loop()
else { currentStatus.flatShiftingHard = false; }
}
//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
{
switch(configPage6.boostCutType)
{
case 1:
BIT_SET(currentStatus.spark, BIT_SPARK_BOOSTCUT);
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
break;
case 2:
BIT_SET(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
BIT_CLEAR(currentStatus.spark, BIT_SPARK_BOOSTCUT);
break;
case 3:
BIT_SET(currentStatus.spark, BIT_SPARK_BOOSTCUT);
BIT_SET(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
break;
default:
//Shouldn't ever happen, but just in case, disable all cuts
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
BIT_CLEAR(currentStatus.spark, BIT_SPARK_BOOSTCUT);
}
}
else
{
BIT_CLEAR(currentStatus.spark, BIT_SPARK_BOOSTCUT);
BIT_CLEAR(currentStatus.status1, BIT_STATUS1_BOOSTCUT);
}
//And check whether the tooth log buffer is ready
if(toothHistoryIndex > TOOTH_LOG_SIZE) { BIT_SET(currentStatus.status1, BIT_STATUS1_TOOTHLOG1READY); }
@ -932,7 +903,7 @@ void loop()
//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(currentStatus.launchingHard || BIT_CHECK(currentStatus.spark, BIT_SPARK_BOOSTCUT) || BIT_CHECK(currentStatus.spark, BIT_SPARK_HRDLIM) || currentStatus.flatShiftingHard)
if(checkEngineProtect() || currentStatus.launchingHard || BIT_CHECK(currentStatus.spark, BIT_SPARK_HRDLIM) || currentStatus.flatShiftingHard)
{
if(configPage2.hardCutType == HARD_CUT_FULL) { ignitionOn = false; }
else