From 20c5e177564fdbfe77114a4eec2ac42323a3704f Mon Sep 17 00:00:00 2001 From: Tjeerd <33102280+Tjeerdie@users.noreply.github.com> Date: Fri, 3 Jun 2022 07:44:09 +0200 Subject: [PATCH] Improve closedloop boost control (#736) * First try on updating closedloop boost control * added eeprom updates for backward comp[atibility * fix merge conflict * Change updates to next release EEPROM version. * Fix some issues after merging master * some cleanup to minimize changes and speedup review * cleanup updates * chances on updates to alaign with new table format * move LUT to new config page in eeprom * little cleanup * Update storage.h comments * fix some ini warnings Co-authored-by: Tjeerd --- reference/speeduino.ini | 65 +++++++++++++++++++++++++-------- speeduino/auxiliaries.ino | 16 +++++--- speeduino/comms_legacy.cpp | 5 +++ speeduino/globals.h | 23 ++++++++++++ speeduino/globals.ino | 2 + speeduino/pages.cpp | 9 ++++- speeduino/pages.h | 30 ++++++++------- speeduino/src/PID_v1/PID_v1.cpp | 20 ++++++++-- speeduino/src/PID_v1/PID_v1.h | 4 ++ speeduino/storage.cpp | 18 +++++++++ speeduino/storage.h | 13 ++++++- speeduino/updates.ino | 40 +++++++++++++++++++- 12 files changed, 204 insertions(+), 41 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index ba596763..8006de03 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -222,16 +222,16 @@ ;---------------------------------------------------------------------------- endianness = little - nPages = 14 - pageSize = 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288 + nPages = 15 + pageSize = 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288, 256 ; New commands - pageIdentifier = "\$tsCanId\x01", "\$tsCanId\x02", "\$tsCanId\x03", "\$tsCanId\x04", "\$tsCanId\x05", "\$tsCanId\x06", "\$tsCanId\x07", "\$tsCanId\x08", "\$tsCanId\x09", "\$tsCanId\x0A", "\$tsCanId\x0B", "\$tsCanId\x0C", "\$tsCanId\x0D", "\$tsCanId\x0E" - burnCommand = "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i" - pageReadCommand = "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c" - pageValueWrite = "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v" - pageChunkWrite = "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v" - crc32CheckCommand = "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i" + pageIdentifier = "\$tsCanId\x01", "\$tsCanId\x02", "\$tsCanId\x03", "\$tsCanId\x04", "\$tsCanId\x05", "\$tsCanId\x06", "\$tsCanId\x07", "\$tsCanId\x08", "\$tsCanId\x09", "\$tsCanId\x0A", "\$tsCanId\x0B", "\$tsCanId\x0C", "\$tsCanId\x0D", "\$tsCanId\x0E", "\$tsCanId\x0F" + burnCommand = "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i", "b%2i" + pageReadCommand = "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c", "p%2i%2o%2c" + pageValueWrite = "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v" + pageChunkWrite = "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v", "M%2i%2o%2c%v" + crc32CheckCommand = "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i", "d%2i" #if mcu_stm32 blockingFactor = 121 @@ -458,7 +458,6 @@ page = 1 unused2-95 = scalar, U08, 127, "RPM", 100, 0.0, 0.0, 16320, 0 - ;Page 2 is the fuel map and axis bins only page = 2 ; name = bits, type, offset, bits @@ -1371,6 +1370,25 @@ page = 14 ;------------------------------------------------------------------------------- +;-------------------------------------------------- +;boost Duty lookup map (Page 15) +;-------------------------------------------------- +page = 15 +;boost Duty lookup table + boostTableDutyLookup = array, U08, 0, [8x8], "Duty Cycle %", 0.5, 0.0, 0, 100, 0 + rpmBinsDutyLookup = array, U08, 64, [ 8], "RPM", 100.0, 0.0, 100, 25500, 0 + loadBinsDutyLookup = array, U08, 72, [ 8], "kpa", 2.0, 0.0, 0.0, {fuelLoadMax}, 0 +;add variables for improved closedloop boost control + boostControlEnable = bits, U08, 80, [0:0], "Baro", "Fixed" + unused15_1_1 = bits, U08, 80, [1:3], "False", "INVALID","INVALID", "INVALID","INVALID", "INVALID","INVALID", "INVALID" + unused15_1_2 = bits, U08, 80, [4:6], "False", "INVALID","INVALID", "INVALID","INVALID", "INVALID","INVALID", "INVALID" + unused15_1_3 = bits, U08, 80, [7:7], "False", "INVALID" + boostDCWhenDisabled = scalar, U08, 81, "%", 1, 0, 0, 100, 0 + boostControlEnableThreshold = scalar, U08, 82, "kpa", 1, 0.0, 0.0, 255, 0 + unused15_3_176 = array, U08, 83, [173], "%", 1.0, 0.0, 0.0, 255, 0 + +;------------------------------------------------------------------------------- + [EventTriggers] triggeredPageRefresh = 1, { vssRefresh > 0 } @@ -2253,6 +2271,11 @@ menuDialog = main canBMWCluster = "Enables CAN broadcasting for BMW E46, E39 and E38 instrument clusters with message ID's 0x316, 0x329 and 0x545" canVAGCluster = "Enables CAN broadcasting for VAG instrument clusters with message ID's 0x280 and 0x5A0" + boostControlEnable = "Set the trigger to enable/disable the closedloop boost controller. When set to: \n 'fixed': if the fuel load exceeds the threshold closedloop boost controller is enbaled.\n 'baro': if the fuel load exceeds the baro the controller is enabled (legacy) " + boostDCWhenDisabled = "When the closedloop boost controller is disabled by 'enable trigger', this is the Duty cycle set on the boost selenoid. Ususally this is 99% because it keeps the waste gate firmly closed until the threshold and builds boost as fast as possible (no wastegate leak)" + boostControlEnableThreshold = "When the 'Boost control enable trigger' is set to 'fixed', this value is used as threshold. Usually the value is set just below the wastgate pressure of the used turbo setup. For example 130kpa for a 0.3 bar wastegate actuator. Below this value the ECU has no control over the boost anyway." + boostDCLupTbl = "Boost target to boost valve dutycyle look-up table. Lookup table for boost control valve duty cycle for a given BoostTarget, closedloop controller works on top of this duty cycle." + [UserDefined] ; Enhanced TunerStudio dialogs can be defined here @@ -2769,6 +2792,7 @@ menuDialog = main field = "In open loop mode, the values in this table are duty cycle %" field = "In closed loop mode, the values are boost targets in kPa" panel = boostTbl + panel = boostDCLupTbl { boostEnabled & boostType == 1 } dialog = coolantProtection, "Coolant Based Rev Limit" panel = coolant_prot_curve, { hardRevMode == 2 } @@ -2997,12 +3021,15 @@ menuDialog = main panel = boostCut panel = boostByGear, { boostEnabled && vssMode > 1 } field = "Closed Loop settings" - field = "Control mode", boostMode, { boostEnabled && boostType == 1 } - slider = "Sensitivity", boostSens, horizontal, { boostEnabled && boostType == 1 } - field = "Control interval", boostIntv, { boostEnabled && boostType == 1 } - field = "P", boostKP, { boostEnabled && boostMode && boostType == 1 } - field = "I", boostKI, { boostEnabled && boostMode && boostType == 1 } - field = "D", boostKD, { boostEnabled && boostMode && boostType == 1 } + field = "Control mode", boostMode, { boostEnabled && boostType == 1 } + field = "Boost control enable trigger", boostControlEnable { boostEnabled && boostType == 1 } + field = "Valve duty when below threshold", boostDCWhenDisabled { boostEnabled && boostType == 1 } + field = "Boost control enable threshold", boostControlEnableThreshold { boostEnabled && boostControlEnable && boostType == 1 } + slider = "Sensitivity", boostSens, horizontal, { boostEnabled && boostType == 1 } + field = "Control interval", boostIntv, { boostEnabled && boostType == 1 } + field = "P", boostKP, { boostEnabled && boostMode && boostType == 1 } + field = "I", boostKI, { boostEnabled && boostMode && boostType == 1 } + field = "D", boostKD, { boostEnabled && boostMode && boostType == 1 } dialog = vvt2, "Second VVT output" field = "VVT2 Control Enabled", vvt2Enabled @@ -4552,6 +4579,14 @@ cmdVSSratio6 = "E\x99\x06" gridHeight = 3.0 upDownLabel = "HIGHER", "LOWER" + table = boostDCLupTbl, boostDutyLookup, "Boost target -> boost valve duty cycle lookup Table", 7 + xBins = rpmBinsDutyLookup, rpm + yBins = loadBinsDutyLookup, boostTarget + zBins = boostTableDutyLookup + gridHeight = 3.0 + upDownLabel = "HIGHER", "LOWER" + + table = vvtTbl, vvtMap, "VVT control Table", 7 xBins = rpmBinsVVT, rpm ;yBins = tpsBinsVVT, throttle diff --git a/speeduino/auxiliaries.ino b/speeduino/auxiliaries.ino index 645bb477..a1cbfb13 100644 --- a/speeduino/auxiliaries.ino +++ b/speeduino/auxiliaries.ino @@ -367,7 +367,6 @@ void boostByGear() } } -#define BOOST_HYSTER 40 void boostControl() { if( configPage6.boostEnabled==1 ) @@ -392,7 +391,7 @@ void boostControl() if ( (configPage9.boostByGearEnabled > 0) && (configPage2.vssMode > 1) ){ boostByGear(); } else{ currentStatus.boostTarget = get3DTableValue(&boostTable, (currentStatus.TPS * 2), currentStatus.RPM) << 1; } //Boost target table is in kpa and divided by 2 } - if(currentStatus.MAP >= currentStatus.baro ) //Only engage boost control above baro pressure + if(((configPage15.boostControlEnable == EN_BOOST_CONTROL_BARO) & (currentStatus.MAP >= currentStatus.baro)) | ((configPage15.boostControlEnable == EN_BOOST_CONTROL_FIXED) & (currentStatus.MAP >= configPage15.boostControlEnableThreshold))) //Only enables boost control above baro pressure or above user defined threshold (User defined level is ususally set to boost with wastegate actuator only boost level) { //If flex fuel is enabled, there can be an adder to the boost target based on ethanol content if( configPage2.flexEnabled == 1 ) @@ -415,7 +414,7 @@ void boostControl() else { boostPID.SetTunings(configPage6.boostKP, configPage6.boostKI, configPage6.boostKD); } } - bool PIDcomputed = boostPID.Compute(); //Compute() returns false if the required interval has not yet passed. + bool PIDcomputed = boostPID.Compute(get3DTableValue(&boostTableLookupDuty, currentStatus.boostTarget, currentStatus.RPM) * 100/2); //Compute() returns false if the required interval has not yet passed. if(currentStatus.boostDuty == 0) { DISABLE_BOOST_TIMER(); BOOST_PIN_LOW(); } //If boost duty is 0, shut everything down else { @@ -433,8 +432,15 @@ void boostControl() } else { - //Boost control does nothing if kPa below the hysteresis point - boostDisable(); + boostPID.Initialize(); //This resets the ITerm value to prevent rubber banding + //Boost control needs to have a high duty cycle if control is below threshold (baro or fixed value). This ensures the waste gate is closed as much as possible, this build boost as fast as possible. + currentStatus.boostDuty = configPage15.boostDCWhenDisabled*100; + boost_pwm_target_value = ((unsigned long)(currentStatus.boostDuty) * boost_pwm_max_count) / 10000; //Convert boost duty (Which is a % multipled by 100) to a pwm count + ENABLE_BOOST_TIMER(); //Turn on the compare unit (ie turn on the interrupt) if boost duty >0 + if(currentStatus.boostDuty==0){ + //If boost control does nothing disable PWM completely + boostDisable(); + } } //MAP above boost + hyster } //Open / Cloosed loop diff --git a/speeduino/comms_legacy.cpp b/speeduino/comms_legacy.cpp index 0aa503cc..e921ac0e 100644 --- a/speeduino/comms_legacy.cpp +++ b/speeduino/comms_legacy.cpp @@ -1043,6 +1043,11 @@ void sendPageASCII() serial_print_3dtable(&ignitionTable2, ignitionTable2.type_key); break; + case boostvvtPage2: + Serial.println(F("\nBoost lookup table")); + serial_print_3dtable(&boostTableLookupDuty, boostTableLookupDuty.type_key); + break; + case warmupPage: case progOutsPage: default: diff --git a/speeduino/globals.h b/speeduino/globals.h index de89856d..08a805bf 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -279,6 +279,9 @@ #define BOOST_MODE_SIMPLE 0 #define BOOST_MODE_FULL 1 +#define EN_BOOST_CONTROL_BARO 0 +#define EN_BOOST_CONTROL_FIXED 1 + #define WMI_MODE_SIMPLE 0 #define WMI_MODE_PROPORTIONAL 1 #define WMI_MODE_OPENLOOP 2 @@ -443,6 +446,7 @@ extern struct table3d16RpmLoad ignitionTable2; //16x16 ignition map extern struct table3d16RpmLoad afrTable; //16x16 afr target map extern struct table3d8RpmLoad stagingTable; //8x8 fuel staging table extern struct table3d8RpmLoad boostTable; //8x8 boost map +extern struct table3d8RpmLoad boostTableLookupDuty; //8x8 boost map extern struct table3d8RpmLoad vvtTable; //8x8 vvt map extern struct table3d8RpmLoad vvt2Table; //8x8 vvt map extern struct table3d8RpmLoad wmiTable; //8x8 wmi map @@ -1430,6 +1434,24 @@ struct config13 { } __attribute__((__packed__)); //The 32 bit systems require all structs to be fully packed #endif +/** +Page 15 - second page for VVT and boost control. +256 bytes long. +*/ +struct config15 { + byte boostControlEnable : 1; + byte unused15_1 : 7; //7bits unused + byte boostDCWhenDisabled; + byte boostControlEnableThreshold; //if fixed value enable set threshold here. + byte unused15_3_176[173]; + +#if defined(CORE_AVR) + }; +#else + } __attribute__((__packed__)); //The 32 bit systems require all structs to be fully packed +#endif + + extern byte pinInjector1; //Output pin injector 1 extern byte pinInjector2; //Output pin injector 2 extern byte pinInjector3; //Output pin injector 3 @@ -1522,6 +1544,7 @@ extern struct config6 configPage6; extern struct config9 configPage9; extern struct config10 configPage10; extern struct config13 configPage13; +extern struct config15 configPage15; //extern byte cltCalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the coolant sensor calibration values */ //extern byte iatCalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the inlet air temperature sensor calibration values */ //extern byte o2CalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the O2 sensor calibration values */ diff --git a/speeduino/globals.ino b/speeduino/globals.ino index 56f496c0..412c4f86 100644 --- a/speeduino/globals.ino +++ b/speeduino/globals.ino @@ -15,6 +15,7 @@ struct table3d16RpmLoad ignitionTable2; ///< 16x16 ignition map struct table3d16RpmLoad afrTable; ///< 16x16 afr target map struct table3d8RpmLoad stagingTable; ///< 8x8 fuel staging table struct table3d8RpmLoad boostTable; ///< 8x8 boost map +struct table3d8RpmLoad boostTableLookupDuty; ///< 8x8 boost map lookup table struct table3d8RpmLoad vvtTable; ///< 8x8 vvt map struct table3d8RpmLoad vvt2Table; ///< 8x8 vvt2 map struct table3d8RpmLoad wmiTable; ///< 8x8 wmi map @@ -255,6 +256,7 @@ struct config6 configPage6; struct config9 configPage9; struct config10 configPage10; struct config13 configPage13; +struct config15 configPage15; //byte cltCalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the coolant sensor calibration values */ //byte iatCalibrationTable[CALIBRATION_TABLE_SIZE]; /**< An array containing the inlet air temperature sensor calibration values */ diff --git a/speeduino/pages.cpp b/speeduino/pages.cpp index 59ed76ba..3d583482 100644 --- a/speeduino/pages.cpp +++ b/speeduino/pages.cpp @@ -24,7 +24,7 @@ // 2. Offset to intra-entity byte // Page sizes as defined in the .ini file -constexpr const uint16_t PROGMEM ini_page_sizes[] = { 0, 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288 }; +constexpr const uint16_t PROGMEM ini_page_sizes[] = { 0, 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288, 256 }; // ========================= Table size calculations ========================= // Note that these should be computed at compile time, assuming the correct @@ -398,6 +398,13 @@ page_iterator_t map_page_offset_to_entity(uint8_t pageNumber, uint16_t offset) END_OF_PAGE(progOutsPage, 1) } + case boostvvtPage2: //Boost, VVT and staging maps (all 8x8) + { + CHECK_TABLE(boostvvtPage2, offset, &boostTableLookupDuty, 0) + CHECK_RAW(boostvvtPage2, offset, &configPage15, sizeof(configPage15), 1) + END_OF_PAGE(boostvvtPage2, 2) + } + default: abort(); // Unknown page number. Not a lot we can do. break; diff --git a/speeduino/pages.h b/speeduino/pages.h index 247db4d5..6fd88da1 100644 --- a/speeduino/pages.h +++ b/speeduino/pages.h @@ -13,20 +13,22 @@ uint8_t getPageCount(); uint16_t getPageSize(byte pageNum /**< [in] The page number */ ); // These are the page numbers that the Tuner Studio serial protocol uses to transverse the different map and config pages. -#define veMapPage 2 -#define veSetPage 1 //Note that this and the veMapPage were swapped in Feb 2019 as the 'algorithm' field must be declared in the ini before it's used in the fuel table -#define ignMapPage 3 -#define ignSetPage 4//Config Page 2 -#define afrMapPage 5 -#define afrSetPage 6//Config Page 3 -#define boostvvtPage 7 -#define seqFuelPage 8 -#define canbusPage 9//Config Page 9 -#define warmupPage 10 //Config Page 10 -#define fuelMap2Page 11 -#define wmiMapPage 12 -#define progOutsPage 13 -#define ignMap2Page 14 +#define veMapPage 2 +#define veSetPage 1 //Note that this and the veMapPage were swapped in Feb 2019 as the 'algorithm' field must be declared in the ini before it's used in the fuel table +#define ignMapPage 3 +#define ignSetPage 4//Config Page 2 +#define afrMapPage 5 +#define afrSetPage 6//Config Page 3 +#define boostvvtPage 7 +#define seqFuelPage 8 +#define canbusPage 9//Config Page 9 +#define warmupPage 10 //Config Page 10 +#define fuelMap2Page 11 +#define wmiMapPage 12 +#define progOutsPage 13 +#define ignMap2Page 14 +#define boostvvtPage2 15 + // ============================== Per-byte page access ========================== diff --git a/speeduino/src/PID_v1/PID_v1.cpp b/speeduino/src/PID_v1/PID_v1.cpp index cd731d9c..6d5e8270 100755 --- a/speeduino/src/PID_v1/PID_v1.cpp +++ b/speeduino/src/PID_v1/PID_v1.cpp @@ -553,6 +553,18 @@ integerPID_ideal::integerPID_ideal(long* Input, uint16_t* Output, uint16_t* Setp * false when nothing has been done. **********************************************************************************/ bool integerPID_ideal::Compute() +{ + //This is the orginal PID with 50% Base target DC + return Compute(50*limitMultiplier); +} + +/* Compute() ********************************************************************** + * This, as they say, is where the magic happens. this function should be called + * every time "void loop()" executes. the function will decide for itself whether a new + * pid Output needs to be computed. returns true when the output is computed, + * false when nothing has been done. + **********************************************************************************/ +bool integerPID_ideal::Compute(uint16_t FeedForward) { unsigned long now = millis(); //SampleTime = (now - lastTime); @@ -567,19 +579,19 @@ bool integerPID_ideal::Compute() ITerm += error; - uint16_t bias = 50; //Base target DC% + // uint16_t bias = 50; //Base target DC% long output = 0; if(ki != 0) { - output = ((outMax - bias) * limitMultiplier * 100) / (long)ki; + output = ((outMax * limitMultiplier * 100) - FeedForward) / (long)ki; if (output < 0) { output = 0; } } if (ITerm > output) { ITerm = output; } if(ki != 0) { - output = ((bias - outMin) * limitMultiplier * 100) / (long)ki; + output = (FeedForward - (-outMin * limitMultiplier * 100)) / (long)ki; if (output < 0) { output = 0; } } else { output = 0; } @@ -587,7 +599,7 @@ bool integerPID_ideal::Compute() /*Compute PID Output*/ output = (kp * error) + (ki * ITerm) + (kd * (error - lastError)); - output = (bias * limitMultiplier) + (output / 10); //output is % multipled by 1000. To get % with 2 decimal places, divide it by 10. Likewise, bias is % in whole numbers. Multiply it by 100 to get it with 2 places. + output = FeedForward + (output / 10); //output is % multipled by 1000. To get % with 2 decimal places, divide it by 10. Likewise, bias is % in whole numbers. Multiply it by 100 to get it with 2 places. //if(output > (outMax * limitMultiplier)) { output = (outMax * limitMultiplier); } //if(output < (outMin * limitMultiplier)) { output = (outMin * limitMultiplier); } diff --git a/speeduino/src/PID_v1/PID_v1.h b/speeduino/src/PID_v1/PID_v1.h index 694c1f3e..b3e9b274 100755 --- a/speeduino/src/PID_v1/PID_v1.h +++ b/speeduino/src/PID_v1/PID_v1.h @@ -175,6 +175,10 @@ class integerPID_ideal // called every time loop() cycles. ON/OFF and // calculation frequency can be set using SetMode // SetSampleTime respectively + bool Compute(uint16_t); // * performs the PID calculation. it should be + // called every time loop() cycles. ON/OFF and + // calculation frequency can be set using SetMode + // SetSampleTime respectively void SetOutputLimits(long, long); //clamps the output to a specific range. 0-255 by default, but //it's likely the user will want to change this depending on diff --git a/speeduino/storage.cpp b/speeduino/storage.cpp index f32c1c87..1bd200f6 100644 --- a/speeduino/storage.cpp +++ b/speeduino/storage.cpp @@ -281,6 +281,19 @@ void writeConfig(uint8_t pageNum) result = writeTable(&ignitionTable2, ignitionTable2.type_key, { EEPROM_CONFIG14_MAP, 0 }); break; + case boostvvtPage2: + /*--------------------------------------------------- + | Boost duty cycle lookuptable (See storage.h for data layout) - Page 15 + | 8x8 table itself + the 8 values along each of the axis + -----------------------------------------------------*/ + result = writeTable(&boostTableLookupDuty, boostTableLookupDuty.type_key, { EEPROM_CONFIG15_MAP, result.counter }); + + /*--------------------------------------------------- + | Config page 15 (See storage.h for data layout) + -----------------------------------------------------*/ + result = write_range((byte *)&configPage15, (byte *)&configPage15+sizeof(configPage15), { EEPROM_CONFIG15_START, 0}); + break; + default: break; } @@ -433,6 +446,11 @@ void loadConfig() loadTable(&ignitionTable2, ignitionTable2.type_key, EEPROM_CONFIG14_MAP); + //********************************************************************************************************************************************************************************* + //CONFIG PAGE (15) + boost duty lookup table (LUT) + loadTable(&boostTableLookupDuty, boostTableLookupDuty.type_key, EEPROM_CONFIG15_MAP); + load_range(EEPROM_CONFIG15_START, (byte *)&configPage15, (byte *)&configPage15+sizeof(configPage15)); + //********************************************************************************************************************************************************************************* } diff --git a/speeduino/storage.h b/speeduino/storage.h index 072b6a9d..7603d659 100644 --- a/speeduino/storage.h +++ b/speeduino/storage.h @@ -95,7 +95,12 @@ * | 3151 |36 | Trim8 table (6x6) | @ref EEPROM_CONFIG8_MAP8 | * | 3187 |6 | Trim8 table (X axis) (RPM) | | * | 3193 |6 | Trim8 table (Y axis) (MAP) | | - * | 3199 |475 | EMPTY | | + * | 3199 |2 | X and Y sizes boostLUT table | | + * | 3201 |64 | boostLUT table (8x8) | @ref EEPROM_CONFIG15_MAP | + * | 3265 |8 | boostLUT table (X axis) (RPM) | | + * | 3273 |8 | boostLUT table (Y axis) (targetBoost)| | + * | 3281 |176 | Page 15 settings | @ref EEPROM_CONFIG15_START | + * | 3457 |217 | EMPTY | | * | 3674 |4 | CLT Calibration CRC32 | | * | 3678 |4 | IAT Calibration CRC32 | | * | 3682 |4 | O2 Calibration CRC32 | | @@ -174,6 +179,12 @@ extern uint32_t deferEEPROMWritesUntil; #define EEPROM_CONFIG8_MAP7 3101 #define EEPROM_CONFIG8_MAP8 3151 +//Page 15 added after OUT OF ORDER page 8 +#define EEPROM_CONFIG15_MAP 3199 +#define EEPROM_CONFIG15_START 3281 +#define EEPROM_CONFIG15_END 3457 + + #define EEPROM_CALIBRATION_CLT_CRC 3674 #define EEPROM_CALIBRATION_IAT_CRC 3678 #define EEPROM_CALIBRATION_O2_CRC 3682 diff --git a/speeduino/updates.ino b/speeduino/updates.ino index 075394b6..264a2b07 100644 --- a/speeduino/updates.ino +++ b/speeduino/updates.ino @@ -621,10 +621,48 @@ void doUpdates() configPage2.canBMWCluster = 0; configPage2.canVAGCluster = 0; + + configPage15.boostDCWhenDisabled = 0; + configPage15.boostControlEnable = EN_BOOST_CONTROL_BARO; + + //Fill the boostTableLookupDuty with all 50% duty cycle. This is the same as the hardcoded 50% DC that had been used before. + //This makes the boostcontrol fully backwards compatible. + auto table_it = boostTableLookupDuty.values.begin(); + while (!table_it.at_end()) + { + auto row = *table_it; + while (!row.at_end()) + { + *row = 50*2; + ++row; + } + ++table_it; + } + + //Set some sensible values at the RPM axis + auto table_X = boostTableLookupDuty.axisX.begin(); + uint16_t i = 0; + while (!table_X.at_end()) + { + ++i; + *table_X = 1000+(500*i); + ++table_X; + } + + //Set some sensible values at the boosttarget axis + auto table_Y = boostTableLookupDuty.axisY.begin(); + i = 0; + while (!table_Y.at_end()) + { + ++i; + *table_Y = (120 + 10*i); + ++table_Y; + } + writeAllConfig(); storeEEPROMVersion(20); } - + //Final check is always for 255 and 0 (Brand new arduino) if( (readEEPROMVersion() == 0) || (readEEPROMVersion() == 255) ) {