Table-based flex fuel corrections

Changed the linear low / high flex fuel correction method to a table2D-based one.
This commit is contained in:
Murray 2018-01-19 21:25:01 -06:00
parent fa5d721b98
commit 2350d5d785
8 changed files with 110 additions and 34 deletions

2
.gitignore vendored
View File

@ -18,3 +18,5 @@ reference/hardware/v0.4/gerbers/Archive.zip
.project
.vscode
.build
.vscode/c_cpp_properties.json
.vscode/launch.json

View File

@ -158,8 +158,8 @@ page = 1
;Page 2 is all general settings (Previously part of page 1)
;--------------------------------------------------
page = 2
flexBoostLow = scalar, S08, 0, "kPa", 1.0, 0.0, -127, 127, 0
flexBoostHigh = scalar, U08, 1, "kPa", 1.0, 0.0, 0.0, 255, 0
unused2-1 = scalar, S08, 0, "kPa", 1.0, 0.0, -127, 127, 0
unused2-2 = scalar, U08, 1, "kPa", 1.0, 0.0, 0.0, 255, 0
asePct = scalar, U08, 2, "%", 1.0, 0.0, 0.0, 95.0, 0
aseCount = scalar, U08, 3, "s", 1.0, 0.0, 0.0, 255, 0
wueRates = array, U08, 4, [10], "%", 1.0, 0.0, 0.0, 255, 0
@ -236,10 +236,10 @@ page = 2
oddfire3 = scalar, U16, 53, "deg", 1.0, 0.0, 0.0, 720, 0 ; * ( 2 byte)
oddfire4 = scalar, U16, 55, "deg", 1.0, 0.0, 0.0, 720, 0 ; * ( 2 byte)
flexFuelLow = scalar, U08, 57, "%", 1.0, 0.0, 0.0, 250.0, 0
flexFuelHigh = scalar, U08, 58, "%", 1.0, 0.0, 0.0, 250.0, 0
flexAdvLow = scalar, U08, 59, "Deg", 1.0, 0.0, 0.0, 250.0, 0
flexAdvHigh = scalar, U08, 60, "Deg", 1.0, 0.0, 0.0, 250.0, 0
unused2-57 = scalar, U08, 57, "%", 1.0, 0.0, 0.0, 250.0, 0
unused2-58 = scalar, U08, 58, "%", 1.0, 0.0, 0.0, 250.0, 0
unused2-59 = scalar, U08, 59, "Deg", 1.0, 0.0, 0.0, 250.0, 0
unused2-60 = scalar, U08, 60, "Deg", 1.0, 0.0, 0.0, 250.0, 0
iacCLminDuty = scalar, U08, 61, "%", 1.0, 0.0, 0.0, 100.0, 0 ; Minimum and maximum duty cycles when using closed loop idle
iacCLmaxDuty = scalar, U08, 62, "%", 1.0, 0.0, 0.0, 100.0, 0
@ -705,7 +705,14 @@ page = 10
#endif
boostSens = scalar, U16, 25, "", 1, 0, 0, 5000, 0
boostIntv = scalar, U08, 27, "ms", 1, 0, 0, 250, 0
unused11_28_192 = array, U08, 28,[163], "RPM", 100.0, 0.0, 100, 25500, 0
flexCorrectionBins = array, U08, 28, [6], "%", 1.0, 0.0, 0.0, 250.0, 0
; The boost range is obviously arbitrary since int16_t has ~32k in both directions
flexCorrectionBoost = array, S16, 34, [6], "kPa", 1.0, 0.0, -500.0, 500.0, 0
flexCorrectionFuel = array, U08, 46, [6], "%", 1.0, 0.0, 0.0, 250.0, 0
flexCorrectionAdv = array, U08, 52, [6], "Deg", 1.0, 0.0, 0.0, 250.0, 0
unused11_53_192 = array, U08, 53,[139], "RPM", 100.0, 0.0, 100, 25500, 0
;-------------------------------------------------------------------------------
@ -1128,16 +1135,16 @@ menuDialog = main
dialog = flexMiddle, ""
field = "Low (E0)"
field = "", flexFreqLow, { flexEnabled }
field = "", flexFuelLow, { flexEnabled }
field = "", flexAdvLow, { flexEnabled }
field = "", flexBoostLow, { boostEnabled }
;field = "", flexFuelLow, { flexEnabled && 0 }
;field = "", flexAdvLow, { flexEnabled && 0 }
;field = "", flexBoostLow, { boostEnabled }
dialog = flexRight, ""
field = "High (E100)"
field = "", flexFreqHigh, { flexEnabled }
field = "", flexFuelHigh, { flexEnabled }
field = "", flexAdvHigh, { flexEnabled }
field = "", flexBoostHigh, { flexEnabled && boostEnabled }
;field = "", flexFuelHigh, { flexEnabled && 0 }
;field = "", flexAdvHigh, { flexEnabled && 0 }
;field = "", flexBoostHigh, { flexEnabled && boostEnabled }
dialog = flexMain, "Flex Fuel Calibration", xAxis
panel = flexLeft
@ -1151,6 +1158,8 @@ menuDialog = main
topicHelp = "http://speeduino.com/wiki/index.php/Flex_Fuel"
panel = flexFuelTop
panel = flexMain
panel = flex_corrections_curve, { flexEnabled }
dialog = tacho, "Tacho"
field = "Output pin", tachoPin
@ -1917,6 +1926,20 @@ cmdtestspk450dc = "E\x03\x0C"
xBins = crankingEnrichBins, coolant
yBins = crankingEnrichValues
;gauge = cltGau25
; Flex fuel correction curves
curve = flex_corrections_curve, "Flex Fuel Corrections"
columnLabel = "Ethanol %", "Correction Type"
xAxis = 0, 100, 5
xBins = flexCorrectionBins, flex
yBins = flexCorrectionFuel
yBins = flexCorrectionAdv
yBins = flexCorrectionBoost, { boostEnabled }
lineLabel = "Fuel Adj."
lineLabel = "Add'l. Adv."
lineLabel = "Add'l. Boost"
showTextValues = true
size = 640, 480
; Warmup enrichment VEAL AFR adjustment curve (Not currently working)
;curve = warmup_afr_curve, "AFR Target Temperature Adustment"

View File

@ -80,8 +80,10 @@ void boostControl()
//If flex fuel is enabled, there can be an adder to the boost target based on ethanol content
if( configPage1.flexEnabled == 1 )
{
int16_t boostAdder = (((int16_t)configPage1.flexBoostHigh - (int16_t)configPage1.flexBoostLow) * currentStatus.ethanolPct) / 100;
boostAdder = boostAdder + configPage1.flexBoostLow; //Required in case flexBoostLow is less than 0
int16_t boostAdder = flexLookupCache.boost = BIT_CHECK(TIMER_mask, BIT_TIMER_4HZ) || !flexLookupCache.boostReady
? table2D_getValue(&flexCorrectionBoostTable, currentStatus.ethanolPct)
: flexLookupCache.boost;
currentStatus.boostTarget += boostAdder;
}

View File

@ -19,6 +19,7 @@ Flood clear mode etc.
long PID_O2, PID_output, PID_AFRTarget;
PID egoPID(&PID_O2, &PID_output, &PID_AFRTarget, configPage3.egoKP, configPage3.egoKI, configPage3.egoKD, REVERSE); //This is the PID object if that algorithm is used. Needs to be global as it maintains state outside of each function call
void initialiseCorrections()
{
egoPID.SetMode(AUTOMATIC); //Turn O2 PID on
@ -279,10 +280,11 @@ static inline bool correctionDFCO()
static inline byte correctionFlex()
{
byte flexValue = 100;
if(configPage1.flexEnabled == 1)
if (configPage1.flexEnabled == 1)
{
byte flexRange = configPage1.flexFuelHigh - configPage1.flexFuelLow;
flexValue = percentage(currentStatus.ethanolPct, flexRange) + 100;
flexValue = flexLookupCache.fuel = BIT_CHECK(TIMER_mask, BIT_TIMER_4HZ) || !flexLookupCache.fuelReady
? table2D_getValue(&flexCorrectionFuelTable, currentStatus.ethanolPct)
: flexLookupCache.fuel;
}
return flexValue;
}
@ -405,11 +407,10 @@ static inline int8_t correctionFlexTiming(int8_t advance)
byte ignFlexValue = advance;
if( configPage1.flexEnabled == 1 ) //Check for flex being enabled
{
byte flexRange = configPage1.flexAdvHigh - configPage1.flexAdvLow;
if (currentStatus.ethanolPct != 0) { currentStatus.flexIgnCorrection = percentage(currentStatus.ethanolPct, flexRange); }
else { currentStatus.flexIgnCorrection = 0; }
currentStatus.flexIgnCorrection = flexLookupCache.advance = BIT_CHECK(TIMER_mask, BIT_TIMER_4HZ) || !flexLookupCache.advanceReady
? table2D_getValue(&flexCorrectionAdvTable, currentStatus.ethanolPct)
: flexLookupCache.advance;
ignFlexValue = advance + currentStatus.flexIgnCorrection;
}
return ignFlexValue;

View File

@ -173,6 +173,9 @@ struct table2D injectorVCorrectionTable; //6 bin injector voltage correction (2D
struct table2D IATDensityCorrectionTable; //9 bin inlet air temperature density correction (2D)
struct table2D IATRetardTable; //6 bin ignition adjustment based on inlet air temperature (2D)
struct table2D rotarySplitTable; //8 bin ignition split curve for rotary leading/trailing (2D)
struct table2D flexCorrectionFuelTable; //6 bin flex fuel correction table for fuel adjustments (2D)
struct table2D flexCorrectionAdvTable; //6 bin flex fuel correction table for timing advance (2D)
struct table2D flexCorrectionBoostTable; //6 bin flex fuel correction table for boost adjustments (2D)
//These are for the direct port manipulation of the injectors and coils
volatile byte *inj1_pin_port;
@ -309,8 +312,8 @@ struct statuses currentStatus; //The global status object
//This mostly covers off variables that are required for fuel
struct config1 {
int8_t flexBoostLow; //Must be signed to allow for negatives
byte flexBoostHigh;
byte unused2_1;
byte unused2_2;
byte asePct; //Afterstart enrichment (%)
byte aseCount; //Afterstart enrichment cycles. This is the number of ignition cycles that the afterstart enrichment % lasts for
byte wueValues[10]; //Warm up enrichment array (10 bytes)
@ -385,10 +388,10 @@ struct config1 {
uint16_t oddfire2; //The ATDC angle of channel 2 for oddfire
uint16_t oddfire3; //The ATDC angle of channel 3 for oddfire
uint16_t oddfire4; //The ATDC angle of channel 4 for oddfire
byte flexFuelLow; //Fuel % to be used for the lowest ethanol reading (Typically 100%)
byte flexFuelHigh; //Fuel % to be used for the highest ethanol reading (Typically 163%)
byte flexAdvLow; //Additional advance (in degrees) at lowest ethanol reading (Typically 0)
byte flexAdvHigh; //Additional advance (in degrees) at highest ethanol reading (Varies, usually 10-20)
byte unused2_57;
byte unused2_58;
byte unused2_59;
byte unused2_60;
byte iacCLminDuty;
byte iacCLmaxDuty;
@ -628,7 +631,13 @@ struct config11 {
uint16_t boostSens;
byte boostIntv;
byte unused11_28_192[164];
uint8_t flexCorrectionBins[6];
int16_t flexCorrectionBoost[6];
uint8_t flexCorrectionFuel[6]; //Fuel % to be used at current ethanol reading (typically 100% fuel @ 0% eth, 163% @ 100%)
uint8_t flexCorrectionAdv[6]; //Additional advance (in degrees) at current ethanol reading (typically 0 @ 0%, 10-20 @ 100%)
byte unused11_53_192[139];
#if defined(CORE_AVR)
};
@ -636,6 +645,16 @@ struct config11 {
} __attribute__((__packed__)); //The 32 bit systems require all structs to be fully packed
#endif
struct flexCachedLookups
{
bool fuelReady;
bool advanceReady;
bool boostReady;
byte fuel;
byte advance;
int16_t boost;
};
struct flexCachedLookups flexLookupCache = { false, false, false, 0, 0, 0 };
byte pinInjector1; //Output pin injector 1
byte pinInjector2; //Output pin injector 2
@ -717,4 +736,4 @@ extern byte iatCalibrationTable[CALIBRATION_TABLE_SIZE];
extern byte o2CalibrationTable[CALIBRATION_TABLE_SIZE];
#endif // GLOBALS_H
#endif // GLOBALS_H

View File

@ -201,6 +201,19 @@ void setup()
rotarySplitTable.values = configPage11.rotarySplitValues;
rotarySplitTable.axisX = configPage11.rotarySplitBins;
flexCorrectionFuelTable.valueSize = SIZE_BYTE;
flexCorrectionFuelTable.xSize = 6;
flexCorrectionFuelTable.values = configPage11.flexCorrectionFuel;
flexCorrectionFuelTable.axisX = configPage11.flexCorrectionBins;
flexCorrectionAdvTable.valueSize = SIZE_BYTE;
flexCorrectionAdvTable.xSize = 6;
flexCorrectionAdvTable.values = configPage11.flexCorrectionAdv;
flexCorrectionAdvTable.axisX = configPage11.flexCorrectionBins;
flexCorrectionBoostTable.valueSize = SIZE_INT;
flexCorrectionBoostTable.xSize = 6;
flexCorrectionBoostTable.values16 = configPage11.flexCorrectionBoost;
flexCorrectionBoostTable.axisX = configPage11.flexCorrectionBins;
//Setup the calibration tables
loadCalibration();
@ -1480,4 +1493,4 @@ static inline unsigned int PW(int REQ_FUEL, byte VE, long MAP, int corrections,
}
}
return (unsigned int)(intermediate);
}
}

View File

@ -222,4 +222,4 @@ void oneMSInterval() //Most ARM chips can simply call a function
TCNT2 = 131; //Preload timer2 with 100 cycles, leaving 156 till overflow.
TIFR2 = 0x00; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
#endif
}
}

View File

@ -8,7 +8,7 @@
void doUpdates()
{
#define CURRENT_DATA_VERSION 6
#define CURRENT_DATA_VERSION 7
//May 2017 firmware introduced a -40 offset on the ignition table. Update that table to +40
if(EEPROM.read(EEPROM_DATA_VERSION) == 2)
@ -77,6 +77,22 @@ void doUpdates()
loadConfig(); //Reload the config after changing everything in EEPROM
}
if (EEPROM.read(EEPROM_DATA_VERSION) == 6) {
//Convert whatever flex fuel settings are there into the new tables
for (uint8_t x = 0; x < 6; x++)
{
uint8_t pct = x * 20;
configPage11.flexCorrectionBins[x] = pct;
configPage11.flexCorrectionBoost[x] = percentage(pct, configPage1.unused2_2 - (int8_t)configPage1.unused2_1);
configPage11.flexCorrectionFuel[x] = percentage(pct, configPage1.unused2_58 - configPage1.unused2_57);
configPage11.flexCorrectionAdv[x] = percentage(pct, configPage1.unused2_60 - configPage1.unused2_59);
}
writeAllConfig();
EEPROM.write(EEPROM_DATA_VERSION, 7);
}
//Final check is always for 255 and 0 (Brand new arduino)
if( (EEPROM.read(EEPROM_DATA_VERSION) == 0) || (EEPROM.read(EEPROM_DATA_VERSION) == 255) )
{