From 0a5d226756f4441779637be6fe8d1e9eb75ed72a Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Wed, 1 Jun 2022 00:04:20 +0000 Subject: [PATCH 01/46] Disable SD on T4.1 temporarily to prevent lockups. See #847 --- speeduino/board_teensy41.h | 5 +++-- speeduino/board_teensy41.ino | 6 ++++++ speeduino/rtc_common.ino | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/speeduino/board_teensy41.h b/speeduino/board_teensy41.h index b3e7d6a6..bfbe8017 100644 --- a/speeduino/board_teensy41.h +++ b/speeduino/board_teensy41.h @@ -10,17 +10,18 @@ uint16_t freeRam(); void doSystemReset(); void jumpToBootloader(); + time_t getTeensy3Time(); #define PORT_TYPE uint32_t //Size of the port variables #define PINMASK_TYPE uint32_t #define COMPARE_TYPE uint32_t #define COUNTER_TYPE uint32_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) - #define SD_LOGGING //SD logging enabled by default for Teensy 4.1 as it has the slot built in #define BOARD_MAX_DIGITAL_PINS 34 #define BOARD_MAX_IO_PINS 34 //digital pins + analog channels + 1 #define EEPROM_LIB_H typedef int eeprom_address_t; - #define RTC_ENABLED + //#define RTC_ENABLED + //#define SD_LOGGING //SD logging enabled by default for Teensy 4.1 as it has the slot built in #define RTC_LIB_H "TimeLib.h" #define SD_CONFIG SdioConfig(FIFO_SDIO) //Set Teensy to use SDIO in FIFO mode. This is the fastest SD mode on Teensy as it offloads most of the writes diff --git a/speeduino/board_teensy41.ino b/speeduino/board_teensy41.ino index 0a903660..1cb1965d 100644 --- a/speeduino/board_teensy41.ino +++ b/speeduino/board_teensy41.ino @@ -266,6 +266,12 @@ uint16_t freeRam() return (uint16_t)stackTop - heapTop; } +//This function is used for attempting to set the RTC time during compile +time_t getTeensy3Time() +{ + return Teensy3Clock.get(); +} + void doSystemReset() { return; } void jumpToBootloader() { return; } diff --git a/speeduino/rtc_common.ino b/speeduino/rtc_common.ino index ba9bf233..b858ea7e 100644 --- a/speeduino/rtc_common.ino +++ b/speeduino/rtc_common.ino @@ -7,7 +7,7 @@ void initRTC() { - #if defined(CORE_TEENSY35) || defined(CORE_TEENSY36) + #if defined(CORE_TEENSY35) || defined(CORE_TEENSY36)|| defined(CORE_TEENSY41) setSyncProvider(getTeensy3Time); #elif defined(CORE_STM32) From b3acfe9f7452aac6c49941d9c50718cb033b7803 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Wed, 1 Jun 2022 17:06:44 +1000 Subject: [PATCH 02/46] Fix unit test value --- platformio.ini | 2 +- test/test_fuel/test_corrections.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 393d4d10..2fd48f4a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,7 +15,7 @@ framework=arduino build_unflags = -Os build_flags = -O3 -ffast-math -fshort-enums -funroll-loops -Wall -Wextra -std=c99 lib_deps = EEPROM, Time -test_build_project_src = true +;test_build_project_src = true test_build_src = yes debug_tool = simavr test_ignore = test_table3d_native diff --git a/test/test_fuel/test_corrections.cpp b/test/test_fuel/test_corrections.cpp index 7a84d27f..186fa84f 100644 --- a/test/test_fuel/test_corrections.cpp +++ b/test/test_fuel/test_corrections.cpp @@ -297,7 +297,7 @@ void test_corrections_TAE_50pc_warmup_taper() currentStatus.TPS = 50; //25% actual value //Set a cold % of 50% increase - configPage2.aeColdPct = 200; + configPage2.aeColdPct = 150; configPage2.aeColdTaperMax = 60 + CALIBRATION_TEMPERATURE_OFFSET; configPage2.aeColdTaperMin = 0 + CALIBRATION_TEMPERATURE_OFFSET; //Set the coolant to be 50% of the way through the warmup range From 256e4acd2e25ca37fc8529e61f7f7523e45abbe9 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 03/46] 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) ) { From c97d2b1162e86664f5596f1488734ba8b167acb1 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Fri, 3 Jun 2022 16:14:30 +1000 Subject: [PATCH 04/46] Minor cleanup of boost dialog from previous PR --- reference/speeduino.ini | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 8006de03..d756792d 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -2274,7 +2274,6 @@ menuDialog = main 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] @@ -2787,12 +2786,19 @@ menuDialog = main field = "Gear 5 ", boostByGear5, { boostByGearEnabled } field = "Gear 6 ", boostByGear6, { boostByGearEnabled } + dialog = boostBaseDC, "Closed loop initial duty" + field = "Base duty cycle to be used for a given boost target", , { hardRevMode == 2 } + panel = boostDCLupTbl, { boostEnabled & boostType == 1 } + + dialog = boostDCTarget, "Primary Boost table" + field = "In open loop mode, the values in this table are duty cycle %", , { }, { boostType == 0 } + field = "In closed loop mode, the values are boost targets in kPa", , { }, { boostType == 1 } + panel = boostTbl + dialog = boostLoad, "" field = "Mode", boostType - 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 } + panel = boostDCTarget + panel = boostBaseDC, { boostType == 1 } dialog = coolantProtection, "Coolant Based Rev Limit" panel = coolant_prot_curve, { hardRevMode == 2 } @@ -4579,7 +4585,7 @@ cmdVSSratio6 = "E\x99\x06" gridHeight = 3.0 upDownLabel = "HIGHER", "LOWER" - table = boostDCLupTbl, boostDutyLookup, "Boost target -> boost valve duty cycle lookup Table", 7 + table = boostDCLupTbl, boostDutyLookup, "Base duty for closed loop", 7 xBins = rpmBinsDutyLookup, rpm yBins = loadBinsDutyLookup, boostTarget zBins = boostTableDutyLookup From 892303dad014425137e1057657ffcd1c91f76c21 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Fri, 3 Jun 2022 18:23:22 +1000 Subject: [PATCH 05/46] Add dynamic EEPROM block write limit based on RPM. Should fix #859 --- reference/speeduino.ini | 8 ++++---- speeduino/storage.cpp | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index d756792d..b91e4b86 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -2787,12 +2787,12 @@ menuDialog = main field = "Gear 6 ", boostByGear6, { boostByGearEnabled } dialog = boostBaseDC, "Closed loop initial duty" - field = "Base duty cycle to be used for a given boost target", , { hardRevMode == 2 } - panel = boostDCLupTbl, { boostEnabled & boostType == 1 } + field = "Base duty cycle to be used for a given boost target", {}, { boostType == 2 } + panel = boostDCLupTbl, { boostEnabled && boostType == 1 } dialog = boostDCTarget, "Primary Boost table" - field = "In open loop mode, the values in this table are duty cycle %", , { }, { boostType == 0 } - field = "In closed loop mode, the values are boost targets in kPa", , { }, { boostType == 1 } + field = "In open loop mode, the values in this table are duty cycle %", {}, {}, { boostType == 0 } + field = "In closed loop mode, the values in this table are boost targets in kPa", {}, {}, { boostType == 1 } panel = boostTbl dialog = boostLoad, "" diff --git a/speeduino/storage.cpp b/speeduino/storage.cpp index 1bd200f6..2416578a 100644 --- a/speeduino/storage.cpp +++ b/speeduino/storage.cpp @@ -13,11 +13,14 @@ A full copy of the license may be found in the projects root directory #include "pages.h" #include "table3d_axis_io.h" + + //The maximum number of write operations that will be performed in one go. If we try to write to the EEPROM too fast (Each write takes ~3ms) then the rest of the system can hang) #if defined(CORE_STM32) || defined(CORE_TEENSY) & !defined(USE_SPI_EEPROM) -#define EEPROM_MAX_WRITE_BLOCK 64 +//#define EEPROM_MAX_WRITE_BLOCK 64 + uint8_t EEPROM_MAX_WRITE_BLOCK = 64; #else -#define EEPROM_MAX_WRITE_BLOCK 24 + uint8_t EEPROM_MAX_WRITE_BLOCK = 24; //#define EEPROM_MAX_WRITE_BLOCK 8 #endif @@ -153,7 +156,15 @@ void writeConfig(uint8_t pageNum) { write_location result = { 0, 0 }; - //if(micros() < deferEEPROMWritesUntil) { result.counter = (EEPROM_MAX_WRITE_BLOCK + 1); } //If we are deferring writes then we don't want to write anything. This will force can_write() to return false and the write will be skipped. + #ifdef CORE_AVR + //In order to prevent missed pulses during EEPROM writes on AVR, scale the maximum write block size based on the RPM + //This calculation is based on EEPROM writes taking approximately 4ms per byte (Actual value is 3.8ms, so 4ms has some safety margin) + if(currentStatus.RPM > 65) { EEPROM_MAX_WRITE_BLOCK = (15000 / currentStatus.RPM); } //Min RPM of 65 prevents overflow of uint8_t. + else { EEPROM_MAX_WRITE_BLOCK = 24; } + + if(EEPROM_MAX_WRITE_BLOCK < 1) { EEPROM_MAX_WRITE_BLOCK = 1; } + if(EEPROM_MAX_WRITE_BLOCK > 24) { EEPROM_MAX_WRITE_BLOCK = 24; } //Any higher than this will cause comms timeouts on AVR + #endif switch(pageNum) { From 59ccd052e35b2a39a688f364b40c95675266765a Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Mon, 6 Jun 2022 14:33:41 +1000 Subject: [PATCH 06/46] Only set the idle up pin state on init if it's enabled --- speeduino/idle.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speeduino/idle.ino b/speeduino/idle.ino index 097c89b4..accb29aa 100644 --- a/speeduino/idle.ino +++ b/speeduino/idle.ino @@ -273,7 +273,7 @@ void initialiseIdleUpOutput() if (configPage2.idleUpOutputInv == 1) { idleUpOutputHIGH = LOW; idleUpOutputLOW = HIGH; } else { idleUpOutputHIGH = HIGH; idleUpOutputLOW = LOW; } - digitalWrite(pinIdleUpOutput, idleUpOutputLOW); //Initialise program with the idle up output in the off state + if(configPage2.idleUpEnabled > 0) { digitalWrite(pinIdleUpOutput, idleUpOutputLOW); } //Initialise program with the idle up output in the off state if it is enabled. currentStatus.idleUpOutputActive = false; idleUpOutput_pin_port = portOutputRegister(digitalPinToPort(pinIdleUpOutput)); From 8843e28a43b3a5d371d565dc7323db58919c8ab3 Mon Sep 17 00:00:00 2001 From: larmicfre <49905831+larmicfre@users.noreply.github.com> Date: Mon, 20 Jun 2022 01:52:07 +0200 Subject: [PATCH 07/46] AFR protection function (#861) * Implementing AFR protection * Update globals.h * Bug fixes and code refactoring * Moved variables to prevent ODR * Dialog for AFR protection * Data size and math corrections * Possibility to use either AFR or lambda * Updated default AFR protection values * No need to do multiplications due to existing RPMdiv100 variable * The X100 multiplier was wrongfully removed * Add defaults in updates.ino, minor formatting cleanups Co-authored-by: Josh Stewart --- reference/speeduino.ini | 60 ++++++++++++++++++++++++- speeduino/engineProtection.h | 1 - speeduino/engineProtection.ino | 80 +++++++++++++++++++++++++++++++++- speeduino/globals.h | 18 +++++--- speeduino/speeduino.ino | 4 +- speeduino/updates.ino | 7 +++ 6 files changed, 157 insertions(+), 13 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index b91e4b86..acc46c92 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -1055,7 +1055,21 @@ page = 9 #else coolantProtTemp = array, U08, 173, [6], "F", 1.8, -22.23, -40, 215, 0 #endif - unused179_191 = array, U08, 179, [13], "", 1, 0, 0, 255, 0 + + unused179_184 = array, U08, 179, [6], "", 1, 0, 0, 255, 0 + + ; AFR engine protection + afrProtectEnabled = bits, U08, 185, [0:0], "Off", "On" + afrProtectMAP = scalar, U08, 186, "kPa", 2.0, 0.0, 0.0, 511.0, 0 ; 8 bit value, 1 byte + afrProtectRPM = scalar, U08, 187, "RPM", 100, 0.0, 100, 25500, 0 ; 8 bit value, 1 byte + afrProtectTPS = scalar, U08, 188, "%", 0.5, 0.0, 0.0, 100.0, 1 ; 8 bit value, 1 byte +#if LAMBDA + afrProtectDeviation = scalar, U08, 189, "Lambda", {0.1 / stoich}, 0.0, 0.00, 25.5, 2 ; 8 bit value, 1 byte +#else + afrProtectDeviation = scalar, U08, 189, "AFR", 0.1, 0.0, 0.0, 25.5, 1 ; 8 bit value, 1 byte +#endif + afrProtectCutTime = scalar, U08, 190, "seconds", 0.1, 0.0, 0.0, 2.5, 1 ; 8 bit value, 1 byte + afrProtectReactivationTPS = scalar, U08, 191, "%", 0.5, 0.0, 0.0, 100.0, 1 ; 8 bit value, 1 byte page = 10 #if CELSIUS @@ -1571,6 +1585,19 @@ page = 15 #endif defaultValue = vvtDelay, 60 + ; AFR protection default values + defaultValue = afrProtectEnabled, 0 + defaultValue = afrProtectMAP, 180 + defaultValue = afrProtectRPM, 4000 + defaultValue = afrProtectTPS, 80 +#if LAMBDA + defaultValue = afrProtectDeviation, 0.10 +#else + defaultValue = afrProtectDeviation, 1.47 +#endif + defaultValue = afrProtectCutTime, 0.8 + defaultValue = afrProtectReactivationTPS, 20 + ;Default pins defaultValue = fanPin, 0 defaultValue = vvt1Pin, 0 @@ -1757,6 +1784,7 @@ menuDialog = main groupChildMenu = revLimiterDialog, "Rev Limiters", { engineProtectType } groupChildMenu = boostCut, "Boost Cut", { engineProtectType } groupChildMenu = oilPressureProtection, "Oil Pressure", { engineProtectType } + groupChildMenu = afrProtect, "AFR Protection", { engineProtectType } subMenu = flexFuel, "Flex Fuel", 2 subMenu = veTableDialog, "VE Table", 0 subMenu = sparkTbl, "Spark Table", 2 @@ -1995,6 +2023,18 @@ menuDialog = main hardRevLim = "A fixed hard rev limit is a single 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" + ; AFR Protection Help + afrProtectMAP = "Minimum manifold air pressure the AFR lean protection will activate" + afrProtectRPM = "The minimum RPM the AFR lean protection will activate" + afrProtectTPS = "The minimum current throttle position for the AFR lean protection to activate" +#if LAMBDA + afrProtectDeviation = "Maximum deviation from current lambda value in which lean protection will activate" +#else + afrProtectDeviation = "Maximum deviation from current AFR value in which lean protection will activate" +#endif + afrProtectCutTime = "A time delay before activating engine protection when all conditions has been met" + afrProtectReactivationTPS = "Going below this throttle position (%) will deactivate this protection" + 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" fuel2InputPullup = "Whether to use the built in PULLUP for the switching input. This should be Yes for a typical ground switching input" @@ -2818,7 +2858,23 @@ menuDialog = main field = "Oil Pressure Protection", oilPressureProtEnbl, { oilPressureEnable } panel = oil_pressure_prot_curve, { oilPressureEnable && oilPressureProtEnbl } - + ; AFR engine protection dialog + dialog = afrProtect, "AFR Protection", yAxis + field = "AFR protection is used to prevent engine from running lean" + field = "#Note: This function requires wideband sensor and proper AFR table" + field = "" + field = "Enable AFR protection ", afrProtectEnabled, {egoType == 2} + field = "Minimum manifold air pressure ", afrProtectMAP, {afrProtectEnabled} + field = "Minimum engine RPM ", afrProtectRPM, {afrProtectEnabled} + field = "Minimum throttle position ", afrProtectTPS, {afrProtectEnabled} +#if LAMBDA + field = "Maximum lambda deviation ", afrProtectDeviation, {afrProtectEnabled} +#else + field = "Maximum AFR deviation ", afrProtectDeviation, {afrProtectEnabled} +#endif + field = "Time before cut ", afrProtectCutTime, {afrProtectEnabled} + field = "" + field = "Reactivate below throttle ", afrProtectReactivationTPS, {afrProtectEnabled} indicatorPanel = protectIndicatorPanel, 1, { 1 } indicator = { engineProtectStatus}, "Engine Protect OFF", "Engine Protect ON", green, black, red, black diff --git a/speeduino/engineProtection.h b/speeduino/engineProtection.h index 09a05b43..d98f5312 100644 --- a/speeduino/engineProtection.h +++ b/speeduino/engineProtection.h @@ -2,7 +2,6 @@ #define HARD_REV_FIXED 1 #define HARD_REV_COOLANT 2 - byte checkEngineProtect(); byte checkRevLimit(); byte checkBoostLimit(); diff --git a/speeduino/engineProtection.ino b/speeduino/engineProtection.ino index 5a87ed5a..b69f09cc 100644 --- a/speeduino/engineProtection.ino +++ b/speeduino/engineProtection.ino @@ -112,7 +112,85 @@ byte checkOilPressureLimit() byte checkAFRLimit() { - byte checkAFRLimitActive = 0; + static bool checkAFRLimitActive = false; + static bool afrProtectCountEnabled = false; + static unsigned long afrProtectCount = 0; + static constexpr char X2_MULTIPLIER = 2; + static constexpr char X100_MULTIPLIER = 100; + + /* + To use this function, a wideband sensor is required. + + First of all, check whether engine protection is enabled, + thereafter check whether AFR protection is enabled and at last + if wideband sensor is used. + + After confirmation, the following conditions has to be met: + - MAP above x kPa + - RPM above x + - TPS above x % + - AFR threshold (AFR target + defined maximum deviation) + - Time before cut + + See afrProtect variables in globals.h for more information. + + If all conditions above are true, a specified time delay is starting + to count down in which leads to the engine protection function + to be activated using selected protection cut method (e.g. ignition, + fuel or both). + + For reactivation, the following condition has to be met: + - TPS below x % + */ + + /* + Do 3 checks here; + - whether engine protection is enabled + - whether AFR protection is enabled + - whether wideband sensor is used + */ + if(configPage6.engineProtectType != PROTECT_CUT_OFF && configPage9.afrProtectEnabled && configPage6.egoType == EGO_TYPE_WIDE) { + /* Conditions */ + bool mapCondition = (currentStatus.MAP >= (configPage9.afrProtectMinMAP * X2_MULTIPLIER)) ? true : false; + bool rpmCondition = (currentStatus.RPMdiv100 >= configPage9.afrProtectMinRPM) ? true : false; + bool tpsCondition = (currentStatus.TPS >= configPage9.afrProtectMinTPS) ? true : false; + bool afrCondition = (currentStatus.O2 >= (currentStatus.afrTarget + configPage9.afrProtectDeviation)) ? true : false; + + /* Check if conditions above are fulfilled */ + if(mapCondition && rpmCondition && tpsCondition && afrCondition) + { + /* All conditions fulfilled - start counter for 'protection delay' */ + if(!afrProtectCountEnabled) + { + afrProtectCountEnabled = true; + afrProtectCount = millis(); + } + + /* Check if countdown has reached its target, if so then instruct to cut */ + if(millis() >= (afrProtectCount + (configPage9.afrProtectCutTime * X100_MULTIPLIER))) + { + checkAFRLimitActive = true; + BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_AFR); + } + } + else + { + /* Conditions have presumably changed - deactivate and reset counter */ + if(afrProtectCountEnabled) + { + afrProtectCountEnabled = false; + afrProtectCount = 0; + } + } + + /* Check if condition for reactivation is fulfilled */ + if(checkAFRLimitActive && (currentStatus.TPS <= configPage9.afrProtectReactivationTPS)) + { + checkAFRLimitActive = false; + afrProtectCountEnabled = false; + BIT_CLEAR(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_AFR); + } + } return checkAFRLimitActive; } diff --git a/speeduino/globals.h b/speeduino/globals.h index 08a805bf..bf6a55e1 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -248,6 +248,10 @@ #define COMPOSITE_LOG_TRIG 2 #define COMPOSITE_LOG_SYNC 3 +#define EGO_TYPE_OFF 0 +#define EGO_TYPE_NARROW 1 +#define EGO_TYPE_WIDE 2 + #define INJ_TYPE_PORT 0 #define INJ_TYPE_TBODY 1 @@ -1180,13 +1184,13 @@ struct config9 { byte unused10_182; byte unused10_183; byte unused10_184; - byte unused10_185; - byte unused10_186; - byte unused10_187; - byte unused10_188; - byte unused10_189; - byte unused10_190; - byte unused10_191; + byte afrProtectEnabled : 1; /* < AFR protection enabled status. 0 = disabled, 1 = enabled */ + 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 */ + byte afrProtectMinTPS; /* < Minimum TPS. */ + byte afrProtectDeviation; /* < Maximum deviation from AFR target table. Stored value is multiplied by 10 */ + byte afrProtectCutTime; /* < Time in ms before cut. Stored value is divided by 100. Maximum of 2550 ms */ + byte afrProtectReactivationTPS; /* Disable engine protection cut once below this TPS percentage */ #if defined(CORE_AVR) }; diff --git a/speeduino/speeduino.ino b/speeduino/speeduino.ino index e7d44364..997e3125 100644 --- a/speeduino/speeduino.ino +++ b/speeduino/speeduino.ino @@ -1328,7 +1328,7 @@ uint16_t PW(int REQ_FUEL, byte VE, long MAP, uint16_t corrections, int injOpen) if ( configPage2.multiplyMAP == MULTIPLY_MAP_MODE_100) { iMAP = ((unsigned int)MAP << 7) / 100; } else if( configPage2.multiplyMAP == MULTIPLY_MAP_MODE_BARO) { iMAP = ((unsigned int)MAP << 7) / currentStatus.baro; } - if ( (configPage2.includeAFR == true) && (configPage6.egoType == 2) && (currentStatus.runSecs > configPage6.ego_sdelay) ) { + if ( (configPage2.includeAFR == true) && (configPage6.egoType == EGO_TYPE_WIDE) && (currentStatus.runSecs > configPage6.ego_sdelay) ) { iAFR = ((unsigned int)currentStatus.O2 << 7) / currentStatus.afrTarget; //Include AFR (vs target) if enabled } if ( (configPage2.incorporateAFR == true) && (configPage2.includeAFR == false) ) { @@ -1341,7 +1341,7 @@ uint16_t PW(int REQ_FUEL, byte VE, long MAP, uint16_t corrections, int injOpen) unsigned long intermediate = ((uint32_t)REQ_FUEL * (uint32_t)iVE) >> 7; //Need to use an intermediate value to avoid overflowing the long if ( configPage2.multiplyMAP > 0 ) { intermediate = (intermediate * (unsigned long)iMAP) >> 7; } - if ( (configPage2.includeAFR == true) && (configPage6.egoType == 2) && (currentStatus.runSecs > configPage6.ego_sdelay) ) { + if ( (configPage2.includeAFR == true) && (configPage6.egoType == EGO_TYPE_WIDE) && (currentStatus.runSecs > configPage6.ego_sdelay) ) { //EGO type must be set to wideband and the AFR warmup time must've elapsed for this to be used intermediate = (intermediate * (unsigned long)iAFR) >> 7; } diff --git a/speeduino/updates.ino b/speeduino/updates.ino index 264a2b07..79a04821 100644 --- a/speeduino/updates.ino +++ b/speeduino/updates.ino @@ -659,6 +659,13 @@ void doUpdates() ++table_Y; } + //AFR Protection added, add default values + configPage9.afrProtectEnabled = 0; //Disable by default + configPage9.afrProtectMinMAP = 90; //Is divided by 2, vlue represents 180kPa + configPage9.afrProtectMinRPM = 40; //4000 RPM min + configPage9.afrProtectMinTPS = 160; //80% TPS min + configPage9.afrProtectDeviation = 14; //1.4 AFR deviation + writeAllConfig(); storeEEPROMVersion(20); } From 8d91f2a6ea47cf2be729f52d8292d6c30f667edb Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Mon, 20 Jun 2022 15:03:31 +1000 Subject: [PATCH 08/46] Prevent cranking and ASE corrections running at once. Alternative fix to #868 --- speeduino/corrections.ino | 50 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/speeduino/corrections.ino b/speeduino/corrections.ino index 2eaaf924..8302d80e 100644 --- a/speeduino/corrections.ino +++ b/speeduino/corrections.ino @@ -288,7 +288,7 @@ uint16_t correctionCranking() unsigned long taperStart = (unsigned long) crankingValue * 100 / currentStatus.ASEValue; crankingValue = (uint16_t) map(crankingEnrichTaper, 0, configPage10.crankingEnrichTaper, taperStart, 100); //Taper from start value to 100% if (crankingValue < 100) { crankingValue = 100; } //Sanity check - if( BIT_CHECK(TIMER_mask, BIT_TIMER_10HZ) ) { crankingEnrichTaper++; } + if( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) ) { crankingEnrichTaper++; } } return crankingValue; } @@ -298,40 +298,48 @@ uint16_t correctionCranking() * where an additional amount of fuel is added (Over and above the WUE amount). * * @return uint8_t The After Start Enrichment modifier as a %. 100% = No modification. - */ + */ byte correctionASE() { - int16_t ASEValue; + int16_t ASEValue = 100; //Two checks are required: //1) Is the engine run time less than the configured ase time //2) Make sure we're not still cranking - if ( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) || (currentStatus.ASEValue == 0) ) + if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) != true ) { - if ( (currentStatus.runSecs < (table2D_getValue(&ASECountTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET))) && !(BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) ) + if ( BIT_CHECK(LOOP_TIMER, BIT_TIMER_15HZ) || (currentStatus.ASEValue == 0) ) { - BIT_SET(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as active. - ASEValue = 100 + table2D_getValue(&ASETable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); - aseTaper = 0; - } - else - { - if ( (!BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) && (aseTaper < configPage2.aseTaperTime) ) //Cranking check needs to be here also, so cranking and afterstart enrichments won't run simultaneously + if ( (currentStatus.runSecs < (table2D_getValue(&ASECountTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET))) && !(BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) ) { BIT_SET(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as active. - ASEValue = 100 + map(aseTaper, 0, configPage2.aseTaperTime, table2D_getValue(&ASETable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET), 0); - aseTaper++; + ASEValue = 100 + table2D_getValue(&ASETable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); + aseTaper = 0; } else { - BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as inactive. - ASEValue = 100; + if ( aseTaper < configPage2.aseTaperTime ) //Check if we've reached the end of the taper time + { + BIT_SET(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as active. + ASEValue = 100 + map(aseTaper, 0, configPage2.aseTaperTime, table2D_getValue(&ASETable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET), 0); + aseTaper++; + } + else + { + BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as inactive. + ASEValue = 100; + } } + + //Safety checks + if(ASEValue > 255) { ASEValue = 255; } + if(ASEValue < 0) { ASEValue = 0; } + currentStatus.ASEValue = (byte)ASEValue; } - - //Safety checks - if(ASEValue > 255) { ASEValue = 255; } - if(ASEValue < 0) { ASEValue = 0; } - currentStatus.ASEValue = (byte)ASEValue; + } + else + { + BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as inactive. + ASEValue = 100; } return currentStatus.ASEValue; } From 95fa09ba370026fd5b4ed31f7f9046c9a668537a Mon Sep 17 00:00:00 2001 From: larmicfre <49905831+larmicfre@users.noreply.github.com> Date: Sun, 26 Jun 2022 09:43:35 +0200 Subject: [PATCH 09/46] Corrected RPM to TPS (#878). Fixes #874 --- reference/speeduino.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index acc46c92..c051c3cf 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -2091,7 +2091,7 @@ menuDialog = main launchPin = "The ARDUINO pin that the clutch switch is connected to. This is NOT the pin on the connector, but the pin it relates to on the arduino" launchHiLo = "Whether the signal is High or Low when the clutch pedal is engaged. For a ground switching input (Most clutch switches), this should be LOW" lnchPullRes = "Whether the internal pullup resistor is enabled or left floating. For a ground switching input (Most clutch switches), select Pullup. For a 0v-5v input, select Floating" - lnchCtrlTPS = "The minimum RPM that launch control will engage at" + lnchCtrlTPS = "The minimum TPS percentage that launch control will engage at" lnchSoftLim = "The RPM point that the launch control ignition timing adjustment will engage (When under launch conditions). Should be below the hard rev limit RPM" lnchRetard = "When under launch conditions (Eg Clutch engaged) the ignition timing will be set to this when above the Soft rev limit. This will override any other ignition modifiers" lnchHardLim = "The RPM point above which the fuel and/or ignition will be cut when launch is active (Eg Clutch engaged). See the Engine Protection dialog to set whether it is fuel, ignition or both that are cut." From 09ac508051ec52ceae35f7d4b504c857b9e34172 Mon Sep 17 00:00:00 2001 From: larmicfre <49905831+larmicfre@users.noreply.github.com> Date: Mon, 27 Jun 2022 01:21:11 +0200 Subject: [PATCH 10/46] Fixed value mode for AFR protection (#877) --- reference/speeduino.ini | 18 ++++++++++-------- speeduino/engineProtection.ino | 15 ++++++++++++++- speeduino/globals.h | 2 +- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index c051c3cf..0ecc3458 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -1059,7 +1059,7 @@ page = 9 unused179_184 = array, U08, 179, [6], "", 1, 0, 0, 255, 0 ; AFR engine protection - afrProtectEnabled = bits, U08, 185, [0:0], "Off", "On" + afrProtectEnabled = bits, U08, 185, [0:1], "Off", "Fixed mode", "Table mode", "INVALID" afrProtectMAP = scalar, U08, 186, "kPa", 2.0, 0.0, 0.0, 511.0, 0 ; 8 bit value, 1 byte afrProtectRPM = scalar, U08, 187, "RPM", 100, 0.0, 100, 25500, 0 ; 8 bit value, 1 byte afrProtectTPS = scalar, U08, 188, "%", 0.5, 0.0, 0.0, 100.0, 1 ; 8 bit value, 1 byte @@ -2025,14 +2025,14 @@ menuDialog = main ; AFR Protection Help afrProtectMAP = "Minimum manifold air pressure the AFR lean protection will activate" - afrProtectRPM = "The minimum RPM the AFR lean protection will activate" - afrProtectTPS = "The minimum current throttle position for the AFR lean protection to activate" + afrProtectRPM = "Minimum RPM the AFR lean protection will activate" + afrProtectTPS = "Minimum current throttle position for the AFR lean protection to activate" #if LAMBDA - afrProtectDeviation = "Maximum deviation from current lambda value in which lean protection will activate" + afrProtectDeviation = "Fixed mode = A fixed maximum lambda value (e.g. 0.95)\n\nTable mode = A maximum deviation (e.g. 0.1) from current lambda using target table + specified deviation" #else - afrProtectDeviation = "Maximum deviation from current AFR value in which lean protection will activate" + afrProtectDeviation = "Fixed mode = A fixed maximum AFR value (e.g. 14.0)\n\nTable mode = A maximum deviation (e.g. 1.5) from current AFR using target table + specified deviation" #endif - afrProtectCutTime = "A time delay before activating engine protection when all conditions has been met" + afrProtectCutTime = "Time delay before activating AFR protection when all conditions has been fulfilled" afrProtectReactivationTPS = "Going below this throttle position (%) will deactivate this protection" fuel2InputPin = "The Arduino pin that is being used to trigger the second fuel table to be active" @@ -2868,9 +2868,11 @@ menuDialog = main field = "Minimum engine RPM ", afrProtectRPM, {afrProtectEnabled} field = "Minimum throttle position ", afrProtectTPS, {afrProtectEnabled} #if LAMBDA - field = "Maximum lambda deviation ", afrProtectDeviation, {afrProtectEnabled} + field = "Maximum lambda ", afrProtectDeviation, {afrProtectEnabled}, {afrProtectEnabled == 0 || afrProtectEnabled == 1} + field = "Maximum lambda deviation ", afrProtectDeviation, {afrProtectEnabled}, {afrProtectEnabled == 2} #else - field = "Maximum AFR deviation ", afrProtectDeviation, {afrProtectEnabled} + field = "Maximum AFR ", afrProtectDeviation, {afrProtectEnabled}, {afrProtectEnabled == 0 || afrProtectEnabled == 1} + field = "Maximum AFR deviation ", afrProtectDeviation, {afrProtectEnabled}, {afrProtectEnabled == 2} #endif field = "Time before cut ", afrProtectCutTime, {afrProtectEnabled} field = "" diff --git a/speeduino/engineProtection.ino b/speeduino/engineProtection.ino index b69f09cc..87f18c54 100644 --- a/speeduino/engineProtection.ino +++ b/speeduino/engineProtection.ino @@ -154,7 +154,20 @@ byte checkAFRLimit() bool mapCondition = (currentStatus.MAP >= (configPage9.afrProtectMinMAP * X2_MULTIPLIER)) ? true : false; bool rpmCondition = (currentStatus.RPMdiv100 >= configPage9.afrProtectMinRPM) ? true : false; bool tpsCondition = (currentStatus.TPS >= configPage9.afrProtectMinTPS) ? true : false; - bool afrCondition = (currentStatus.O2 >= (currentStatus.afrTarget + configPage9.afrProtectDeviation)) ? true : false; + + /* + Depending on selected mode, this could either be fixed AFR value or a + value set to be the maximum deviation from AFR target table. + + 1 = fixed value mode, 2 = target table mode + */ + bool afrCondition; + switch(configPage9.afrProtectEnabled) + { + case 1: afrCondition = (currentStatus.O2 >= configPage9.afrProtectDeviation) ? true : false; break; /* Fixed value */ + case 2: afrCondition = (currentStatus.O2 >= (currentStatus.afrTarget + configPage9.afrProtectDeviation)) ? true : false; break; /* Deviation from target table */ + default: afrCondition = false; /* Unknown mode. Shouldn't even get here */ + } /* Check if conditions above are fulfilled */ if(mapCondition && rpmCondition && tpsCondition && afrCondition) diff --git a/speeduino/globals.h b/speeduino/globals.h index bf6a55e1..81d7f95a 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -1184,7 +1184,7 @@ struct config9 { byte unused10_182; byte unused10_183; byte unused10_184; - byte afrProtectEnabled : 1; /* < AFR protection enabled status. 0 = disabled, 1 = enabled */ + 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 */ byte afrProtectMinTPS; /* < Minimum TPS. */ From f6b653ea059de694831d5136c66344566d733b7e Mon Sep 17 00:00:00 2001 From: Tjeerd <33102280+Tjeerdie@users.noreply.github.com> Date: Mon, 27 Jun 2022 01:30:40 +0200 Subject: [PATCH 11/46] bug fix. A workaround for failing emulated on internal flash writes + a root cause fix (#876) * workaround for failing flash writes * Root cause fix for EEPROM emulation on STM32 * Oops, remove some debugging functions. Co-authored-by: Tjeerd --- speeduino/board_stm32_official.h | 38 +++++++++++------------ speeduino/board_stm32_official.ino | 29 +---------------- speeduino/scheduler.ino | 13 ++++++++ speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp | 8 +++++ 4 files changed, 41 insertions(+), 47 deletions(-) diff --git a/speeduino/board_stm32_official.h b/speeduino/board_stm32_official.h index 550ea970..23bc6fcb 100644 --- a/speeduino/board_stm32_official.h +++ b/speeduino/board_stm32_official.h @@ -195,20 +195,20 @@ extern "C" char* sbrk(int incr); #define IGN8_COMPARE (TIM4)->CCR4 -#define FUEL1_TIMER_ENABLE() (TIM3)->SR = ~TIM_FLAG_CC1; (TIM3)->DIER |= TIM_DIER_CC1IE -#define FUEL2_TIMER_ENABLE() (TIM3)->SR = ~TIM_FLAG_CC2; (TIM3)->DIER |= TIM_DIER_CC2IE -#define FUEL3_TIMER_ENABLE() (TIM3)->SR = ~TIM_FLAG_CC3; (TIM3)->DIER |= TIM_DIER_CC3IE -#define FUEL4_TIMER_ENABLE() (TIM3)->SR = ~TIM_FLAG_CC4; (TIM3)->DIER |= TIM_DIER_CC4IE +#define FUEL1_TIMER_ENABLE() (TIM3)->CR1 |= TIM_CR1_CEN; (TIM3)->SR = ~TIM_FLAG_CC1; (TIM3)->DIER |= TIM_DIER_CC1IE +#define FUEL2_TIMER_ENABLE() (TIM3)->CR1 |= TIM_CR1_CEN; (TIM3)->SR = ~TIM_FLAG_CC2; (TIM3)->DIER |= TIM_DIER_CC2IE +#define FUEL3_TIMER_ENABLE() (TIM3)->CR1 |= TIM_CR1_CEN; (TIM3)->SR = ~TIM_FLAG_CC3; (TIM3)->DIER |= TIM_DIER_CC3IE +#define FUEL4_TIMER_ENABLE() (TIM3)->CR1 |= TIM_CR1_CEN; (TIM3)->SR = ~TIM_FLAG_CC4; (TIM3)->DIER |= TIM_DIER_CC4IE #define FUEL1_TIMER_DISABLE() (TIM3)->DIER &= ~TIM_DIER_CC1IE #define FUEL2_TIMER_DISABLE() (TIM3)->DIER &= ~TIM_DIER_CC2IE #define FUEL3_TIMER_DISABLE() (TIM3)->DIER &= ~TIM_DIER_CC3IE #define FUEL4_TIMER_DISABLE() (TIM3)->DIER &= ~TIM_DIER_CC4IE -#define IGN1_TIMER_ENABLE() (TIM2)->SR = ~TIM_FLAG_CC1; (TIM2)->DIER |= TIM_DIER_CC1IE -#define IGN2_TIMER_ENABLE() (TIM2)->SR = ~TIM_FLAG_CC2; (TIM2)->DIER |= TIM_DIER_CC2IE -#define IGN3_TIMER_ENABLE() (TIM2)->SR = ~TIM_FLAG_CC3; (TIM2)->DIER |= TIM_DIER_CC3IE -#define IGN4_TIMER_ENABLE() (TIM2)->SR = ~TIM_FLAG_CC4; (TIM2)->DIER |= TIM_DIER_CC4IE +#define IGN1_TIMER_ENABLE() (TIM2)->CR1 |= TIM_CR1_CEN; (TIM2)->SR = ~TIM_FLAG_CC1; (TIM2)->DIER |= TIM_DIER_CC1IE +#define IGN2_TIMER_ENABLE() (TIM2)->CR1 |= TIM_CR1_CEN; (TIM2)->SR = ~TIM_FLAG_CC2; (TIM2)->DIER |= TIM_DIER_CC2IE +#define IGN3_TIMER_ENABLE() (TIM2)->CR1 |= TIM_CR1_CEN; (TIM2)->SR = ~TIM_FLAG_CC3; (TIM2)->DIER |= TIM_DIER_CC3IE +#define IGN4_TIMER_ENABLE() (TIM2)->CR1 |= TIM_CR1_CEN; (TIM2)->SR = ~TIM_FLAG_CC4; (TIM2)->DIER |= TIM_DIER_CC4IE #define IGN1_TIMER_DISABLE() (TIM2)->DIER &= ~TIM_DIER_CC1IE #define IGN2_TIMER_DISABLE() (TIM2)->DIER &= ~TIM_DIER_CC2IE @@ -216,20 +216,20 @@ extern "C" char* sbrk(int incr); #define IGN4_TIMER_DISABLE() (TIM2)->DIER &= ~TIM_DIER_CC4IE -#define FUEL5_TIMER_ENABLE() (TIM5)->SR = ~TIM_FLAG_CC1; (TIM5)->DIER |= TIM_DIER_CC1IE -#define FUEL6_TIMER_ENABLE() (TIM5)->SR = ~TIM_FLAG_CC2; (TIM5)->DIER |= TIM_DIER_CC2IE -#define FUEL7_TIMER_ENABLE() (TIM5)->SR = ~TIM_FLAG_CC3; (TIM5)->DIER |= TIM_DIER_CC3IE -#define FUEL8_TIMER_ENABLE() (TIM5)->SR = ~TIM_FLAG_CC4; (TIM5)->DIER |= TIM_DIER_CC4IE +#define FUEL5_TIMER_ENABLE() (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->SR = ~TIM_FLAG_CC1; (TIM5)->DIER |= TIM_DIER_CC1IE +#define FUEL6_TIMER_ENABLE() (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->SR = ~TIM_FLAG_CC2; (TIM5)->DIER |= TIM_DIER_CC2IE +#define FUEL7_TIMER_ENABLE() (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->SR = ~TIM_FLAG_CC3; (TIM5)->DIER |= TIM_DIER_CC3IE +#define FUEL8_TIMER_ENABLE() (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->SR = ~TIM_FLAG_CC4; (TIM5)->DIER |= TIM_DIER_CC4IE #define FUEL5_TIMER_DISABLE() (TIM5)->DIER &= ~TIM_DIER_CC1IE #define FUEL6_TIMER_DISABLE() (TIM5)->DIER &= ~TIM_DIER_CC2IE #define FUEL7_TIMER_DISABLE() (TIM5)->DIER &= ~TIM_DIER_CC3IE #define FUEL8_TIMER_DISABLE() (TIM5)->DIER &= ~TIM_DIER_CC4IE -#define IGN5_TIMER_ENABLE() (TIM4)->SR = ~TIM_FLAG_CC1; (TIM4)->DIER |= TIM_DIER_CC1IE -#define IGN6_TIMER_ENABLE() (TIM4)->SR = ~TIM_FLAG_CC2; (TIM4)->DIER |= TIM_DIER_CC2IE -#define IGN7_TIMER_ENABLE() (TIM4)->SR = ~TIM_FLAG_CC3; (TIM4)->DIER |= TIM_DIER_CC3IE -#define IGN8_TIMER_ENABLE() (TIM4)->SR = ~TIM_FLAG_CC4; (TIM4)->DIER |= TIM_DIER_CC4IE +#define IGN5_TIMER_ENABLE() (TIM4)->CR1 |= TIM_CR1_CEN; (TIM4)->SR = ~TIM_FLAG_CC1; (TIM4)->DIER |= TIM_DIER_CC1IE +#define IGN6_TIMER_ENABLE() (TIM4)->CR1 |= TIM_CR1_CEN; (TIM4)->SR = ~TIM_FLAG_CC2; (TIM4)->DIER |= TIM_DIER_CC2IE +#define IGN7_TIMER_ENABLE() (TIM4)->CR1 |= TIM_CR1_CEN; (TIM4)->SR = ~TIM_FLAG_CC3; (TIM4)->DIER |= TIM_DIER_CC3IE +#define IGN8_TIMER_ENABLE() (TIM4)->CR1 |= TIM_CR1_CEN; (TIM4)->SR = ~TIM_FLAG_CC4; (TIM4)->DIER |= TIM_DIER_CC4IE #define IGN5_TIMER_DISABLE() (TIM4)->DIER &= ~TIM_DIER_CC1IE #define IGN6_TIMER_DISABLE() (TIM4)->DIER &= ~TIM_DIER_CC2IE @@ -243,13 +243,13 @@ extern "C" char* sbrk(int incr); *********************************************************************************************************** * Auxiliaries */ -#define ENABLE_BOOST_TIMER() (TIM1)->SR = ~TIM_FLAG_CC2; (TIM1)->DIER |= TIM_DIER_CC2IE +#define ENABLE_BOOST_TIMER() (TIM1)->SR = ~TIM_FLAG_CC2; (TIM1)->DIER |= TIM_DIER_CC2IE; (TIM1)->CR1 |= TIM_CR1_CEN; #define DISABLE_BOOST_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC2IE -#define ENABLE_VVT_TIMER() (TIM1)->SR = ~TIM_FLAG_CC3; (TIM1)->DIER |= TIM_DIER_CC3IE +#define ENABLE_VVT_TIMER() (TIM1)->SR = ~TIM_FLAG_CC3; (TIM1)->DIER |= TIM_DIER_CC3IE; (TIM1)->CR1 |= TIM_CR1_CEN; #define DISABLE_VVT_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC3IE -#define ENABLE_FAN_TIMER() (TIM1)->SR = ~TIM_FLAG_CC1; (TIM1)->DIER |= TIM_DIER_CC1IE +#define ENABLE_FAN_TIMER() (TIM1)->SR = ~TIM_FLAG_CC1; (TIM1)->DIER |= TIM_DIER_CC1IE; (TIM1)->CR1 |= TIM_CR1_CEN; #define DISABLE_FAN_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC1IE #define BOOST_TIMER_COMPARE (TIM1)->CCR2 diff --git a/speeduino/board_stm32_official.ino b/speeduino/board_stm32_official.ino index a336ef03..a7b34e7b 100644 --- a/speeduino/board_stm32_official.ino +++ b/speeduino/board_stm32_official.ino @@ -278,34 +278,7 @@ STM32RTC& rtc = STM32RTC::getInstance(); Timer4.attachInterrupt(4, ignitionSchedule8Interrupt); #endif - Timer1.resume(); - DISABLE_BOOST_TIMER(); //Make sure it is disabled. It's is enabled by default on the library - DISABLE_VVT_TIMER(); //Make sure it is disabled. It's is enabled by default on the library - IDLE_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - Timer2.resume(); - IGN1_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - IGN2_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - IGN3_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - IGN4_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - Timer3.resume(); - FUEL1_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - FUEL2_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - FUEL3_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - FUEL4_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - #if (IGN_CHANNELS >= 5) - Timer4.resume(); - IGN5_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - IGN6_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - IGN7_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - IGN8_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - #endif - #if (INJ_CHANNELS >= 5) - Timer5.resume(); - FUEL5_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - FUEL6_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - FUEL7_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - FUEL8_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library - #endif + } uint16_t freeRam() diff --git a/speeduino/scheduler.ino b/speeduino/scheduler.ino index 0265f19a..8dfebcdf 100644 --- a/speeduino/scheduler.ino +++ b/speeduino/scheduler.ino @@ -116,10 +116,23 @@ void initialiseSchedulers() IGN2_TIMER_ENABLE(); IGN3_TIMER_ENABLE(); IGN4_TIMER_ENABLE(); +#if (IGN_CHANNELS >= 5) IGN5_TIMER_ENABLE(); IGN6_TIMER_ENABLE(); IGN7_TIMER_ENABLE(); IGN8_TIMER_ENABLE(); +#endif + + FUEL1_TIMER_ENABLE(); + FUEL2_TIMER_ENABLE(); + FUEL3_TIMER_ENABLE(); + FUEL4_TIMER_ENABLE(); +#if (INJ_CHANNELS >= 5) + FUEL5_TIMER_ENABLE(); + FUEL6_TIMER_ENABLE(); + FUEL7_TIMER_ENABLE(); + FUEL8_TIMER_ENABLE(); +#endif ignitionSchedule1.schedulesSet = 0; ignitionSchedule2.schedulesSet = 0; diff --git a/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp b/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp index 0fb3e975..e0f52567 100644 --- a/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp +++ b/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp @@ -394,6 +394,14 @@ int8_t InternalSTM32F4_EEPROM_Class::writeFlashBytes(uint32_t flashAddress, byte uint16_t data = 0; uint32_t offset = 0; uint32_t countaddress = translatedAddress; + + //Clear any flash errors before try writing to flash to prevent write failures. + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR); + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR); + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGPERR) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGPERR); + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR); + if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR ) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR); + HAL_FLASH_Unlock(); while (countaddress < translatedAddress + length) { memcpy(&data, buf + offset, sizeof(uint16_t)); From 54230fd52283dcc23551f7b02d76b9ea5c8be134 Mon Sep 17 00:00:00 2001 From: Daniel Tobias Date: Mon, 27 Jun 2022 10:39:14 +1000 Subject: [PATCH 12/46] Correct typos found by codespell (#880) --- speeduino/auxiliaries.ino | 4 ++-- speeduino/board_stm32_official.h | 2 +- speeduino/canBroadcast.ino | 4 ++-- speeduino/cancomms.ino | 4 ++-- speeduino/comms.cpp | 2 +- speeduino/comms.h | 2 +- speeduino/corrections.ino | 2 +- speeduino/crankMaths.ino | 10 +++++----- speeduino/decoders.ino | 2 +- speeduino/globals.h | 10 +++++----- speeduino/idle.h | 2 +- speeduino/idle.ino | 2 +- speeduino/init.ino | 2 +- speeduino/int16_byte.h | 7 ++++--- speeduino/scheduler.h | 2 +- speeduino/scheduler.ino | 10 +++++----- speeduino/sensors.ino | 2 +- speeduino/speeduino.ino | 2 +- speeduino/timers.h | 2 +- speeduino/timers.ino | 11 +++++------ speeduino/updates.ino | 2 +- 21 files changed, 43 insertions(+), 43 deletions(-) diff --git a/speeduino/auxiliaries.ino b/speeduino/auxiliaries.ino index a1cbfb13..9553aa77 100644 --- a/speeduino/auxiliaries.ino +++ b/speeduino/auxiliaries.ino @@ -391,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(((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(((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 usually 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 ) @@ -435,7 +435,7 @@ void boostControl() 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 + boost_pwm_target_value = ((unsigned long)(currentStatus.boostDuty) * boost_pwm_max_count) / 10000; //Convert boost duty (Which is a % multiplied 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 diff --git a/speeduino/board_stm32_official.h b/speeduino/board_stm32_official.h index 23bc6fcb..9e2b83d0 100644 --- a/speeduino/board_stm32_official.h +++ b/speeduino/board_stm32_official.h @@ -67,7 +67,7 @@ extern "C" char* sbrk(int incr); #ifndef PB11 //Hack for F4 BlackPills #define PB11 PB10 #endif - //Hack to alow compile on small STM boards + //Hack to allow compilation on small STM boards #ifndef A10 #define A10 PA0 #define A11 PA1 diff --git a/speeduino/canBroadcast.ino b/speeduino/canBroadcast.ino index 2ef6c7ad..04dec41d 100644 --- a/speeduino/canBroadcast.ino +++ b/speeduino/canBroadcast.ino @@ -74,7 +74,7 @@ void DashMessage(uint16_t DashMessageID) outMsg.buf[0] = 0x00; //Check engine light (binary 10), Cruise light (binary 1000), EML (binary 10000). outMsg.buf[1] = 0x00; //LSB Fuel consumption outMsg.buf[2] = 0x00; //MSB Fuel Consumption - if (currentStatus.coolant > 159) { outMsg.buf[3] = 0x08; } //Turn on overheat light if coolant temp hits 120 degrees celcius. + if (currentStatus.coolant > 159) { outMsg.buf[3] = 0x08; } //Turn on overheat light if coolant temp hits 120 degrees celsius. else { outMsg.buf[3] = 0x00; } //Overheat light off at normal engine temps. outMsg.buf[4] = 0x7E; //this is oil temp break; @@ -113,4 +113,4 @@ void DashMessage(uint16_t DashMessageID) break; } } -#endif \ No newline at end of file +#endif diff --git a/speeduino/cancomms.ino b/speeduino/cancomms.ino index ebe83c6c..f5f9806c 100644 --- a/speeduino/cancomms.ino +++ b/speeduino/cancomms.ino @@ -73,7 +73,7 @@ void secondserial_Command() Glow = Gdata[(configPage9.caninput_source_start_byte[destcaninchannel]&7)]; if ((BIT_CHECK(configPage9.caninput_source_num_bytes,destcaninchannel) > 0)) //if true then num bytes is 2 { - if ((configPage9.caninput_source_start_byte[destcaninchannel]&7) < 8) //you cant have a 2 byte value starting at byte 7(8 on the list) + if ((configPage9.caninput_source_start_byte[destcaninchannel]&7) < 8) //you can't have a 2 byte value starting at byte 7(8 on the list) { Ghigh = Gdata[((configPage9.caninput_source_start_byte[destcaninchannel]&7)+1)]; } @@ -423,7 +423,7 @@ void sendCancommand(uint8_t cmdtype, uint16_t canaddress, uint8_t candata1, uint break; case 2: // requests via serial3 - CANSerial.print("R"); //send "R" to request data from the sourcecanAddress whos value is sent next + CANSerial.print("R"); //send "R" to request data from the sourcecanAddress whose value is sent next CANSerial.write(candata1); //the currentStatus.current_caninchannel CANSerial.write(lowByte(sourcecanAddress) ); //send lsb first CANSerial.write(highByte(sourcecanAddress) ); diff --git a/speeduino/comms.cpp b/speeduino/comms.cpp index 9c25442e..d5b4b17c 100644 --- a/speeduino/comms.cpp +++ b/speeduino/comms.cpp @@ -527,7 +527,7 @@ void processSerialCommand() serialPayload[13] = 0; serialPayload[14] = 0; - //Unkown purpose for last 2 bytes + //Unknown purpose for last 2 bytes serialPayload[15] = 0; serialPayload[16] = 0; diff --git a/speeduino/comms.h b/speeduino/comms.h index 9e84a2c4..ea086f9a 100644 --- a/speeduino/comms.h +++ b/speeduino/comms.h @@ -73,7 +73,7 @@ extern bool serialWriteInProgress; extern bool serialReceivePending; /**< Whether or not a serial request has only been partially received. This occurs when a the length has been received in the serial buffer, but not all of the payload or CRC has yet been received. */ -void parseSerial();//This is the heart of the Command Line Interpeter. All that needed to be done was to make it human readable. +void parseSerial();//This is the heart of the Command Line Interpreter. All that needed to be done was to make it human readable. void processSerialCommand(); void sendSerialReturnCode(byte returnCode); void sendSerialPayload(void*, uint16_t payloadLength); diff --git a/speeduino/corrections.ino b/speeduino/corrections.ino index 8302d80e..38d41e16 100644 --- a/speeduino/corrections.ino +++ b/speeduino/corrections.ino @@ -293,7 +293,7 @@ uint16_t correctionCranking() return crankingValue; } -/** Afer Start Enrichment calculation. +/** After Start Enrichment calculation. * This is a short period (Usually <20 seconds) immediately after the engine first fires (But not when cranking) * where an additional amount of fuel is added (Over and above the WUE amount). * diff --git a/speeduino/crankMaths.ino b/speeduino/crankMaths.ino index 687dc37c..c09c1261 100644 --- a/speeduino/crankMaths.ino +++ b/speeduino/crankMaths.ino @@ -21,7 +21,7 @@ int rpmDelta; * * Currently 4 methods are planned and/or available: * 1) Last interval based on a full revolution -* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependant) +* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependent) * 3) Closed loop error correction (Alpha-beta filter) * 4) 2nd derivative prediction (Speed + acceleration) */ @@ -55,7 +55,7 @@ unsigned long angleToTime(int16_t angle, byte method) * Convert a time (uS) into an angle at current speed * Currently 4 methods are planned and/or available: * 1) Last interval based on a full revolution -* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependant) +* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependent) * 3) Closed loop error correction (Alpha-beta filter) * 4) 2nd derivative prediction (Speed + acceleration) */ @@ -134,7 +134,7 @@ void doCrankSpeedCalcs() rpmDelta = (toothDeltaV << 10) / (6 * toothDeltaT); } - timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpmDelta).quot; //This give accuracy down to 0.1 of a degree and can provide noticably better timing results on low res triggers + timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpmDelta).quot; //This gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low resolution triggers timePerDegree = timePerDegreex16 / 16; } else @@ -155,10 +155,10 @@ void doCrankSpeedCalcs() { //long timeThisRevolution = (micros_safe() - toothOneTime); interrupts(); - //Take into account any likely accleration that has occurred since the last full revolution completed: + //Take into account any likely acceleration that has occurred since the last full revolution completed: //long rpm_adjust = (timeThisRevolution * (long)currentStatus.rpmDOT) / 1000000; long rpm_adjust = 0; - timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpm_adjust).quot; //The use of a x16 value gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low res triggers + timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpm_adjust).quot; //The use of a x16 value gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low resolution triggers timePerDegree = timePerDegreex16 / 16; } } diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index 7c39e15b..c0d4bb6d 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -3227,7 +3227,7 @@ void triggerSetEndTeeth_Daihatsu() /** Harley Davidson (V2) with 2 unevenly Spaced Teeth. Within the decoder code, the sync tooth is referred to as tooth #1. Derived from GMX7 and adapted for Harley. -Only rising Edge is used for simplicity.The second input is ignored, as it does not help to desolve cam position. +Only rising Edge is used for simplicity.The second input is ignored, as it does not help to resolve cam position. * @defgroup dec_harley Harley Davidson * @{ */ diff --git a/speeduino/globals.h b/speeduino/globals.h index 81d7f95a..7460c6c6 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -808,7 +808,7 @@ struct config2 { //config2 in ini byte fuelAlgorithm : 3;///< Fuel algorithm - 0=Manifold pressure/MAP (LOAD_SOURCE_MAP, default, proven), 1=Throttle/TPS (LOAD_SOURCE_TPS), 2=IMAP/EMAP (LOAD_SOURCE_IMAPEMAP) - byte fixAngEnable : 1; ///< Whether fixed/locked timing is enabled (0=diable, 1=enable, See @ref configPage4.FixAng) + byte fixAngEnable : 1; ///< Whether fixed/locked timing is enabled (0=disable, 1=enable, See @ref configPage4.FixAng) byte nInjectors : 4; ///< Number of injectors @@ -818,8 +818,8 @@ struct config2 { byte legacyMAP : 1; ///< Legacy MAP reading behaviour byte baroCorr : 1; // Unused ? byte injLayout : 2; /**< Injector Layout - 0=INJ_PAIRED (number outputs == number cyls/2, timed over 1 crank rev), 1=INJ_SEMISEQUENTIAL (like paired, but number outputs == number cyls, only for 4 cyl), - 2=INJ_BANKED (2 outputs are used), 3=INJ_SEQUENTIAL (number ouputs == number cyls, timed over full cycle, 2 crank revs) */ - byte perToothIgn : 1; ///< Experimental / New ign. mode ... (?) (See decoders.ino) + 2=INJ_BANKED (2 outputs are used), 3=INJ_SEQUENTIAL (number outputs == number cyls, timed over full cycle, 2 crank revs) */ + byte perToothIgn : 1; ///< Experimental / New ignition mode ... (?) (See decoders.ino) byte dfcoEnabled : 1; ///< Whether or not DFCO (deceleration fuel cut-off) is turned on byte aeColdTaperMax; ///< AE cold modifier, taper end temp (no modifier applied, was primePulse in early versions) @@ -1397,7 +1397,7 @@ struct config13 { uint8_t outputDelay[8]; ///< Output write delay for each programmable I/O (Unit: 0.1S) uint8_t firstDataIn[8]; ///< Set of first I/O vars to compare uint8_t secondDataIn[8];///< Set of second I/O vars to compare - uint8_t outputTimeLimit[8]; ///< Output delay for each programmable I/O, kindOfLimiting bit dependant(Unit: 0.1S) + uint8_t outputTimeLimit[8]; ///< Output delay for each programmable I/O, kindOfLimiting bit dependent(Unit: 0.1S) uint8_t unused_13[8]; // Unused int16_t firstTarget[8]; ///< first target value to compare with numeric comp int16_t secondTarget[8];///< second target value to compare with bitwise op @@ -1528,7 +1528,7 @@ extern byte pinFuelPressure; extern byte pinOilPressure; extern byte pinWMIEmpty; // Water tank empty sensor extern byte pinWMIIndicator; // No water indicator bulb -extern byte pinWMIEnabled; // ON-OFF ouput to relay/pump/solenoid +extern byte pinWMIEnabled; // ON-OFF output to relay/pump/solenoid extern byte pinMC33810_1_CS; extern byte pinMC33810_2_CS; #ifdef USE_SPI_EEPROM diff --git a/speeduino/idle.h b/speeduino/idle.h index a05dc363..5e1eb8e9 100644 --- a/speeduino/idle.h +++ b/speeduino/idle.h @@ -30,7 +30,7 @@ struct StepperIdle int curIdleStep; //Tracks the current location of the stepper int targetIdleStep; //What the targeted step is volatile StepperStatus stepperStatus; - volatile unsigned long stepStartTime; //The time the curren + volatile unsigned long stepStartTime; byte lessAirDirection; byte moreAirDirection; }; diff --git a/speeduino/idle.ino b/speeduino/idle.ino index accb29aa..066970a3 100644 --- a/speeduino/idle.ino +++ b/speeduino/idle.ino @@ -544,7 +544,7 @@ void idleControl() idle_cl_target_rpm = (uint16_t)currentStatus.CLIdleTarget * 10; //Multiply the byte target value back out by 10 if( BIT_CHECK(LOOP_TIMER, BIT_TIMER_1HZ) ) { idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD); } //Re-read the PID settings once per second - if((currentStatus.RPM - idle_cl_target_rpm > configPage2.iacRPMlimitHysteresis*10) || (currentStatus.TPS > configPage2.iacTPSlimit)){ //reset integral to zero when TPS is bigger than set value in TS (opening throttle so not idle anymore). OR when RPM higher than Idle Target + RPM Histeresis (comming back from high rpm with throttle closed) + if((currentStatus.RPM - idle_cl_target_rpm > configPage2.iacRPMlimitHysteresis*10) || (currentStatus.TPS > configPage2.iacTPSlimit)){ //reset integral to zero when TPS is bigger than set value in TS (opening throttle so not idle anymore). OR when RPM higher than Idle Target + RPM Histeresis (coming back from high rpm with throttle closed) idlePID.ResetIntegeral(); } PID_computed = idlePID.Compute(true, FeedForwardTerm); diff --git a/speeduino/init.ino b/speeduino/init.ino index 1e769d94..26e38301 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -1482,7 +1482,7 @@ void setPinMapping(byte boardID) //https://github.com/stm32duino/Arduino_Core_STM32/blob/master/variants/Generic_F411Cx/variant.h#L28 //pins PA12, PA11 are used for USB or CAN couldn't be used for GPIO //pins PB12, PB13, PB14 and PB15 are used to SPI FLASH - //PB2 can't be used as input becuase is BOOT pin + //PB2 can't be used as input because it's the BOOT pin pinInjector1 = PB7; //Output pin injector 1 is on pinInjector2 = PB6; //Output pin injector 2 is on pinInjector3 = PB5; //Output pin injector 3 is on diff --git a/speeduino/int16_byte.h b/speeduino/int16_byte.h index c7c093b0..9680a653 100644 --- a/speeduino/int16_byte.h +++ b/speeduino/int16_byte.h @@ -12,7 +12,7 @@ typedef uint8_t byte; /** @brief Represents a 16-bit value as a byte. Useful for I/O. - * + * * Often we need to deal internally with values that fit in 16-bits but do * not require much accuracy. E.g. table axes in RPM. For these values we can * save storage space (EEPROM) by scaling to/from 8-bits using a fixed divisor. @@ -23,11 +23,12 @@ public: /** * @brief Construct + * * @param factor The factor to multiply when converting \c byte to \c int16_t * @param divider The factor to divide by when converting \c int16_t to \c byte * * \c divider could be computed from \c factor, but including it as a parameter - * allows callers to create \c factor instances at compile tiem. + * allows callers to create \c factor instances at compile time. */ constexpr int16_byte(uint8_t factor, const libdivide::libdivide_s16_t ÷r) : _factor(factor), _divider(divider) @@ -45,4 +46,4 @@ private: libdivide::libdivide_s16_t _divider; }; -/** @} */ \ No newline at end of file +/** @} */ diff --git a/speeduino/scheduler.h b/speeduino/scheduler.h index 4c24da60..b99def18 100644 --- a/speeduino/scheduler.h +++ b/speeduino/scheduler.h @@ -108,7 +108,7 @@ void setIgnitionSchedule8(void (*startCallback)(), unsigned long timeout, unsign inline void refreshIgnitionSchedule1(unsigned long timeToEnd) __attribute__((always_inline)); -//The ARM cores use seprate functions for their ISRs +//The ARM cores use separate functions for their ISRs #if defined(ARDUINO_ARCH_STM32) || defined(CORE_TEENSY) static inline void fuelSchedule1Interrupt(); static inline void fuelSchedule2Interrupt(); diff --git a/speeduino/scheduler.ino b/speeduino/scheduler.ino index 8dfebcdf..ac1d22b2 100644 --- a/speeduino/scheduler.ino +++ b/speeduino/scheduler.ino @@ -1250,7 +1250,7 @@ static inline void ignitionSchedule4Interrupt() //Most ARM chips can simply call ignitionSchedule4.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule4.startTime = micros(); if(ignitionSchedule4.endScheduleSetByDecoder == true) { SET_COMPARE(IGN4_COMPARE, ignitionSchedule4.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN4_COMPARE, IGN4_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule4.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha + else { SET_COMPARE(IGN4_COMPARE, IGN4_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule4.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs } else if (ignitionSchedule4.Status == RUNNING) { @@ -1291,7 +1291,7 @@ static inline void ignitionSchedule5Interrupt() //Most ARM chips can simply call ignitionSchedule5.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule5.startTime = micros(); if(ignitionSchedule5.endScheduleSetByDecoder == true) { SET_COMPARE(IGN5_COMPARE, ignitionSchedule5.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN5_COMPARE, IGN5_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule5.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha + else { SET_COMPARE(IGN5_COMPARE, IGN5_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule5.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs } else if (ignitionSchedule5.Status == RUNNING) { @@ -1332,7 +1332,7 @@ static inline void ignitionSchedule6Interrupt() //Most ARM chips can simply call ignitionSchedule6.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule6.startTime = micros(); if(ignitionSchedule6.endScheduleSetByDecoder == true) { SET_COMPARE(IGN6_COMPARE, ignitionSchedule6.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN6_COMPARE, IGN6_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule6.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha + else { SET_COMPARE(IGN6_COMPARE, IGN6_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule6.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs } else if (ignitionSchedule6.Status == RUNNING) { @@ -1373,7 +1373,7 @@ static inline void ignitionSchedule7Interrupt() //Most ARM chips can simply call ignitionSchedule7.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule7.startTime = micros(); if(ignitionSchedule7.endScheduleSetByDecoder == true) { SET_COMPARE(IGN7_COMPARE, ignitionSchedule7.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN7_COMPARE, IGN7_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule7.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha + else { SET_COMPARE(IGN7_COMPARE, IGN7_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule7.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs } else if (ignitionSchedule7.Status == RUNNING) { @@ -1414,7 +1414,7 @@ static inline void ignitionSchedule8Interrupt() //Most ARM chips can simply call ignitionSchedule8.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule8.startTime = micros(); if(ignitionSchedule8.endScheduleSetByDecoder == true) { SET_COMPARE(IGN8_COMPARE, ignitionSchedule8.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN8_COMPARE, IGN8_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule8.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha + else { SET_COMPARE(IGN8_COMPARE, IGN8_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule8.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs } else if (ignitionSchedule8.Status == RUNNING) { diff --git a/speeduino/sensors.ino b/speeduino/sensors.ino index 72a612e0..6bd9ca1b 100644 --- a/speeduino/sensors.ino +++ b/speeduino/sensors.ino @@ -96,7 +96,7 @@ void initialiseADC() else if ((((configPage9.enable_secondarySerial == 1) || ((configPage9.enable_intcan == 1) && (configPage9.intcan_available == 1))) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&12) == 12) || (((configPage9.enable_secondarySerial == 0) && ( (configPage9.enable_intcan == 1) && (configPage9.intcan_available == 0) )) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 3) || (((configPage9.enable_secondarySerial == 0) && (configPage9.enable_intcan == 0)) && ((configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 3))) - { //if current input channel is enabled as digital local pin check caninput_selxb(bits 2:3) wih &12 and caninput_selxa(bits 0:1) with &3 + { //if current input channel is enabled as digital local pin check caninput_selxb(bits 2:3) with &12 and caninput_selxa(bits 0:1) with &3 byte pinNumber = (configPage9.Auxinpinb[currentStatus.current_caninchannel]&63) + 1; if( pinIsUsed(pinNumber) ) { diff --git a/speeduino/speeduino.ino b/speeduino/speeduino.ino index 997e3125..4bee59cb 100644 --- a/speeduino/speeduino.ino +++ b/speeduino/speeduino.ino @@ -101,7 +101,7 @@ inline uint16_t applyFuelTrimToPW(trimTable3d *pTrimTable, int16_t fuelLoad, int /** Speeduino main loop. * - * Main loop chores (roughly in order they are preformed): + * Main loop chores (roughly in the order that they are performed): * - Check if serial comms or tooth logging are in progress (send or receive, prioritise communication) * - Record loop timing vars * - Check tooth time, update @ref statuses (currentStatus) variables diff --git a/speeduino/timers.h b/speeduino/timers.h index 1cb87a71..c677d8f7 100644 --- a/speeduino/timers.h +++ b/speeduino/timers.h @@ -24,7 +24,7 @@ Hence we will preload the timer with 131 cycles to leave 125 until overflow (1ms volatile bool tachoAlt = false; #define TACHO_PULSE_HIGH() *tach_pin_port |= (tach_pin_mask) #define TACHO_PULSE_LOW() *tach_pin_port &= ~(tach_pin_mask) -enum TachoOutputStatus {DEACTIVE, READY, ACTIVE}; //The 3 statuses that the tacho output pulse can have +enum TachoOutputStatus {INACTIVE, READY, ACTIVE}; //The 3 statuses that the tacho output pulse can have volatile uint8_t tachoEndTime; //The time (in ms) that the tacho pulse needs to end at volatile TachoOutputStatus tachoOutputFlag; diff --git a/speeduino/timers.ino b/speeduino/timers.ino index 9f1f36ac..ed9c33e7 100644 --- a/speeduino/timers.ino +++ b/speeduino/timers.ino @@ -32,7 +32,7 @@ void initialiseTimers() loop100ms = 0; loop250ms = 0; loopSec = 0; - tachoOutputFlag = DEACTIVE; + tachoOutputFlag = INACTIVE; } @@ -84,7 +84,7 @@ void oneMSInterval() //Most ARM chips can simply call a function else { //Don't run on this pulse (Half speed tacho) - tachoOutputFlag = DEACTIVE; + tachoOutputFlag = INACTIVE; } tachoAlt = !tachoAlt; //Flip the alternating value in case half speed tacho is in use. } @@ -94,7 +94,7 @@ void oneMSInterval() //Most ARM chips can simply call a function if((uint8_t)ms_counter == tachoEndTime) { TACHO_PULSE_HIGH(); - tachoOutputFlag = DEACTIVE; + tachoOutputFlag = INACTIVE; } } // Tacho sweep @@ -161,9 +161,9 @@ void oneMSInterval() //Most ARM chips can simply call a function //************************************************************************************************************************************************** //This updates the runSecs variable - //If the engine is running or cranking, we need ot update the run time counter. + //If the engine is running or cranking, we need to update the run time counter. if (BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN)) - { //NOTE - There is a potential for a ~1sec gap between engine crank starting and ths runSec number being incremented. This may delay ASE! + { //NOTE - There is a potential for a ~1sec gap between engine crank starting and the runSec number being incremented. This may delay ASE! if (currentStatus.runSecs <= 254) //Ensure we cap out at 255 and don't overflow. (which would reset ASE and cause problems with the closed loop fuelling (Which has to wait for the O2 to warmup)) { currentStatus.runSecs++; } //Increment our run counter by 1 second. } @@ -271,4 +271,3 @@ void oneMSInterval() //Most ARM chips can simply call a function TCNT2 = 131; //Preload timer2 with 100 cycles, leaving 156 till overflow. #endif } - diff --git a/speeduino/updates.ino b/speeduino/updates.ino index 79a04821..b30a464d 100644 --- a/speeduino/updates.ino +++ b/speeduino/updates.ino @@ -220,7 +220,7 @@ void doUpdates() configPage4.cltAdvValues[5] = 0; - //March 19 added a tacho pulse duration that could default to stupidly high values. Check if this is the case and fix it if found. 6ms is tha maximum allowed value + //March 19 added a tacho pulse duration that could default to stupidly high values. Check if this is the case and fix it if found. 6ms is the maximum allowed value if(configPage2.tachoDuration > 6) { configPage2.tachoDuration = 3; } //MAP based AE was introduced, force the AE mode to be TPS for all existing tunes From 124d17812eb81f6b8bb016e685718aef2db9f248 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Mon, 27 Jun 2022 11:48:12 +1000 Subject: [PATCH 13/46] Fix broken build on Teensy from #880 --- speeduino/timers.h | 2 +- speeduino/timers.ino | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/speeduino/timers.h b/speeduino/timers.h index c677d8f7..380af06e 100644 --- a/speeduino/timers.h +++ b/speeduino/timers.h @@ -24,7 +24,7 @@ Hence we will preload the timer with 131 cycles to leave 125 until overflow (1ms volatile bool tachoAlt = false; #define TACHO_PULSE_HIGH() *tach_pin_port |= (tach_pin_mask) #define TACHO_PULSE_LOW() *tach_pin_port &= ~(tach_pin_mask) -enum TachoOutputStatus {INACTIVE, READY, ACTIVE}; //The 3 statuses that the tacho output pulse can have +enum TachoOutputStatus {TACHO_INACTIVE, READY, ACTIVE}; //The 3 statuses that the tacho output pulse can have. NOTE: Cannot just use 'INACTIVE' as this is already defined within the Teensy Libs volatile uint8_t tachoEndTime; //The time (in ms) that the tacho pulse needs to end at volatile TachoOutputStatus tachoOutputFlag; diff --git a/speeduino/timers.ino b/speeduino/timers.ino index ed9c33e7..672e1d4b 100644 --- a/speeduino/timers.ino +++ b/speeduino/timers.ino @@ -32,7 +32,7 @@ void initialiseTimers() loop100ms = 0; loop250ms = 0; loopSec = 0; - tachoOutputFlag = INACTIVE; + tachoOutputFlag = TACHO_INACTIVE; } @@ -84,7 +84,7 @@ void oneMSInterval() //Most ARM chips can simply call a function else { //Don't run on this pulse (Half speed tacho) - tachoOutputFlag = INACTIVE; + tachoOutputFlag = TACHO_INACTIVE; } tachoAlt = !tachoAlt; //Flip the alternating value in case half speed tacho is in use. } @@ -94,7 +94,7 @@ void oneMSInterval() //Most ARM chips can simply call a function if((uint8_t)ms_counter == tachoEndTime) { TACHO_PULSE_HIGH(); - tachoOutputFlag = INACTIVE; + tachoOutputFlag = TACHO_INACTIVE; } } // Tacho sweep From 522e4068db5f938193edf77c55bff74e778b03e6 Mon Sep 17 00:00:00 2001 From: tx_haggis <13982343+adbancroft@users.noreply.github.com> Date: Sun, 26 Jun 2022 20:53:33 -0500 Subject: [PATCH 14/46] Narrow scope of EEPROM_MAX_WRITE_BLOCK to writeConfig (#881) * EEPROM_MAX_WRITE_BLOCK can be local to writeConfig() This saves a byte of memory ;-) * Fix MISRA/lint warnings Correctly cast address parameter of eeprom_read_block Statically access table 3d type_key member * Remove force burn code - unused * Replace eepromWritesPending with bit set/check * Refactor: chain write_location instances. Clearer code. --- speeduino/storage.cpp | 182 ++++++++++++++++++++++-------------------- speeduino/storage.h | 2 - 2 files changed, 95 insertions(+), 89 deletions(-) diff --git a/speeduino/storage.cpp b/speeduino/storage.cpp index 2416578a..ca95d1ef 100644 --- a/speeduino/storage.cpp +++ b/speeduino/storage.cpp @@ -14,18 +14,9 @@ A full copy of the license may be found in the projects root directory #include "table3d_axis_io.h" - -//The maximum number of write operations that will be performed in one go. If we try to write to the EEPROM too fast (Each write takes ~3ms) then the rest of the system can hang) -#if defined(CORE_STM32) || defined(CORE_TEENSY) & !defined(USE_SPI_EEPROM) -//#define EEPROM_MAX_WRITE_BLOCK 64 - uint8_t EEPROM_MAX_WRITE_BLOCK = 64; -#else - uint8_t EEPROM_MAX_WRITE_BLOCK = 24; -//#define EEPROM_MAX_WRITE_BLOCK 8 -#endif - #define EEPROM_DATA_VERSION 0 + // Calibration data is stored at the end of the EEPROM (This is in case any further calibration tables are needed as they are large blocks) #define STORAGE_END 0xFFF // Should be E2END? #define EEPROM_CALIBRATION_CLT_VALUES (STORAGE_END-sizeof(cltCalibration_values)) @@ -36,13 +27,12 @@ A full copy of the license may be found in the projects root directory #define EEPROM_CALIBRATION_O2_BINS (EEPROM_CALIBRATION_O2_VALUES-sizeof(o2Calibration_bins)) #define EEPROM_LAST_BARO (EEPROM_CALIBRATION_O2_BINS-1) -static bool eepromWritesPending = false; -static bool forceBurn = false; + uint32_t deferEEPROMWritesUntil = 0; bool isEepromWritePending() { - return eepromWritesPending; + return BIT_CHECK(currentStatus.status4, BIT_STATUS4_BURNPENDING); } /** Write all config pages to EEPROM. @@ -51,21 +41,21 @@ void writeAllConfig() { uint8_t pageCount = getPageCount(); uint8_t page = 1U; - writeConfig(page++); - while (page 0) { canWrite = (counter <= EEPROM_MAX_WRITE_BLOCK); } - else { canWrite = (counter <= (EEPROM_MAX_WRITE_BLOCK * 8)); } //Write to EEPROM more aggressively if the engine is not running + if(currentStatus.RPM > 0) { canWrite = (counter <= write_block_size); } + else { canWrite = (counter <= (write_block_size * 8)); } //Write to EEPROM more aggressively if the engine is not running return canWrite; } @@ -98,7 +95,7 @@ struct write_location { static inline write_location write_range(const byte *pStart, const byte *pEnd, write_location location) { - while ( (location.can_write() || forceBurn) && pStart!=pEnd) + while ( location.can_write() && pStart!=pEnd) { location.update(*pStart); ++pStart; @@ -114,7 +111,7 @@ static inline write_location write(const table_row_iterator &row, write_location static inline write_location write(table_value_iterator it, write_location location) { - while ((location.can_write() || forceBurn) && !it.at_end()) + while (location.can_write() && !it.at_end()) { location = write(*it, location); ++it; @@ -125,7 +122,7 @@ static inline write_location write(table_value_iterator it, write_location locat static inline write_location write(table_axis_iterator it, write_location location) { const int16_byte *pConverter = table3d_axis_io::get_converter(it.domain()); - while ((location.can_write() || forceBurn) && !it.at_end()) + while (location.can_write() && !it.at_end()) { location.update(pConverter->to_byte(*it)); ++location; @@ -154,17 +151,30 @@ and writes them to EEPROM as per the layout defined in storage.h. */ void writeConfig(uint8_t pageNum) { - write_location result = { 0, 0 }; +//The maximum number of write operations that will be performed in one go. +//If we try to write to the EEPROM too fast (Each write takes ~3ms) then +//the rest of the system can hang) +#if defined(CORE_STM32) || defined(CORE_TEENSY) & !defined(USE_SPI_EEPROM) + uint8_t EEPROM_MAX_WRITE_BLOCK = 64; +#else + uint8_t EEPROM_MAX_WRITE_BLOCK = 24; - #ifdef CORE_AVR - //In order to prevent missed pulses during EEPROM writes on AVR, scale the maximum write block size based on the RPM - //This calculation is based on EEPROM writes taking approximately 4ms per byte (Actual value is 3.8ms, so 4ms has some safety margin) - if(currentStatus.RPM > 65) { EEPROM_MAX_WRITE_BLOCK = (15000 / currentStatus.RPM); } //Min RPM of 65 prevents overflow of uint8_t. - else { EEPROM_MAX_WRITE_BLOCK = 24; } +#ifdef CORE_AVR + //In order to prevent missed pulses during EEPROM writes on AVR, scale the + //maximum write block size based on the RPM. + //This calculation is based on EEPROM writes taking approximately 4ms per byte + //(Actual value is 3.8ms, so 4ms has some safety margin) + if(currentStatus.RPM > 65) //Min RPM of 65 prevents overflow of uint8_t + { + EEPROM_MAX_WRITE_BLOCK = (uint8_t)(15000U / currentStatus.RPM); + EEPROM_MAX_WRITE_BLOCK = max(EEPROM_MAX_WRITE_BLOCK, 1); + EEPROM_MAX_WRITE_BLOCK = min(EEPROM_MAX_WRITE_BLOCK, 24); //Any higher than this will cause comms timeouts on AVR + } +#endif - if(EEPROM_MAX_WRITE_BLOCK < 1) { EEPROM_MAX_WRITE_BLOCK = 1; } - if(EEPROM_MAX_WRITE_BLOCK > 24) { EEPROM_MAX_WRITE_BLOCK = 24; } //Any higher than this will cause comms timeouts on AVR - #endif +#endif + + write_location result = { 0, 0, EEPROM_MAX_WRITE_BLOCK }; switch(pageNum) { @@ -173,7 +183,7 @@ void writeConfig(uint8_t pageNum) | Fuel table (See storage.h for data layout) - Page 1 | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&fuelTable, fuelTable.type_key, { EEPROM_CONFIG1_MAP, 0 }); + result = writeTable(&fuelTable, decltype(fuelTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG1_MAP)); break; case veSetPage: @@ -181,7 +191,7 @@ void writeConfig(uint8_t pageNum) | Config page 2 (See storage.h for data layout) | 64 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage2, (byte *)&configPage2+sizeof(configPage2), { EEPROM_CONFIG2_START, 0 }); + result = write_range((byte *)&configPage2, (byte *)&configPage2+sizeof(configPage2), result.changeWriteAddress(EEPROM_CONFIG2_START)); break; case ignMapPage: @@ -189,7 +199,7 @@ void writeConfig(uint8_t pageNum) | Ignition table (See storage.h for data layout) - Page 1 | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&ignitionTable, ignitionTable.type_key, { EEPROM_CONFIG3_MAP, 0 }); + result = writeTable(&ignitionTable, decltype(ignitionTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG3_MAP)); break; case ignSetPage: @@ -197,7 +207,7 @@ void writeConfig(uint8_t pageNum) | Config page 2 (See storage.h for data layout) | 64 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage4, (byte *)&configPage4+sizeof(configPage4), { EEPROM_CONFIG4_START, 0 }); + result = write_range((byte *)&configPage4, (byte *)&configPage4+sizeof(configPage4), result.changeWriteAddress(EEPROM_CONFIG4_START)); break; case afrMapPage: @@ -205,7 +215,7 @@ void writeConfig(uint8_t pageNum) | AFR table (See storage.h for data layout) - Page 5 | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&afrTable, afrTable.type_key, { EEPROM_CONFIG5_MAP, 0 }); + result = writeTable(&afrTable, decltype(afrTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG5_MAP)); break; case afrSetPage: @@ -213,7 +223,7 @@ void writeConfig(uint8_t pageNum) | Config page 3 (See storage.h for data layout) | 64 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage6, (byte *)&configPage6+sizeof(configPage6), { EEPROM_CONFIG6_START, 0 }); + result = write_range((byte *)&configPage6, (byte *)&configPage6+sizeof(configPage6), result.changeWriteAddress(EEPROM_CONFIG6_START)); break; case boostvvtPage: @@ -221,9 +231,9 @@ void writeConfig(uint8_t pageNum) | Boost and vvt tables (See storage.h for data layout) - Page 8 | 8x8 table itself + the 8 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&boostTable, boostTable.type_key, { EEPROM_CONFIG7_MAP1, 0 }); - result = writeTable(&vvtTable, vvtTable.type_key, { EEPROM_CONFIG7_MAP2, result.counter }); - result = writeTable(&stagingTable, stagingTable.type_key, { EEPROM_CONFIG7_MAP3, result.counter }); + result = writeTable(&boostTable, decltype(boostTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG7_MAP1)); + result = writeTable(&vvtTable, decltype(vvtTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG7_MAP2)); + result = writeTable(&stagingTable, decltype(stagingTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG7_MAP3)); break; case seqFuelPage: @@ -231,14 +241,14 @@ void writeConfig(uint8_t pageNum) | Fuel trim tables (See storage.h for data layout) - Page 9 | 6x6 tables itself + the 6 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&trim1Table, trim1Table.type_key, { EEPROM_CONFIG8_MAP1, 0 }); - result = writeTable(&trim2Table, trim2Table.type_key, { EEPROM_CONFIG8_MAP2, result.counter }); - result = writeTable(&trim3Table, trim3Table.type_key, { EEPROM_CONFIG8_MAP3, result.counter }); - result = writeTable(&trim4Table, trim4Table.type_key, { EEPROM_CONFIG8_MAP4, result.counter }); - result = writeTable(&trim5Table, trim5Table.type_key, { EEPROM_CONFIG8_MAP5, result.counter }); - result = writeTable(&trim6Table, trim6Table.type_key, { EEPROM_CONFIG8_MAP6, result.counter }); - result = writeTable(&trim7Table, trim7Table.type_key, { EEPROM_CONFIG8_MAP7, result.counter }); - result = writeTable(&trim8Table, trim8Table.type_key, { EEPROM_CONFIG8_MAP8, result.counter }); + result = writeTable(&trim1Table, decltype(trim1Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP1)); + result = writeTable(&trim2Table, decltype(trim2Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP2)); + result = writeTable(&trim3Table, decltype(trim3Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP3)); + result = writeTable(&trim4Table, decltype(trim4Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP4)); + result = writeTable(&trim5Table, decltype(trim5Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP5)); + result = writeTable(&trim6Table, decltype(trim6Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP6)); + result = writeTable(&trim7Table, decltype(trim7Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP7)); + result = writeTable(&trim8Table, decltype(trim8Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP8)); break; case canbusPage: @@ -246,7 +256,7 @@ void writeConfig(uint8_t pageNum) | Config page 10 (See storage.h for data layout) | 192 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage9, (byte *)&configPage9+sizeof(configPage9), { EEPROM_CONFIG9_START, 0 }); + result = write_range((byte *)&configPage9, (byte *)&configPage9+sizeof(configPage9), result.changeWriteAddress(EEPROM_CONFIG9_START)); break; case warmupPage: @@ -254,7 +264,7 @@ void writeConfig(uint8_t pageNum) | Config page 11 (See storage.h for data layout) | 192 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage10, (byte *)&configPage10+sizeof(configPage10), { EEPROM_CONFIG10_START, 0}); + result = write_range((byte *)&configPage10, (byte *)&configPage10+sizeof(configPage10), result.changeWriteAddress(EEPROM_CONFIG10_START)); break; case fuelMap2Page: @@ -262,7 +272,7 @@ void writeConfig(uint8_t pageNum) | Fuel table 2 (See storage.h for data layout) | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&fuelTable2, fuelTable2.type_key, { EEPROM_CONFIG11_MAP, 0 }); + result = writeTable(&fuelTable2, decltype(fuelTable2)::type_key, result.changeWriteAddress(EEPROM_CONFIG11_MAP)); break; case wmiMapPage: @@ -272,16 +282,16 @@ void writeConfig(uint8_t pageNum) | 8x8 VVT2 table + the 8 values along each of the axis | 4x4 Dwell table itself + the 4 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&wmiTable, wmiTable.type_key, { EEPROM_CONFIG12_MAP, 0 }); - result = writeTable(&vvt2Table, vvt2Table.type_key, { EEPROM_CONFIG12_MAP2, result.counter }); - result = writeTable(&dwellTable, dwellTable.type_key, { EEPROM_CONFIG12_MAP3, result.counter }); + result = writeTable(&wmiTable, decltype(wmiTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG12_MAP)); + result = writeTable(&vvt2Table, decltype(vvt2Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG12_MAP2)); + result = writeTable(&dwellTable, decltype(dwellTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG12_MAP3)); break; case progOutsPage: /*--------------------------------------------------- | Config page 13 (See storage.h for data layout) -----------------------------------------------------*/ - result = write_range((byte *)&configPage13, (byte *)&configPage13+sizeof(configPage13), { EEPROM_CONFIG13_START, 0}); + result = write_range((byte *)&configPage13, (byte *)&configPage13+sizeof(configPage13), result.changeWriteAddress(EEPROM_CONFIG13_START)); break; case ignMap2Page: @@ -289,7 +299,7 @@ void writeConfig(uint8_t pageNum) | Ignition table (See storage.h for data layout) - Page 1 | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&ignitionTable2, ignitionTable2.type_key, { EEPROM_CONFIG14_MAP, 0 }); + result = writeTable(&ignitionTable2, decltype(ignitionTable2)::type_key, result.changeWriteAddress(EEPROM_CONFIG14_MAP)); break; case boostvvtPage2: @@ -297,21 +307,19 @@ void writeConfig(uint8_t pageNum) | 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 }); + result = writeTable(&boostTableLookupDuty, decltype(boostTableLookupDuty)::type_key, result.changeWriteAddress(EEPROM_CONFIG15_MAP)); /*--------------------------------------------------- | Config page 15 (See storage.h for data layout) -----------------------------------------------------*/ - result = write_range((byte *)&configPage15, (byte *)&configPage15+sizeof(configPage15), { EEPROM_CONFIG15_START, 0}); + result = write_range((byte *)&configPage15, (byte *)&configPage15+sizeof(configPage15), result.changeWriteAddress(EEPROM_CONFIG15_START)); break; default: break; } - eepromWritesPending = !result.can_write(); - if(eepromWritesPending == true) { BIT_SET(currentStatus.status4, BIT_STATUS4_BURNPENDING); } - else { BIT_CLEAR(currentStatus.status4, BIT_STATUS4_BURNPENDING); } + BIT_WRITE(currentStatus.status4, BIT_STATUS4_BURNPENDING, !result.can_write()); } /** Reset all configPage* structs (2,4,6,9,10,13) and write them full of null-bytes. @@ -344,7 +352,7 @@ static inline eeprom_address_t load_range(eeprom_address_t address, byte *pFirst #if defined(CORE_AVR) // The generic code in the #else branch works but this provides a 45% speed up on AVR size_t size = pLast-pFirst; - eeprom_read_block(pFirst, (void*)address, size); + eeprom_read_block(pFirst, (const void*)(size_t)address, size); return address+size; #else for (; pFirst != pLast; ++address, (void)++pFirst) @@ -383,7 +391,7 @@ static inline eeprom_address_t load(table_axis_iterator it, eeprom_address_t add } -static inline eeprom_address_t loadTable(void *pTable, table_type_t key, eeprom_address_t address) +static inline eeprom_address_t loadTable(const void *pTable, table_type_t key, eeprom_address_t address) { return load(y_begin(pTable, key).reverse(), load(x_begin(pTable, key), @@ -397,37 +405,37 @@ static inline eeprom_address_t loadTable(void *pTable, table_type_t key, eeprom_ */ void loadConfig() { - loadTable(&fuelTable, fuelTable.type_key, EEPROM_CONFIG1_MAP); + loadTable(&fuelTable, decltype(fuelTable)::type_key, EEPROM_CONFIG1_MAP); load_range(EEPROM_CONFIG2_START, (byte *)&configPage2, (byte *)&configPage2+sizeof(configPage2)); //********************************************************************************************************************************************************************************* //IGNITION CONFIG PAGE (2) - loadTable(&ignitionTable, ignitionTable.type_key, EEPROM_CONFIG3_MAP); + loadTable(&ignitionTable, decltype(ignitionTable)::type_key, EEPROM_CONFIG3_MAP); load_range(EEPROM_CONFIG4_START, (byte *)&configPage4, (byte *)&configPage4+sizeof(configPage4)); //********************************************************************************************************************************************************************************* //AFR TARGET CONFIG PAGE (3) - loadTable(&afrTable, afrTable.type_key, EEPROM_CONFIG5_MAP); + loadTable(&afrTable, decltype(afrTable)::type_key, EEPROM_CONFIG5_MAP); load_range(EEPROM_CONFIG6_START, (byte *)&configPage6, (byte *)&configPage6+sizeof(configPage6)); //********************************************************************************************************************************************************************************* // Boost and vvt tables load - loadTable(&boostTable, boostTable.type_key, EEPROM_CONFIG7_MAP1); - loadTable(&vvtTable, vvtTable.type_key, EEPROM_CONFIG7_MAP2); - loadTable(&stagingTable, stagingTable.type_key, EEPROM_CONFIG7_MAP3); + loadTable(&boostTable, decltype(boostTable)::type_key, EEPROM_CONFIG7_MAP1); + loadTable(&vvtTable, decltype(vvtTable)::type_key, EEPROM_CONFIG7_MAP2); + loadTable(&stagingTable, decltype(stagingTable)::type_key, EEPROM_CONFIG7_MAP3); //********************************************************************************************************************************************************************************* // Fuel trim tables load - loadTable(&trim1Table, trim1Table.type_key, EEPROM_CONFIG8_MAP1); - loadTable(&trim2Table, trim2Table.type_key, EEPROM_CONFIG8_MAP2); - loadTable(&trim3Table, trim3Table.type_key, EEPROM_CONFIG8_MAP3); - loadTable(&trim4Table, trim4Table.type_key, EEPROM_CONFIG8_MAP4); - loadTable(&trim5Table, trim5Table.type_key, EEPROM_CONFIG8_MAP5); - loadTable(&trim6Table, trim6Table.type_key, EEPROM_CONFIG8_MAP6); - loadTable(&trim7Table, trim7Table.type_key, EEPROM_CONFIG8_MAP7); - loadTable(&trim8Table, trim8Table.type_key, EEPROM_CONFIG8_MAP8); + loadTable(&trim1Table, decltype(trim1Table)::type_key, EEPROM_CONFIG8_MAP1); + loadTable(&trim2Table, decltype(trim2Table)::type_key, EEPROM_CONFIG8_MAP2); + loadTable(&trim3Table, decltype(trim3Table)::type_key, EEPROM_CONFIG8_MAP3); + loadTable(&trim4Table, decltype(trim4Table)::type_key, EEPROM_CONFIG8_MAP4); + loadTable(&trim5Table, decltype(trim5Table)::type_key, EEPROM_CONFIG8_MAP5); + loadTable(&trim6Table, decltype(trim6Table)::type_key, EEPROM_CONFIG8_MAP6); + loadTable(&trim7Table, decltype(trim7Table)::type_key, EEPROM_CONFIG8_MAP7); + loadTable(&trim8Table, decltype(trim8Table)::type_key, EEPROM_CONFIG8_MAP8); //********************************************************************************************************************************************************************************* //canbus control page load @@ -440,13 +448,13 @@ void loadConfig() //********************************************************************************************************************************************************************************* //Fuel table 2 (See storage.h for data layout) - loadTable(&fuelTable2, fuelTable2.type_key, EEPROM_CONFIG11_MAP); + loadTable(&fuelTable2, decltype(fuelTable2)::type_key, EEPROM_CONFIG11_MAP); //********************************************************************************************************************************************************************************* // WMI, VVT2 and Dwell table load - loadTable(&wmiTable, wmiTable.type_key, EEPROM_CONFIG12_MAP); - loadTable(&vvt2Table, vvt2Table.type_key, EEPROM_CONFIG12_MAP2); - loadTable(&dwellTable, dwellTable.type_key, EEPROM_CONFIG12_MAP3); + loadTable(&wmiTable, decltype(wmiTable)::type_key, EEPROM_CONFIG12_MAP); + loadTable(&vvt2Table, decltype(vvt2Table)::type_key, EEPROM_CONFIG12_MAP2); + loadTable(&dwellTable, decltype(dwellTable)::type_key, EEPROM_CONFIG12_MAP3); //********************************************************************************************************************************************************************************* //CONFIG PAGE (13) @@ -455,11 +463,11 @@ void loadConfig() //********************************************************************************************************************************************************************************* //SECOND IGNITION CONFIG PAGE (14) - loadTable(&ignitionTable2, ignitionTable2.type_key, EEPROM_CONFIG14_MAP); + loadTable(&ignitionTable2, decltype(ignitionTable2)::type_key, EEPROM_CONFIG14_MAP); //********************************************************************************************************************************************************************************* //CONFIG PAGE (15) + boost duty lookup table (LUT) - loadTable(&boostTableLookupDuty, boostTableLookupDuty.type_key, EEPROM_CONFIG15_MAP); + loadTable(&boostTableLookupDuty, decltype(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 7603d659..5c7c558e 100644 --- a/speeduino/storage.h +++ b/speeduino/storage.h @@ -125,8 +125,6 @@ void loadCalibration(); void writeCalibration(); void writeCalibrationPage(uint8_t pageNum); void resetConfigPages(); -void enableForceBurn(); -void disableForceBurn(); //These are utility functions that prevent other files from having to use EEPROM.h directly byte readLastBaro(); From 1650d845aa563dc583f4cb07fecfd39f5d033ec6 Mon Sep 17 00:00:00 2001 From: Pasi Kemppainen <48950874+pazi88@users.noreply.github.com> Date: Mon, 27 Jun 2022 04:54:47 +0300 Subject: [PATCH 15/46] Fix hanging on boot (#858) --- speeduino/board_stm32_official.ino | 5 ++++- speeduino/rtc_common.ino | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/speeduino/board_stm32_official.ino b/speeduino/board_stm32_official.ino index a7b34e7b..565c0a3c 100644 --- a/speeduino/board_stm32_official.ino +++ b/speeduino/board_stm32_official.ino @@ -94,7 +94,10 @@ STM32RTC& rtc = STM32RTC::getInstance(); * Real Time clock for datalogging/time stamping */ #ifdef RTC_ENABLED - rtc.setClockSource(STM32RTC::LSE_CLOCK); //Initialise external clock for RTC. That is the only clock running of VBAT + //Check if RTC time has been set earlier. If yes, RTC will use LSE_CLOCK. If not, default LSI_CLOCK is used, to prevent hanging on boot. + if (rtc.isTimeSet()) { + rtc.setClockSource(STM32RTC::LSE_CLOCK); //Initialise external clock for RTC if clock is set. That is the only clock running of VBAT + } rtc.begin(); // initialise RTC 24H format #endif /* diff --git a/speeduino/rtc_common.ino b/speeduino/rtc_common.ino index b858ea7e..48eebca2 100644 --- a/speeduino/rtc_common.ino +++ b/speeduino/rtc_common.ino @@ -114,6 +114,12 @@ void rtc_setTime(byte second, byte minute, byte hour, byte day, byte month, uint setTime(hour, minute, second, day, month, year); Teensy3Clock.set(now()); #elif defined(CORE_STM32) + //If RTC time has not been set earlier (no battery etc.) we need to stop the RTC and restart it with LSE_CLOCK to have accurate RTC. + if (!rtc.isTimeSet()) { + rtc.end(); + rtc.setClockSource(STM32RTC::LSE_CLOCK); + rtc.begin(); + } rtc.setTime(hour, minute, second); //year in stm32 rtc is a byte. so subtract year 2000 to fit rtc.setDate(day, month, (year-2000)); From 3b03a5b6718c01b6df8c21effb44ad0ce6da913a Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Mon, 27 Jun 2022 12:18:17 +1000 Subject: [PATCH 16/46] Further fixes to the ASE correction --- speeduino/corrections.ino | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/speeduino/corrections.ino b/speeduino/corrections.ino index 38d41e16..627db97b 100644 --- a/speeduino/corrections.ino +++ b/speeduino/corrections.ino @@ -151,8 +151,8 @@ uint16_t correctionsFuel() currentStatus.wueCorrection = correctionWUE(); if (currentStatus.wueCorrection != 100) { sumCorrections = div100(sumCorrections * currentStatus.wueCorrection); } - result = correctionASE(); - if (result != 100) { sumCorrections = div100(sumCorrections * result); } + currentStatus.ASEValue = correctionASE(); + if (currentStatus.ASEValue != 100) { sumCorrections = div100(sumCorrections * currentStatus.ASEValue); } result = correctionCranking(); if (result != 100) { sumCorrections = div100(sumCorrections * result); } @@ -213,7 +213,7 @@ static inline byte correctionsFuel_new() //The values returned by each of the correction functions are multiplied together and then divided back to give a single 0-255 value. currentStatus.wueCorrection = correctionWUE(); numCorrections++; - uint16_t correctionASEvalue = correctionASE(); numCorrections++; + currentStatus.ASEValue = correctionASE(); numCorrections++; uint16_t correctionCrankingValue = correctionCranking(); numCorrections++; currentStatus.AEamount = correctionAccel(); numCorrections++; uint8_t correctionFloodClearValue = correctionFloodClear(); numCorrections++; @@ -229,7 +229,7 @@ static inline byte correctionsFuel_new() if ( BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) == 1 ) { sumCorrections = 0; } sumCorrections = currentStatus.wueCorrection \ - + correctionASEvalue \ + + currentStatus.ASEValue \ + correctionCrankingValue \ + currentStatus.AEamount \ + correctionFloodClearValue \ @@ -301,13 +301,13 @@ uint16_t correctionCranking() */ byte correctionASE() { - int16_t ASEValue = 100; + int16_t ASEValue = currentStatus.ASEValue; //Two checks are required: //1) Is the engine run time less than the configured ase time //2) Make sure we're not still cranking if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) != true ) { - if ( BIT_CHECK(LOOP_TIMER, BIT_TIMER_15HZ) || (currentStatus.ASEValue == 0) ) + if ( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) || (currentStatus.ASEValue == 0) ) { if ( (currentStatus.runSecs < (table2D_getValue(&ASECountTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET))) && !(BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) ) { @@ -333,15 +333,16 @@ byte correctionASE() //Safety checks if(ASEValue > 255) { ASEValue = 255; } if(ASEValue < 0) { ASEValue = 0; } - currentStatus.ASEValue = (byte)ASEValue; + ASEValue = (byte)ASEValue; } } else { + //Engine is cranking, ASE disabled BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as inactive. ASEValue = 100; } - return currentStatus.ASEValue; + return ASEValue; } /** Acceleration enrichment correction calculation. From 655905e867bd47350aabe00ce43bfb82ee4a61cd Mon Sep 17 00:00:00 2001 From: "Vitor Moreno B. Sales" Date: Wed, 29 Jun 2022 03:37:50 -0300 Subject: [PATCH 17/46] Enable use of disabled functions pins (#549) * Enable use pins of disabled functions or unused ign channels * Added new pins and functions to check --- speeduino/globals.h | 10 ++++-- speeduino/globals.ino | 71 +++++++++++++++++++++++++++++++++++++++++ speeduino/speeduino.h | 1 - speeduino/speeduino.ino | 1 - 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/speeduino/globals.h b/speeduino/globals.h index 7460c6c6..2520f503 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -611,6 +611,7 @@ extern volatile byte HWTest_INJ; /**< Each bit in this variable represents extern volatile byte HWTest_INJ_50pc; /**< Each bit in this variable represents one of the injector channels and it's 50% HW test status */ extern volatile byte HWTest_IGN; /**< Each bit in this variable represents one of the ignition channels and it's HW test status */ extern volatile byte HWTest_IGN_50pc; /**< Each bit in this variable represents one of the ignition channels and it's 50% HW test status */ +extern byte maxIgnOutputs; /**< Used for rolling rev limiter to indicate how many total ignition channels should currently be firing */ extern byte resetControl; ///< resetControl needs to be here (as global) because using the config page (4) directly can prevent burning the setting @@ -621,9 +622,9 @@ extern volatile byte LOOP_TIMER; //These functions all do checks on a pin to determine if it is already in use by another (higher importance) function #define pinIsInjector(pin) ( ((pin) == pinInjector1) || ((pin) == pinInjector2) || ((pin) == pinInjector3) || ((pin) == pinInjector4) || ((pin) == pinInjector5) || ((pin) == pinInjector6) || ((pin) == pinInjector7) || ((pin) == pinInjector8) ) #define pinIsIgnition(pin) ( ((pin) == pinCoil1) || ((pin) == pinCoil2) || ((pin) == pinCoil3) || ((pin) == pinCoil4) || ((pin) == pinCoil5) || ((pin) == pinCoil6) || ((pin) == pinCoil7) || ((pin) == pinCoil8) ) -#define pinIsOutput(pin) ( pinIsInjector((pin)) || pinIsIgnition((pin)) || ((pin) == pinFuelPump) || ((pin) == pinFan) || ((pin) == pinVVT_1) || ((pin) == pinVVT_2) || ( ((pin) == pinBoost) && configPage6.boostEnabled) || ((pin) == pinIdle1) || ((pin) == pinIdle2) || ((pin) == pinTachOut) || ((pin) == pinStepperEnable) || ((pin) == pinStepperStep) ) -#define pinIsSensor(pin) ( ((pin) == pinCLT) || ((pin) == pinIAT) || ((pin) == pinMAP) || ((pin) == pinTPS) || ((pin) == pinO2) || ((pin) == pinBat) ) -#define pinIsUsed(pin) ( pinIsSensor((pin)) || pinIsOutput((pin)) || pinIsReserved((pin)) ) +//#define pinIsOutput(pin) ( pinIsInjector((pin)) || pinIsIgnition((pin)) || ((pin) == pinFuelPump) || ((pin) == pinFan) || ((pin) == pinVVT_1) || ((pin) == pinVVT_2) || ( ((pin) == pinBoost) && configPage6.boostEnabled) || ((pin) == pinIdle1) || ((pin) == pinIdle2) || ((pin) == pinTachOut) || ((pin) == pinStepperEnable) || ((pin) == pinStepperStep) ) +#define pinIsSensor(pin) ( ((pin) == pinCLT) || ((pin) == pinIAT) || ((pin) == pinMAP) || ((pin) == pinTPS) || ((pin) == pinO2) || ((pin) == pinBat) || (((pin) == pinFlex) && (configPage2.flexEnabled != 0)) ) +//#define pinIsUsed(pin) ( pinIsSensor((pin)) || pinIsOutput((pin)) || pinIsReserved((pin)) ) /** The status struct with current values for all 'live' variables. * In current version this is 64 bytes. Instantiated as global currentStatus. @@ -1563,4 +1564,7 @@ extern struct table2D cltCalibrationTable; /**< A 32 bin array containing the co extern struct table2D iatCalibrationTable; /**< A 32 bin array containing the inlet air temperature sensor calibration values */ extern struct table2D o2CalibrationTable; /**< A 32 bin array containing the O2 sensor calibration values */ +bool pinIsOutput(byte pin); +bool pinIsUsed(byte pin); + #endif // GLOBALS_H diff --git a/speeduino/globals.ino b/speeduino/globals.ino index 412c4f86..6b02b12d 100644 --- a/speeduino/globals.ino +++ b/speeduino/globals.ino @@ -159,6 +159,7 @@ volatile byte HWTest_INJ = 0; /**< Each bit in this variable represents one of t volatile byte HWTest_INJ_50pc = 0; /**< Each bit in this variable represents one of the injector channels and it's 50% HW test status */ volatile byte HWTest_IGN = 0; /**< Each bit in this variable represents one of the ignition channels and it's HW test status */ volatile byte HWTest_IGN_50pc = 0; +byte maxIgnOutputs = 1; /**< Used for rolling rev limiter to indicate how many total ignition channels should currently be firing */ //This needs to be here because using the config page directly can prevent burning the setting @@ -271,3 +272,73 @@ struct table2D iatCalibrationTable; uint16_t o2Calibration_bins[32]; uint8_t o2Calibration_values[32]; struct table2D o2CalibrationTable; + +//These function do checks on a pin to determine if it is already in use by another (higher importance) active function +inline bool pinIsOutput(byte pin) +{ + bool used = false; + bool isIdlePWM = (configPage6.iacAlgorithm > 0) && ((configPage6.iacAlgorithm <= 3) || (configPage6.iacAlgorithm == 6)); + bool isIdleSteper = (configPage6.iacAlgorithm > 3) && (configPage6.iacAlgorithm != 6); + //Injector? + if ((pin == pinInjector1) + || ((pin == pinInjector2) && (configPage2.nInjectors > 1)) + || ((pin == pinInjector3) && (configPage2.nInjectors > 2)) + || ((pin == pinInjector4) && (configPage2.nInjectors > 3)) + || ((pin == pinInjector5) && (configPage2.nInjectors > 4)) + || ((pin == pinInjector6) && (configPage2.nInjectors > 5)) + || ((pin == pinInjector7) && (configPage2.nInjectors > 6)) + || ((pin == pinInjector8) && (configPage2.nInjectors > 7))) + { + used = true; + } + //Ignition? + if ((pin == pinCoil1) + || ((pin == pinCoil2) && (maxIgnOutputs > 1)) + || ((pin == pinCoil3) && (maxIgnOutputs > 2)) + || ((pin == pinCoil4) && (maxIgnOutputs > 3)) + || ((pin == pinCoil5) && (maxIgnOutputs > 4)) + || ((pin == pinCoil6) && (maxIgnOutputs > 5)) + || ((pin == pinCoil7) && (maxIgnOutputs > 6)) + || ((pin == pinCoil8) && (maxIgnOutputs > 7))) + { + used = true; + } + //Functions? + if ((pin == pinFuelPump) + || ((pin == pinFan) && (configPage2.fanEnable == 1)) + || ((pin == pinVVT_1) && (configPage6.vvtEnabled > 0)) + || ((pin == pinVVT_1) && (configPage10.wmiEnabled > 0)) + || ((pin == pinVVT_2) && (configPage10.vvt2Enabled > 0)) + || ((pin == pinBoost) && (configPage6.boostEnabled == 1)) + || ((pin == pinIdle1) && isIdlePWM) + || ((pin == pinIdle2) && isIdlePWM && (configPage6.iacChannels == 1)) + || ((pin == pinStepperEnable) && isIdleSteper) + || ((pin == pinStepperStep) && isIdleSteper) + || ((pin == pinStepperDir) && isIdleSteper) + || (pin == pinTachOut) ) + { + used = true; + } + //Forbiden or hardware reserved? (Defined at board_xyz.h file) + if ( pinIsReserved(pin) ) { used = true; } + + return used; +} + +inline bool pinIsUsed(byte pin) +{ + bool used = false; + + //Analog input? + if ( pinIsSensor(pin) ) + { + used = true; + } + //Functions? + if ( pinIsOutput(pin) ) + { + used = true; + } + + return used; +} diff --git a/speeduino/speeduino.h b/speeduino/speeduino.h index 68258ad2..b8a2ba8f 100644 --- a/speeduino/speeduino.h +++ b/speeduino/speeduino.h @@ -38,7 +38,6 @@ extern uint16_t inj_opentime_uS; /**< The injector opening time. This is set wit extern bool ignitionOn; /**< The current state of the ignition system (on or off) */ extern bool fuelOn; /**< The current state of the fuel system (on or off) */ -extern byte maxIgnOutputs; /**< Used for rolling rev limiter to indicate how many total ignition channels should currently be firing */ extern byte curRollingCut; /**< Rolling rev limiter, current ignition channel being cut */ extern byte rollingCutCounter; /**< how many times (revolutions) the ignition has been cut in a row */ extern uint32_t rollingCutLastRev; /**< Tracks whether we're on the same or a different rev for the rolling cut */ diff --git a/speeduino/speeduino.ino b/speeduino/speeduino.ino index 4bee59cb..89486f1b 100644 --- a/speeduino/speeduino.ino +++ b/speeduino/speeduino.ino @@ -78,7 +78,6 @@ uint16_t inj_opentime_uS = 0; bool ignitionOn = false; /**< The current state of the ignition system (on or off) */ bool fuelOn = false; /**< The current state of the fuel system (on or off) */ -byte maxIgnOutputs = 1; /**< Used for rolling rev limiter to indicate how many total ignition channels should currently be firing */ byte curRollingCut = 0; /**< Rolling rev limiter, current ignition channel being cut */ byte rollingCutCounter = 0; /**< how many times (revolutions) the ignition has been cut in a row */ uint32_t rollingCutLastRev = 0; /**< Tracks whether we're on the same or a different rev for the rolling cut */ From 31fbaf19a35f3c0a3a38d17f6aedfba9e852b581 Mon Sep 17 00:00:00 2001 From: "Vitor Moreno B. Sales" Date: Wed, 29 Jun 2022 03:41:52 -0300 Subject: [PATCH 18/46] Fix for semi-seq inj after #478 (#883) --- speeduino/updates.ino | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/speeduino/updates.ino b/speeduino/updates.ino index b30a464d..e3975a82 100644 --- a/speeduino/updates.ino +++ b/speeduino/updates.ino @@ -612,7 +612,11 @@ void doUpdates() //Option added to select injector pairing on 4 cylinder engines if( configPage4.inj4cylPairing > INJ_PAIR_14_23 ) { configPage4.inj4cylPairing = 0; } //Check valid value - if( configPage2.nCylinders == 4 ) { configPage4.inj4cylPairing = INJ_PAIR_14_23; } //Force setting to use the default mode from previous FW versions. This is to prevent issues on any setups that have been wired accordingly + if( configPage2.nCylinders == 4 ) + { + if ( configPage2.injLayout == INJ_SEQUENTIAL ) { configPage4.inj4cylPairing = INJ_PAIR_13_24; } //Since #478 engine will always start in semi, make the sequence right for the majority of inlie 4 engines + else { configPage4.inj4cylPairing = INJ_PAIR_14_23; } //Force setting to use the default mode from previous FW versions. This is to prevent issues on any setups that have been wired accordingly + } configPage9.hardRevMode = 1; //Set hard rev limiter to Fixed mode configPage6.tachoMode = 0; From 528bf80252be44b9026b03d68f2ce8e630b2cc36 Mon Sep 17 00:00:00 2001 From: Daniel Tobias Date: Wed, 29 Jun 2022 17:11:42 +1000 Subject: [PATCH 19/46] Don't try to run inappropriate CI on forked repositories (#871) --- .github/workflows/build-firmware.yml | 16 +++++++++++----- .github/workflows/doxygen.yml | 17 ++++++----------- .github/workflows/unit-tests.yml | 6 +++--- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build-firmware.yml b/.github/workflows/build-firmware.yml index fafea9cd..a5d2f6f1 100644 --- a/.github/workflows/build-firmware.yml +++ b/.github/workflows/build-firmware.yml @@ -34,11 +34,17 @@ jobs: python -m pip install --upgrade pip pip install --upgrade platformio - - name: Run PlatformIO - run: platformio run -e teensy35 -e teensy36 -e teensy41 -e black_F407VE -e megaatmega2561 -e megaatmega2560 + - name: Build test atmel + run: platformio run -e megaatmega2560 -e megaatmega2561 + + - name: Build test teensy + run: platformio run -e teensy35 -e teensy36 -e teensy41 + + - name: Build test STM32 + run: platformio run -e black_F407VE -e BlackPill_F401CC -e BlackPill_F411CE_USB - name: Upload to Speeduino server - if: github.event_name != 'pull_request' + if: github.event_name != 'pull_request' && github.repository_owner == 'noisymime' env: WEB_PWD: ${{ secrets.WEB_PWD }} run: | @@ -51,7 +57,7 @@ jobs: - name: Slack Notification (Passed) uses: rtCamp/action-slack-notify@v2 - if: success() && github.event_name != 'pull_request' + if: success() && github.event_name != 'pull_request' && github.repository_owner == 'noisymime' env: SLACK_CHANNEL: git SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff' @@ -63,7 +69,7 @@ jobs: - name: Slack Notification (Failed) uses: rtCamp/action-slack-notify@v2 - if: failure() && github.event_name != 'pull_request' + if: failure() && github.event_name != 'pull_request' && github.repository_owner == 'noisymime' env: SLACK_CHANNEL: git SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff' diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 23e38f8d..c4ba4823 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -1,6 +1,4 @@ -# This is a basic workflow to help you get started with Actions - -name: Doxygen Action +name: Build and update Doxygen documentation # Controls when the action will run. Triggers the workflow on push or pull request # events but only for the master branch @@ -8,8 +6,6 @@ on: push: branches: [ master ] - - # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "build" @@ -22,21 +18,20 @@ jobs: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - - name: Doxygen Action - uses: mattnotmitt/doxygen-action@v1.1.0 + - name: Build Doxygen documentation + uses: mattnotmitt/doxygen-action@v1.9 with: - # Path to Doxyfile doxyfile-path: "./Doxyfile" # default is ./Doxyfile - # Working directory working-directory: "." # default is . - name: Setup git config + if: github.repository_owner == 'noisymime' run: | git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" - - name: Commit Doxygen HTML - if: github.event_name != 'pull_request' + - name: Commit updated Doxygen documentation + if: github.event_name != 'pull_request' && github.repository_owner == 'noisymime' env: GH_DOXYGEN: ${{ secrets.GH_DOXYGEN }} run: | diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 2c57852d..d18fcd1f 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -1,5 +1,3 @@ -# This is a basic workflow to help you get started with Actions - name: Unit Tests # Controls when the workflow will run @@ -13,6 +11,8 @@ on: jobs: build: + # Only try to run hardware unit tests on the upstream repository + if: github.repository_owner == 'noisymime' runs-on: ubuntu-latest @@ -67,4 +67,4 @@ jobs: SLACK_TITLE: 'Unit tests FAILED :warning:' SLACK_USERNAME: Github SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} - MSG_MINIMAL: actions url,commit \ No newline at end of file + MSG_MINIMAL: actions url,commit From 947f4de9eeefb40ca99e421d1fc08e413bac2faf Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Wed, 29 Jun 2022 17:39:18 +1000 Subject: [PATCH 20/46] Remove old unused corrections code --- speeduino/corrections.ino | 72 --------------------------------------- 1 file changed, 72 deletions(-) diff --git a/speeduino/corrections.ino b/speeduino/corrections.ino index 627db97b..72765191 100644 --- a/speeduino/corrections.ino +++ b/speeduino/corrections.ino @@ -70,78 +70,6 @@ void initialiseCorrections() Calls all the other corrections functions and combines their results. This is the only function that should be called from anywhere outside the file */ -uint16_t correctionsFuel1() -{ - #define MAX_CORRECTIONS 3 //The maximum number of corrections allowed before the sum is reprocessed - uint32_t sumCorrections = 100; - byte activeCorrections = 0; - uint16_t result; //temporary variable to store the result of each corrections function - - //The values returned by each of the correction functions are multiplied together and then divided back to give a single 0-255 value. - currentStatus.wueCorrection = correctionWUE(); - if (currentStatus.wueCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.wueCorrection); activeCorrections++; } - - result = correctionASE(); - if (result != 100) { sumCorrections = (sumCorrections * result); activeCorrections++; } - - result = correctionCranking(); - if (result != 100) { sumCorrections = (sumCorrections * result); activeCorrections++; } - if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } // Need to check this to ensure that sumCorrections doesn't overflow. Can occur when the number of corrections is greater than 3 (Which is 100^4) as 100^5 can overflow - - currentStatus.AEamount = correctionAccel(); - if (configPage2.aeApplyMode == AE_MODE_MULTIPLIER) - { - if (currentStatus.AEamount != 100) { sumCorrections = (sumCorrections * currentStatus.AEamount); activeCorrections++; } - if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } - } - - result = correctionFloodClear(); - if (result != 100) { sumCorrections = (sumCorrections * result); activeCorrections++; } - if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } - - currentStatus.egoCorrection = correctionAFRClosedLoop(); - if (currentStatus.egoCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.egoCorrection); activeCorrections++; } - if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } - - currentStatus.batCorrection = correctionBatVoltage(); - if (configPage2.battVCorMode == BATTV_COR_MODE_OPENTIME) - { - inj_opentime_uS = configPage2.injOpen * currentStatus.batCorrection; // Apply voltage correction to injector open time. - } - if (configPage2.battVCorMode == BATTV_COR_MODE_WHOLE) - { - if (currentStatus.batCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.batCorrection); activeCorrections++; } - if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } - } - - currentStatus.iatCorrection = correctionIATDensity(); - if (currentStatus.iatCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.iatCorrection); activeCorrections++; } - if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } - - currentStatus.baroCorrection = correctionBaro(); - if (currentStatus.baroCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.baroCorrection); activeCorrections++; } - if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } - - currentStatus.flexCorrection = correctionFlex(); - if (currentStatus.flexCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.flexCorrection); activeCorrections++; } - if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } - - currentStatus.fuelTempCorrection = correctionFuelTemp(); - if (currentStatus.fuelTempCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.fuelTempCorrection); activeCorrections++; } - if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } - - currentStatus.launchCorrection = correctionLaunch(); - if (currentStatus.launchCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.launchCorrection); activeCorrections++; } - - bitWrite(currentStatus.status1, BIT_STATUS1_DFCO, correctionDFCO()); - if ( BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) == 1 ) { sumCorrections = 0; } - - sumCorrections = sumCorrections / powint(100,activeCorrections); - - if(sumCorrections > 1500) { sumCorrections = 1500; } //This is the maximum allowable increase during cranking - return (uint16_t)sumCorrections; -} - uint16_t correctionsFuel() { uint32_t sumCorrections = 100; From 8f893f5e46f9c15a0d83138c265947c2170671ae Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Wed, 29 Jun 2022 17:42:52 +1000 Subject: [PATCH 21/46] Remove controller priority on trigger edge. Fixes #860 This was added for a specific FW update in 2018 and no longer needed. --- reference/speeduino.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 0ecc3458..a659a526 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -1622,9 +1622,6 @@ page = 15 defaultValue = ADCFILTER_BARO, 64 defaultValue = FILTER_FLEX, 75 - ;Again, force the setting from the controller for the trigger edges. This is particularly useful for the Oct 2018 update where the names of the edges changed - controllerPriority = TrigEdge - controllerPriority = TrigEdgeSec ;VSS Ratios and calibration need controller priority so they can be set with the command buttons controllerPriority = vssPulsesPerKm controllerPriority = vssRatio1 From 57973bd29de0015d38fac630349268baf2c5b1d3 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Fri, 8 Jul 2022 13:27:38 +1000 Subject: [PATCH 22/46] Add engine protection flags to datalog --- reference/speeduino.ini | 235 ++++++++++++++++++++-------------------- 1 file changed, 120 insertions(+), 115 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index a659a526..4ac2a7c8 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -5072,7 +5072,7 @@ cmdVSSratio6 = "E\x99\x06" engineProtectMAP = bits, U08, 84, [1:1] engineProtectOil = bits, U08, 84, [2:2] engineProtectAFR = bits, U08, 84, [3:3] - engineProtectCoolant = bits, U08, 84, [4:4] + engineProtectCoolant = bits, U08, 84, [4:4] engineProtectOth = bits, U08, 84, [5:6] ; Unused for now IOError = bits, U08, 84, [7:7] unused1 = scalar, U08, 84, "ADC",1.000, 0.000 @@ -5208,122 +5208,127 @@ cmdVSSratio6 = "E\x99\x06" ;------------------------------------------------------------------------------- [Datalog] - ; Full datalog. - ; - ; Default user-defined log emulates the full datalog. - ; - ; The entries are saved in the datalog file in the order in - ; which they appear in the list below. - ; - ; Channel - Case sensitive name of output channel to be logged. - ; Label - String written to header line of log. Be careful - ; about changing these, as programs like MSLVV and - ; MSTweak key off specific column names. - ; Type - Data type of output, converted before writing. - ; Format - C-style output format of data. - ; - ; Channel Label Type Format - ; -------------- ---------- ----- ------ - entry = time, "Time", float, "%.3f" - entry = secl, "SecL", int, "%d" - entry = rpm, "RPM", int, "%d" - entry = map, "MAP", int, "%d" - entry = MAPxRPM, "MAPxRPM", int, "%d" - entry = tps, "TPS", float, "%.1f" - entry = afr, "AFR", float, "%.3f" - entry = lambda, "Lambda", float, "%.3f" - entry = iat, "IAT", int, "%d" - entry = coolant, "CLT", int, "%d" - entry = engine, "Engine", int, "%d" - entry = DFCOOn, "DFCO", int, "%d" - entry = egoCorrection, "Gego", int, "%d" - entry = airCorrection, "Gair", int, "%d" - entry = bat_correction, "Gbattery", int, "%d" - entry = warmupEnrich, "Gwarm", int, "%d" - entry = baroCorrection, "Gbaro", int, "%d" - entry = gammaEnrich, "Gammae", int, "%d" - entry = accelEnrich, "Accel Enrich", int, "%d" - entry = veCurr, "VE (Current)", int, "%d" - entry = VE1, "VE1", int, "%d" - entry = VE2, "VE2", int, "%d" - entry = pulseWidth, "PW", float, "%.3f" - entry = afrTarget, "AFR Target", float, "%.3f" - entry = lambdaTarget, "Lambda Target", float, "%.3f" - entry = pulseWidth2, "PW2", float, "%.3f" - entry = dutyCycle, "DutyCycle1", float, "%.1f" - entry = TPSdot, "TPS DOT", int, "%d" { aeMode == 0 } - entry = advance, "Advance (Current)",int, "%d" - entry = dwell, "Dwell", float, "%.1f" - entry = batteryVoltage, "Battery V", float, "%.1f" - entry = rpmDOT, "rpm/s", int, "%d" - entry = flex, "Eth %", int, "%d", { flexEnabled } - entry = flexFuelCor, "GflexFuel", int, "%d", { flexEnabled } - entry = fuelTemp, "Fuel Temp", int, "%d", { flexEnabled } - entry = fuelTempCor, "GfuelTemp", int, "%d", { flexEnabled } - entry = errorNum, "Error #", int, "%d", { errorNum } - entry = currentError, "Error ID", int, "%d", { errorNum } - entry = map_psi, "Boost PSI", float, "%.1f" - entry = boostTarget, "Boost Target", int, "%d", { boostEnabled } - entry = boostDuty, "Boost Duty", int, "%d", { boostEnabled } - entry = boostCutOut , "Boost cut", int, "%d" - entry = launchHard , "Hard Launch", int, "%d" - entry = hardLimitOn , "Hard Limiter", int, "%d" - entry = idleControlOn, "Idle Control", int, "%d" - entry = idleLoad, "IAC value", int, "%d" - entry = CLIdleTarget, "Idle Target RPM", int, "%%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled - entry = CLIdleDelta, "Idle RPM Delta", int, "%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled - entry = baro, "Baro Pressure", int, "%d" - entry = nitrousOn, "Nitrous", int, "%d", { n2o_enable > 0 } - entry = fanStatus, "Fan", int, "%d" - entry = syncLossCounter, "Sync Loss #", int, "%d" - entry = vvt1Angle, "VVT1 Angle", int, "%.1f", { vvtEnabled > 0 } - entry = vvt1Target, "VVT1 Target Angle",int, "%.1f", { vvtEnabled > 0 && vvtMode == 2 } ;;Only show when using close loop vvt - entry = vvt1Duty, "VVT1 Duty", int, "%.1f", { vvtEnabled > 0 } - entry = vss, "Wheel Speed (kph)",int, "%d", { vssMode > 1 } - entry = vssMPH, "Wheel Speed (mph)",int, "%d", { vssMode > 1 } - entry = gear, "Gear", int, "%d", { vssMode > 1 } - entry = fuelPressure, "Fuel Pressure", int, "%d", { fuelPressureEnable > 0 } - entry = oilPressure, "Oil Pressure", int, "%d", { oilPressureEnable > 0 } - entry = vvt2Angle, "VVT2 Angle", int, "%.1f", { vvt2Enabled > 0 } - entry = vvt2Target, "VVT2 Target Angle",int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } ;;Only show when using close loop vvt - entry = vvt2Duty, "VVT2 Duty", int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } - entry = fanDuty, "FAN Duty", int, "%%.1f", { fanEnable == 2 } - entry = loopsPerSecond, "Loops/s", int, "%d" - entry = loopsPerRev, "Loops/rev", int, "%.2f" - entry = wmiPW, "WMI Duty Cycle", int, "%d", { wmiEnabled == 1 } - entry = MAPdot, "MAP DOT", int, "%d" { aeMode == 1 } + ; Full datalog. + ; + ; Default user-defined log emulates the full datalog. + ; + ; The entries are saved in the datalog file in the order in + ; which they appear in the list below. + ; + ; Channel - Case sensitive name of output channel to be logged. + ; Label - String written to header line of log. Be careful + ; about changing these, as programs like MSLVV and + ; MSTweak key off specific column names. + ; Type - Data type of output, converted before writing. + ; Format - C-style output format of data. + ; + ; Channel Label Type Format + ; -------------- ---------- ----- ------ + entry = time, "Time", float, "%.3f" + entry = secl, "SecL", int, "%d" + entry = rpm, "RPM", int, "%d" + entry = map, "MAP", int, "%d" + entry = MAPxRPM, "MAPxRPM", int, "%d" + entry = tps, "TPS", float, "%.1f" + entry = afr, "AFR", float, "%.3f" + entry = lambda, "Lambda", float, "%.3f" + entry = iat, "IAT", int, "%d" + entry = coolant, "CLT", int, "%d" + entry = engine, "Engine", int, "%d" + entry = DFCOOn, "DFCO", int, "%d" + entry = egoCorrection, "Gego", int, "%d" + entry = airCorrection, "Gair", int, "%d" + entry = bat_correction, "Gbattery", int, "%d" + entry = warmupEnrich, "Gwarm", int, "%d" + entry = baroCorrection, "Gbaro", int, "%d" + entry = gammaEnrich, "Gammae", int, "%d" + entry = accelEnrich, "Accel Enrich", int, "%d" + entry = veCurr, "VE (Current)", int, "%d" + entry = VE1, "VE1", int, "%d" + entry = VE2, "VE2", int, "%d" + entry = pulseWidth, "PW", float, "%.3f" + entry = afrTarget, "AFR Target", float, "%.3f" + entry = lambdaTarget, "Lambda Target", float, "%.3f" + entry = pulseWidth2, "PW2", float, "%.3f" + entry = dutyCycle, "DutyCycle1", float, "%.1f" + entry = TPSdot, "TPS DOT", int, "%d" { aeMode == 0 } + entry = advance, "Advance (Current)",int, "%d" + entry = dwell, "Dwell", float, "%.1f" + entry = batteryVoltage, "Battery V", float, "%.1f" + entry = rpmDOT, "rpm/s", int, "%d" + entry = flex, "Eth %", int, "%d", { flexEnabled } + entry = flexFuelCor, "GflexFuel", int, "%d", { flexEnabled } + entry = fuelTemp, "Fuel Temp", int, "%d", { flexEnabled } + entry = fuelTempCor, "GfuelTemp", int, "%d", { flexEnabled } + entry = errorNum, "Error #", int, "%d", { errorNum } + entry = currentError, "Error ID", int, "%d", { errorNum } + entry = map_psi, "Boost PSI", float, "%.1f" + entry = boostTarget, "Boost Target", int, "%d", { boostEnabled } + entry = boostDuty, "Boost Duty", int, "%d", { boostEnabled } + entry = boostCutOut , "Boost cut", int, "%d" + entry = launchHard , "Hard Launch", int, "%d" + entry = hardLimitOn , "Hard Limiter", int, "%d" + entry = idleControlOn, "Idle Control", int, "%d" + entry = idleLoad, "IAC value", int, "%d" + entry = CLIdleTarget, "Idle Target RPM", int, "%%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled + entry = CLIdleDelta, "Idle RPM Delta", int, "%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled + entry = baro, "Baro Pressure", int, "%d" + entry = nitrousOn, "Nitrous", int, "%d", { n2o_enable > 0 } + entry = fanStatus, "Fan", int, "%d" + entry = syncLossCounter, "Sync Loss #", int, "%d" + entry = vvt1Angle, "VVT1 Angle", int, "%.1f", { vvtEnabled > 0 } + entry = vvt1Target, "VVT1 Target Angle",int, "%.1f", { vvtEnabled > 0 && vvtMode == 2 } ;;Only show when using close loop vvt + entry = vvt1Duty, "VVT1 Duty", int, "%.1f", { vvtEnabled > 0 } + entry = vss, "Wheel Speed (kph)",int, "%d", { vssMode > 1 } + entry = vssMPH, "Wheel Speed (mph)",int, "%d", { vssMode > 1 } + entry = gear, "Gear", int, "%d", { vssMode > 1 } + entry = fuelPressure, "Fuel Pressure", int, "%d", { fuelPressureEnable > 0 } + entry = oilPressure, "Oil Pressure", int, "%d", { oilPressureEnable > 0 } + entry = vvt2Angle, "VVT2 Angle", int, "%.1f", { vvt2Enabled > 0 } + entry = vvt2Target, "VVT2 Target Angle",int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } ;;Only show when using close loop vvt + entry = vvt2Duty, "VVT2 Duty", int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } + entry = fanDuty, "FAN Duty", int, "%%.1f", { fanEnable == 2 } + entry = loopsPerSecond, "Loops/s", int, "%d" + entry = loopsPerRev, "Loops/rev", int, "%.2f" + entry = wmiPW, "WMI Duty Cycle", int, "%d", { wmiEnabled == 1 } + entry = MAPdot, "MAP DOT", int, "%d" { aeMode == 1 } - entry = auxin_gauge0, { stringValue(AUXin00Alias) }, int, "%d", {(caninput_sel0b != 0)} - entry = auxin_gauge1, { stringValue(AUXin01Alias) }, int, "%d", { (caninput_sel1b != 0)} - entry = auxin_gauge2, { stringValue(AUXin02Alias) }, int, "%d", { (caninput_sel2b != 0)} - entry = auxin_gauge3, { stringValue(AUXin03Alias) }, int, "%d", { (caninput_sel3b != 0)} - entry = auxin_gauge4, { stringValue(AUXin04Alias) }, int, "%d", { (caninput_sel4b != 0)} - entry = auxin_gauge5, { stringValue(AUXin05Alias) }, int, "%d", { (caninput_sel5b != 0)} - entry = auxin_gauge6, { stringValue(AUXin06Alias) }, int, "%d", { (caninput_sel6b != 0)} - entry = auxin_gauge7, { stringValue(AUXin07Alias) }, int, "%d", { (caninput_sel7b != 0)} - entry = auxin_gauge8, { stringValue(AUXin08Alias) }, int, "%d", { (caninput_sel8b != 0)} - entry = auxin_gauge9, { stringValue(AUXin09Alias) }, int, "%d", { (caninput_sel9b != 0)} - entry = auxin_gauge10, { stringValue(AUXin10Alias) }, int, "%d", { (caninput_sel10b != 0)} - entry = auxin_gauge11, { stringValue(AUXin11Alias) }, int, "%d", { (caninput_sel11b != 0)} - entry = auxin_gauge12, { stringValue(AUXin12Alias) }, int, "%d", { (caninput_sel12b != 0)} - entry = auxin_gauge13, { stringValue(AUXin13Alias) }, int, "%d", { (caninput_sel13b != 0)} - entry = auxin_gauge14, { stringValue(AUXin14Alias) }, int, "%d", { (caninput_sel14b != 0)} - entry = auxin_gauge15, { stringValue(AUXin15Alias) }, int, "%d", { (caninput_sel15b != 0)} - entry = outputsStatus0, { stringValue(prgm_out00Alias)}, int, "%d", { (outputPin[0] != 0)} - entry = outputsStatus1, { stringValue(prgm_out01Alias)}, int, "%d", { (outputPin[1] != 0)} - entry = outputsStatus2, { stringValue(prgm_out02Alias)}, int, "%d", { (outputPin[2] != 0)} - entry = outputsStatus3, { stringValue(prgm_out03Alias)}, int, "%d", { (outputPin[3] != 0)} - entry = outputsStatus4, { stringValue(prgm_out04Alias)}, int, "%d", { (outputPin[4] != 0)} - entry = outputsStatus5, { stringValue(prgm_out05Alias)}, int, "%d", { (outputPin[5] != 0)} - entry = outputsStatus6, { stringValue(prgm_out06Alias)}, int, "%d", { (outputPin[6] != 0)} - entry = outputsStatus7, { stringValue(prgm_out07Alias)}, int, "%d", { (outputPin[7] != 0)} + entry = auxin_gauge0, { stringValue(AUXin00Alias) }, int, "%d", {(caninput_sel0b != 0)} + entry = auxin_gauge1, { stringValue(AUXin01Alias) }, int, "%d", { (caninput_sel1b != 0)} + entry = auxin_gauge2, { stringValue(AUXin02Alias) }, int, "%d", { (caninput_sel2b != 0)} + entry = auxin_gauge3, { stringValue(AUXin03Alias) }, int, "%d", { (caninput_sel3b != 0)} + entry = auxin_gauge4, { stringValue(AUXin04Alias) }, int, "%d", { (caninput_sel4b != 0)} + entry = auxin_gauge5, { stringValue(AUXin05Alias) }, int, "%d", { (caninput_sel5b != 0)} + entry = auxin_gauge6, { stringValue(AUXin06Alias) }, int, "%d", { (caninput_sel6b != 0)} + entry = auxin_gauge7, { stringValue(AUXin07Alias) }, int, "%d", { (caninput_sel7b != 0)} + entry = auxin_gauge8, { stringValue(AUXin08Alias) }, int, "%d", { (caninput_sel8b != 0)} + entry = auxin_gauge9, { stringValue(AUXin09Alias) }, int, "%d", { (caninput_sel9b != 0)} + entry = auxin_gauge10, { stringValue(AUXin10Alias) }, int, "%d", { (caninput_sel10b != 0)} + entry = auxin_gauge11, { stringValue(AUXin11Alias) }, int, "%d", { (caninput_sel11b != 0)} + entry = auxin_gauge12, { stringValue(AUXin12Alias) }, int, "%d", { (caninput_sel12b != 0)} + entry = auxin_gauge13, { stringValue(AUXin13Alias) }, int, "%d", { (caninput_sel13b != 0)} + entry = auxin_gauge14, { stringValue(AUXin14Alias) }, int, "%d", { (caninput_sel14b != 0)} + entry = auxin_gauge15, { stringValue(AUXin15Alias) }, int, "%d", { (caninput_sel15b != 0)} + entry = outputsStatus0, { stringValue(prgm_out00Alias)}, int, "%d", { (outputPin[0] != 0)} + entry = outputsStatus1, { stringValue(prgm_out01Alias)}, int, "%d", { (outputPin[1] != 0)} + entry = outputsStatus2, { stringValue(prgm_out02Alias)}, int, "%d", { (outputPin[2] != 0)} + entry = outputsStatus3, { stringValue(prgm_out03Alias)}, int, "%d", { (outputPin[3] != 0)} + entry = outputsStatus4, { stringValue(prgm_out04Alias)}, int, "%d", { (outputPin[4] != 0)} + entry = outputsStatus5, { stringValue(prgm_out05Alias)}, int, "%d", { (outputPin[5] != 0)} + entry = outputsStatus6, { stringValue(prgm_out06Alias)}, int, "%d", { (outputPin[6] != 0)} + entry = outputsStatus7, { stringValue(prgm_out07Alias)}, int, "%d", { (outputPin[7] != 0)} - entry = advance1, "Advance 1", int, "%d" - entry = advance2, "Advance 2", int, "%d" - entry = emap, "EMAP", int, "%d", { useEMAP } - entry = fuelLoad, "FuelLoad", float, "%.1f" - entry = ignLoad, "IgnitionLoad", float, "%.1f" - entry = syncStatus, "Sync status", int, "%d" + entry = advance1, "Advance 1", int, "%d" + entry = advance2, "Advance 2", int, "%d" + entry = emap, "EMAP", int, "%d", { useEMAP } + entry = fuelLoad, "FuelLoad", float, "%.1f" + entry = ignLoad, "IgnitionLoad", float, "%.1f" + entry = syncStatus, "Sync status", int, "%d" + entry = engineProtectRPM, "Engine Prot. RPM", int, "activeInactive", { engineProtectType } + entry = engineProtectMAP, "Engine Prot. MAP", int, "activeInactive", { engineProtectType && boostCutEnabled } + entry = engineProtectOil, "Engine Prot. Oil Pressure", int, "activeInactive", { engineProtectType && oilPressureProtEnbl && oilPressureEnable } + entry = engineProtectAFR, "Engine Prot. AFR", int, "activeInactive", { engineProtectType && afrProtectEnabled && {egoType == 2} } + entry = engineProtectCoolant, "Engine Prot. CLT", int, "activeInactive", { engineProtectType } [LoggerDefinition] ; valid logger types: composite, tooth, trigger, csv From 6db145aa18e494d17197643a0ae927b5b1faa57d Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Fri, 8 Jul 2022 14:31:48 +1000 Subject: [PATCH 23/46] Add option for SD logging with external switch --- reference/speeduino.ini | 26 +++++++++++++------------- speeduino/SD_logger.ino | 19 ++++++++++++++++--- speeduino/globals.h | 6 ++++-- speeduino/globals.ino | 1 + speeduino/init.ino | 7 +++++++ speeduino/updates.ino | 2 +- 6 files changed, 42 insertions(+), 19 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 4ac2a7c8..cdf32907 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -1360,7 +1360,7 @@ page = 13 onboard_log_trigger_RPM = bits, U08, 117, [3:3], "Disabled", "Enabled" onboard_log_trigger_prot = bits, U08, 117, [4:4], "Disabled", "Enabled" onboard_log_trigger_Vbat = bits, U08, 117, [5:5], "Disabled", "Enabled" - onboard_log_trigger_Epin = bits, U08, 117, [6:7], "Disabled", "polling", "toggle" , "INVALID" + onboard_log_trigger_Epin = bits, U08, 117, [6:7], "Disabled", "Enabled", "INVALID", "INVALID" ;In future add momentary on/off option onboard_log_tr1_duration = scalar, U16, 118, "s", 1.000, 0.0, 0, 65000, 0 onboard_log_tr2_thr_on = scalar, U08, 120, "RPM", 100.0, 0.0, 0, 10000, 0 onboard_log_tr2_thr_off = scalar, U08, 121, "RPM", 100.0, 0.0, 0, 10000, 0 @@ -1370,7 +1370,8 @@ page = 13 onboard_log_tr3_thr_AFR = bits, U08, 122, [3:3], "Disabled", "Enabled" onboard_log_tr4_thr_on = scalar, U08, 123, "V", 0.1, 0.0, 0.0, 15.90, 2 ; * ( 1 byte) onboard_log_tr4_thr_off = scalar, U08, 124, "V", 0.1, 0.0, 0.0, 14.90, 2 ; * ( 1 byte) - onboard_log_tr5_thr_on = scalar, U08, 125, "pin", 1.0, 0.0, 0.0, 255, 0 ; + onboard_log_tr5_Epin_pin = bits , U08, 125, [0:5], $IO_Pins_no_def + unused13_125_2 = bits , U08, 125, [6:7], ";", ",", "tab", "space" unused12_125_127 = array, U08, 126, [2], "%", 1.0, 0.0, 0.0, 255, 0 @@ -1658,7 +1659,7 @@ page = 15 defaultValue = onboard_log_tr3_thr_AFR, 0 defaultValue = onboard_log_tr4_thr_on, 12.5 defaultValue = onboard_log_tr4_thr_off, 7.0 - defaultValue = onboard_log_tr5_thr_on, 0 + defaultValue = onboard_log_tr5_Epin_pin, 0 defaultValue = onboard_log_csv_separator, 0 ;VSS related settings @@ -2298,7 +2299,7 @@ menuDialog = main onboard_log_tr3_thr_AFR = "When the bits of the AFR engine protection function are set the datalogger is started when no set anymore the logger is stopped" onboard_log_tr4_thr_on = "When the measured battery voltage is above this threshold the datalogger is started" onboard_log_tr4_thr_off = "When the measured battery voltage is below this threshold the datalogger is stopped" - onboard_log_tr5_thr_on = "The pin to trigger the datalogger start/stop" + onboard_log_tr5_Epin_pin = "The pin to trigger the datalogger start/stop" onboard_log_csv_separator = "Choose what character is used for the CSV separator between fields" battVCorMode = "The Battery Voltage Correction value from the table below can either be applied on the whole injection Pulse Width value, or only on the Open Time value." @@ -4127,10 +4128,6 @@ menuDialog = main field = "Real Time Clock mode", rtc_mode field = "Real Time Clock Trim +/-", rtc_trim, {rtc_mode} -; dialog = rtc_settings, "Real Time Clock" -; panel = rtc_setup -; panel = std_ms3Rtc - dialog = onboard_log_basic_setup, "Log Configuration" field = "Logger type", onboard_log_file_style ;field = "CSV separator", onboard_log_csv_separator {onboard_log_file_style == 1} @@ -4145,13 +4142,18 @@ menuDialog = main field = "On Boot", onboard_log_trigger_boot, {onboard_log_file_style} field = "On Boot log duration", onboard_log_tr1_duration, {onboard_log_file_style && onboard_log_trigger_boot} - dialog = onboard_log_trigger_RPM, "RPM" + dialog = onboard_log_trigger_RPM, "RPM" field = "RPM", onboard_log_trigger_RPM {onboard_log_file_style && !onboard_log_trigger_boot} field = "ON (Min RPM)", onboard_log_tr2_thr_on {onboard_log_file_style && onboard_log_trigger_RPM} field = "OFF (Max RPM)", onboard_log_tr2_thr_off {onboard_log_file_style && onboard_log_trigger_RPM} - dialog = onboard_log_trigger_prot, "Engine protection" + dialog = onboard_log_trigger_prot, "Engine protection" field = "Engine protection", onboard_log_trigger_prot {onboard_log_file_style && !onboard_log_trigger_boot} + + dialog = onboard_log_trigger_Epin, "External Switch" + field = "Board pin", onboard_log_trigger_Epin {onboard_log_file_style && !onboard_log_trigger_boot} + field = "Pin number", onboard_log_tr5_Epin_pin {onboard_log_file_style && onboard_log_trigger_Epin} + ; field = "RPM", onboard_log_tr3_thr_RPM {onboard_log_file_style && onboard_log_trigger_prot} ; field = "MAP", onboard_log_tr3_thr_MAP {onboard_log_file_style && onboard_log_trigger_prot} ; field = "Oil", onboard_log_tr3_thr_Oil {onboard_log_file_style && onboard_log_trigger_prot} @@ -4162,9 +4164,6 @@ menuDialog = main ; field = "ON threshold", onboard_log_tr4_thr_on {onboard_log_file_style && onboard_log_trigger_Vbat} ; field = "OFF threshold", onboard_log_tr4_thr_off {onboard_log_file_style && onboard_log_trigger_Vbat} -; dialog = onboard_log_trigger_Epin, "Board pin" -; field = "Board pin", onboard_log_trigger_Epin {onboard_log_file_style&& !onboard_log_trigger_boot} -; field = "Pin number", onboard_log_tr5_thr_on {onboard_log_file_style && onboard_log_trigger_Epin} dialog = rtc_settings, "Real Time Clock" field = "Mode", rtc_mode @@ -4175,6 +4174,7 @@ menuDialog = main ;field = "Above RPM", onboard_log_trigger_RPM panel = onboard_log_trigger_RPM panel = onboard_log_trigger_prot + panel = onboard_log_trigger_Epin ;field = "With battery", onboard_log_trigger_Vbat dialog = onboard_log_setup, "On-board logger", border diff --git a/speeduino/SD_logger.ino b/speeduino/SD_logger.ino index 5d47975a..a19525c4 100644 --- a/speeduino/SD_logger.ino +++ b/speeduino/SD_logger.ino @@ -356,9 +356,12 @@ void checkForSDStart() } - if(( configPage13.onboard_log_trigger_Epin) && (SD_status == SD_STATUS_READY) ) + if((configPage13.onboard_log_trigger_Epin) && (SD_status == SD_STATUS_READY) ) { - + if(digitalRead(pinSDEnable) == LOW } + { + beginSDLogging(); //Setup the log file, preallocation, header row + } } } @@ -372,6 +375,7 @@ void checkForSDStop() bool log_RPM = false; bool log_prot = false; bool log_Vbat = false; + bool log_Epin = false; //Logging only needs to be stopped if already active if(SD_status == SD_STATUS_ACTIVE) @@ -404,8 +408,17 @@ void checkForSDStop() } + //External Pin + if(configPage13.onboard_log_trigger_Epin) + { + if(digitalRead(pinSDEnable) == LOW) + { + log_Epin = true; + } + } + //Check all conditions to see if we should stop logging - if( (log_boot == false) && (log_RPM == false) && (log_prot == false) && (log_Vbat == false) && (manualLogActive == false) ) + if( (log_boot == false) && (log_RPM == false) && (log_prot == false) && (log_Vbat == false) && (log_Epin == false) && (manualLogActive == false) ) { endSDLogging(); //Setup the log file, preallocation, header row } diff --git a/speeduino/globals.h b/speeduino/globals.h index 2520f503..e90b862e 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -1428,10 +1428,11 @@ struct config13 { byte onboard_log_tr3_thr_AFR :1; // "Disabled", "Enabled" byte onboard_log_tr4_thr_on; // "V", 0.1, 0.0, 0.0, 15.90, 2 ; * ( 1 byte) byte onboard_log_tr4_thr_off; // "V", 0.1, 0.0, 0.0, 15.90, 2 ; * ( 1 byte) - byte onboard_log_tr5_thr_on; // "pin", 0, 0, 0, 1, 255, 0 ; + byte onboard_log_tr5_Epin_pin :6; // "pin", 0, 0, 0, 1, 255, 0 ; + byte unused13_125_2 :2; - byte unused12_125_127[2]; + byte unused12_126_127[2]; #if defined(CORE_AVR) }; @@ -1532,6 +1533,7 @@ extern byte pinWMIIndicator; // No water indicator bulb extern byte pinWMIEnabled; // ON-OFF output to relay/pump/solenoid extern byte pinMC33810_1_CS; extern byte pinMC33810_2_CS; +extern byte pinSDEnable; //Input for manually enabling SD logging #ifdef USE_SPI_EEPROM extern byte pinSPIFlash_CS; #endif diff --git a/speeduino/globals.ino b/speeduino/globals.ino index 6b02b12d..3b209693 100644 --- a/speeduino/globals.ino +++ b/speeduino/globals.ino @@ -246,6 +246,7 @@ byte pinWMIIndicator; // No water indicator bulb byte pinWMIEnabled; // ON-OFF output to relay/pump/solenoid byte pinMC33810_1_CS; byte pinMC33810_2_CS; +byte pinSDEnable; #ifdef USE_SPI_EEPROM byte pinSPIFlash_CS; #endif diff --git a/speeduino/init.ino b/speeduino/init.ino index 26e38301..43f854b5 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -2617,8 +2617,11 @@ void setPinMapping(byte boardID) if ( (configPage10.wmiIndicatorPin != 0) && (configPage10.wmiIndicatorPin < BOARD_MAX_IO_PINS) ) { pinWMIIndicator = pinTranslate(configPage10.wmiIndicatorPin); } if ( (configPage10.wmiEnabledPin != 0) && (configPage10.wmiEnabledPin < BOARD_MAX_IO_PINS) ) { pinWMIEnabled = pinTranslate(configPage10.wmiEnabledPin); } if ( (configPage10.vvt2Pin != 0) && (configPage10.vvt2Pin < BOARD_MAX_IO_PINS) ) { pinVVT_2 = pinTranslate(configPage10.vvt2Pin); } + if ( (configPage13.onboard_log_trigger_Epin != 0 ) && (configPage13.onboard_log_trigger_Epin != 0) && (configPage13.onboard_log_tr5_Epin_pin < BOARD_MAX_IO_PINS) ) { pinSDEnable = pinTranslate(configPage13.onboard_log_tr5_Epin_pin); } + //Currently there's no default pin for Idle Up + pinIdleUp = pinTranslate(configPage2.idleUpPin); //Currently there's no default pin for Idle Up Output @@ -2819,6 +2822,10 @@ void setPinMapping(byte boardID) { pinMode(pinOilPressure, INPUT); } + if( (configPage13.onboard_log_trigger_Epin > 0) && (!pinIsOutput(pinSDEnable)) ) + { + pinMode(pinSDEnable, INPUT); + } if(configPage10.wmiEnabled > 0) { pinMode(pinWMIEnabled, OUTPUT); diff --git a/speeduino/updates.ino b/speeduino/updates.ino index e3975a82..08befd0d 100644 --- a/speeduino/updates.ino +++ b/speeduino/updates.ino @@ -600,7 +600,7 @@ void doUpdates() configPage13.onboard_log_tr3_thr_AFR = 0; configPage13.onboard_log_tr4_thr_on = 0; configPage13.onboard_log_tr4_thr_off = 0; - configPage13.onboard_log_tr5_thr_on = 0; + configPage13.onboard_log_tr5_Epin_pin = 0; writeAllConfig(); storeEEPROMVersion(19); From f97580f2084e3f91dded2cf98458ec00b8cb68a7 Mon Sep 17 00:00:00 2001 From: Min <72794870+zceemja@users.noreply.github.com> Date: Fri, 8 Jul 2022 04:35:15 +0000 Subject: [PATCH 24/46] TS option to display pressure in bar #842 (#864) Adds options in TunerStudio project settings to have default units for fuel and oil pressure in bar. Adds gauge in kPa. This only adds convertion from psi to bar, not affecting firmware. Co-authored-by: Min --- reference/speeduino.ini | 59 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index cdf32907..9a42d82a 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -25,6 +25,11 @@ ;settingGroup = boostUnits, "Boost table units" ;settingOption = DEFAULT, "kPa" ;settingOption = BOOSTPSI, "PSI" + + settingGroup = pressure_units, "Pressure Display" + settingOption = DEFAULT, "PSI" + settingOption = pressure_bar, "BAR" + settingGroup = enablehardware_test, "Enable Hardware Test Page" settingGroup = resetcontrol_group, "Reset Control Features" @@ -1185,14 +1190,20 @@ page = 10 fuelPressurePin = bits, U08, 136, [0:4], "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "A16", "A17", "A18", "A19", "A20", "A21", "A22", INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID - + #if pressure_bar + fuelPressureMin = scalar, S08, 137, "BAR", 0.0698, 0.0, -7.0, 8.9, 2 ;Note signed int + fuelPressureMax = scalar, U08, 138, "BAR", 0.0698, 0.0, 0.0, 17.8, 2 + oilPressureMin = scalar, S08, 139, "BAR", 0.0698, 0.0, -7.0, 8.9, 2 ;Note signed int + oilPressureMax = scalar, U08, 140, "BAR", 0.0698, 0.0, 0.0, 17.8, 2 + oilPressureProtMins = array, U08, 145, [ 4], "BAR", 0.0698 0.0, 0.0, 17.8, 2 + #else 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 + #endif + oilPressureProtRPM = array, U08, 141, [ 4], "RPM", 100.0, 0.0, 100.0, 25500, 0 wmiEnabled = bits, U08, 149, [0:0], "Off", "On" wmiMode = bits, U08, 149, [1:2], "Simple", "Proportional", "Openloop", "Closedloop" @@ -3044,26 +3055,46 @@ menuDialog = main field = "Enabled", fuelPressureEnable field = "Pin", fuelPressurePin, { fuelPressureEnable } settingSelector = "Common Sensors", { fuelPressureEnable } + #if pressure_bar + settingOption = "0-10 BAR", fuelPressureMin=-1.25, fuelPressureMax=11.25 ; regular sensors give 0.5V to 4.5V for 0 bar to rated bar. Formula Vout = P x 4 / P_rated + 0.5 + settingOption = "0-100 PSI", fuelPressureMin=-0.1, fuelPressureMax=7.1 ; these are just converted psi to bar. Kept because most off-shelf are in PSI + settingOption = "0-150 PSI", fuelPressureMin=-1.25, fuelPressureMax=11.58 + #else settingOption = "0-100 PSI", fuelPressureMin=-3, fuelPressureMax=103 ; Vout = VCC x (P x .97 / 200 + 0.5) settingOption = "0-150 PSI", fuelPressureMin=-18, fuelPressureMax=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 + #endif field = "Pressure at 0v", fuelPressureMin, { fuelPressureEnable } field = "Pressure at 5v", fuelPressureMax, { fuelPressureEnable } dialog = fuelPressureDialog, "Fuel Pressure", xAxis + #if pressure_bar + gauge = fuelPressureBarGauge + #else gauge = fuelPressureGauge + #endif panel = fuelPressureSettings dialog = oilPressureSettings field = "Enabled", oilPressureEnable field = "Pin", oilPressurePin, { oilPressureEnable } settingSelector = "Common Sensors", { oilPressureEnable } + #if pressure_bar + settingOption = "0-10 BAR", oilPressureMin=-1.25, oilPressureMax=11.25 ; regular sensors give 0.5V to 4.5V for 0 bar to rated bar. Formula Vout = P x 4 / P_rated + 0.5 + settingOption = "0-100 PSI", oilPressureMin=-0.1, oilPressureMax=7.1 ; these are just converted psi to bar. Kept because most off-shelf are in PSI + settingOption = "0-150 PSI", oilPressureMin=-1.25, oilPressureMax=11.58 + #else settingOption = "0-100 PSI", oilPressureMin=-3, oilPressureMax=103 ; Vout = VCC x (P x .97 / 200 + 0.5) 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 + #endif field = "Pressure at 0v", oilPressureMin, { oilPressureEnable } field = "Pressure at 5v", oilPressureMax, { oilPressureEnable } dialog = oilPressureDialog, "Oil Pressure", xAxis + #if pressure_bar + gauge = oilPressureBarGauge + #else gauge = oilPressureGauge + #endif panel = oilPressureSettings dialog = pressureSensors, "Pressure Transducers" @@ -4524,9 +4555,13 @@ cmdVSSratio6 = "E\x99\x06" ; Oil Pressure protection curve curve = oil_pressure_prot_curve, "Oil Pressure Protection" - columnLabel = "RPM", "Minimum PSI" + columnLabel = "RPM", "Minimum" xAxis = 0, 8000, 9 - yAxis = 0, 150, 3 + #if pressure_bar + yAxis = 0, 10.0, 3 + #else + yAxis = 0, 150, 3 + #endif xBins = oilPressureProtRPM, rpm yBins = oilPressureProtMins size = 400, 200 @@ -4861,8 +4896,13 @@ cmdVSSratio6 = "E\x99\x06" #endif flexGauge = flex, "Flex sensor", "%", 0, 100, -1, -1, 999, 999, 0, 0 - fuelPressureGauge = fuelPressure, "Fuel Pressure", "PSI", -15, 100, 0, 20, 200, 245, 0, 0 - oilPressureGauge = oilPressure, "Oil Pressure", "PSI", -15, 100, 0, 20, 200, 245, 0, 0 + fuelPressureGauge = fuelPressure, "Fuel Pressure (PSI)", "PSI", -15, 100, 0, 20, 200, 245, 0, 0 + oilPressureGauge = oilPressure, "Oil Pressure (PSI)", "PSI", -15, 100, 0, 20, 200, 245, 0, 0 + fuelPressureBarGauge = fuelPressure_bar,"Fuel Pressure (BAR)", "BAR", -1.0, 7.0, 0.5, 1.4, 14.0, 17.0, 1, 1 + oilPressureBarGauge = oilPressure_bar, "Oil Pressure (BAR)", "BAR", -1.0, 7.0, 0.5, 1.4, 14.0, 17.0, 1, 1 + fuelPressurekPaGauge = fuelPressure_kpa,"Fuel Pressure (kPa)", "kPa", -100, 700, 50, 140, 1400, 1700, 0, 0 + oilPressurekPaGauge = oilPressure_kpa, "Oil Pressure (kPa)", "kPa", -100, 700, 50, 140, 1400, 1700, 0, 0 + gaugeCategory = "Auxiliary Input Channels" AuxInGauge0 = auxin_gauge0, { stringValue(AUXin00Alias) }, "", 0, 1024, -1, -1, 1025, 1025, 0, 0 @@ -5134,6 +5174,11 @@ cmdVSSratio6 = "E\x99\x06" time = { timeNow } seconds = { secl } + fuelPressure_bar = { fuelPressure * 0.06894757 } + oilPressure_bar = { oilPressure * 0.06894757 } + fuelPressure_kpa = { fuelPressure * 6.894757 } + oilPressure_kpa = { oilPressure * 6.894757 } + throttle = { tps }, "%" revolutionTime = { rpm ? ( 60000.0 / rpm) : 0 } From 60dd7d8034f18155b3e805397e5fa3e80ee8369f Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Fri, 8 Jul 2022 22:54:15 +0000 Subject: [PATCH 25/46] Fix typo from last commit --- speeduino/SD_logger.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speeduino/SD_logger.ino b/speeduino/SD_logger.ino index a19525c4..e8f1d485 100644 --- a/speeduino/SD_logger.ino +++ b/speeduino/SD_logger.ino @@ -358,7 +358,7 @@ void checkForSDStart() if((configPage13.onboard_log_trigger_Epin) && (SD_status == SD_STATUS_READY) ) { - if(digitalRead(pinSDEnable) == LOW } + if(digitalRead(pinSDEnable) == LOW) { beginSDLogging(); //Setup the log file, preallocation, header row } From dad1393fe9ba550a68e9ed780017ebcf013af975 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Sat, 9 Jul 2022 16:56:26 +1000 Subject: [PATCH 26/46] Missing commas in ini --- reference/speeduino.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 9a42d82a..88db031f 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -5296,7 +5296,7 @@ cmdVSSratio6 = "E\x99\x06" entry = lambdaTarget, "Lambda Target", float, "%.3f" entry = pulseWidth2, "PW2", float, "%.3f" entry = dutyCycle, "DutyCycle1", float, "%.1f" - entry = TPSdot, "TPS DOT", int, "%d" { aeMode == 0 } + entry = TPSdot, "TPS DOT", int, "%d", { aeMode == 0 } entry = advance, "Advance (Current)",int, "%d" entry = dwell, "Dwell", float, "%.1f" entry = batteryVoltage, "Battery V", float, "%.1f" @@ -5336,7 +5336,7 @@ cmdVSSratio6 = "E\x99\x06" entry = loopsPerSecond, "Loops/s", int, "%d" entry = loopsPerRev, "Loops/rev", int, "%.2f" entry = wmiPW, "WMI Duty Cycle", int, "%d", { wmiEnabled == 1 } - entry = MAPdot, "MAP DOT", int, "%d" { aeMode == 1 } + entry = MAPdot, "MAP DOT", int, "%d", { aeMode == 1 } entry = auxin_gauge0, { stringValue(AUXin00Alias) }, int, "%d", {(caninput_sel0b != 0)} entry = auxin_gauge1, { stringValue(AUXin01Alias) }, int, "%d", { (caninput_sel1b != 0)} From 4938642348de4701626542b33da19ff548233ae8 Mon Sep 17 00:00:00 2001 From: Tjeerd <33102280+Tjeerdie@users.noreply.github.com> Date: Sat, 9 Jul 2022 14:22:18 +0200 Subject: [PATCH 27/46] bug fix EGO PID controller + some improvements. (#879) * Fix for EGO pid * Further improvements on ego PID * Stop EGO controllers from calculating while DFCO is active. To prevent integrator windup. * Fix bug in DFCO enable/disable of the controller Co-authored-by: Tjeerd --- speeduino/corrections.ino | 2 +- speeduino/src/PID_v1/PID_v1.cpp | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/speeduino/corrections.ino b/speeduino/corrections.ino index 72765191..0bcd665a 100644 --- a/speeduino/corrections.ino +++ b/speeduino/corrections.ino @@ -605,7 +605,7 @@ byte correctionAFRClosedLoop() if( (currentStatus.runSecs > configPage6.ego_sdelay) || (configPage2.incorporateAFR == true) ) { currentStatus.afrTarget = get3DTableValue(&afrTable, currentStatus.fuelLoad, currentStatus.RPM); } //Perform the target lookup } - if( configPage6.egoType > 0 ) //egoType of 0 means no O2 sensor + if((configPage6.egoType > 0) & (BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) != 1 ) ) //egoType of 0 means no O2 sensor. If DFCO is active do not run the ego controllers to prevent interator wind-up. { AFRValue = currentStatus.egoCorrection; //Need to record this here, just to make sure the correction stays 'on' even if the nextCycle count isn't ready diff --git a/speeduino/src/PID_v1/PID_v1.cpp b/speeduino/src/PID_v1/PID_v1.cpp index 6d5e8270..139d334a 100755 --- a/speeduino/src/PID_v1/PID_v1.cpp +++ b/speeduino/src/PID_v1/PID_v1.cpp @@ -54,21 +54,21 @@ bool PID::Compute() /*Compute all the working error variables*/ long input = *myInput; long error = *mySetpoint - input; - ITerm += (ki * error)/100; + ITerm += (ki * error); if(ITerm > outMax) ITerm= outMax; - else if(ITerm < outMin) ITerm= outMin; + else if(ITerm < outMin) ITerm = outMin; long dInput = (input - lastInput); /*Compute PID Output*/ - long output = (kp * error)/100 + ITerm- (kd * dInput)/100; + long output = (kp * error) + ITerm- (kd * dInput); if(output > outMax) { output = outMax; } else if(output < outMin) { output = outMin; } - *myOutput = output; + *myOutput = output/1000; /*Remember some variables for next time*/ lastInput = input; - //lastTime = now; + lastTime = now; return true; } //else return false; @@ -90,10 +90,10 @@ void PID::SetTunings(byte Kp, byte Ki, byte Kd) ki = Ki * SampleTimeInSec; kd = Kd / SampleTimeInSec; */ - long InverseSampleTimeInSec = 100000 / SampleTime; + long InverseSampleTimeInSec = 100; kp = Kp; - ki = (Ki * 100) / InverseSampleTimeInSec; - kd = (Kd * InverseSampleTimeInSec) / 100; + ki = Ki; + kd = Kd * 10; if(controllerDirection ==REVERSE) { @@ -129,8 +129,8 @@ void PID::SetSampleTime(int NewSampleTime) void PID::SetOutputLimits(long Min, long Max) { if(Min >= Max) return; - outMin = Min; - outMax = Max; + outMin = Min*1000; + outMax = Max*1000; if(inAuto) { From adac58d8437f627881adcc3c9440a0784cf31380 Mon Sep 17 00:00:00 2001 From: Afroboltski <70011435+Afroboltski@users.noreply.github.com> Date: Mon, 11 Jul 2022 00:38:42 +1200 Subject: [PATCH 28/46] Add necessary pin translations (#887). Fixes #867 --- speeduino/sensors.ino | 2 +- speeduino/speeduino.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/speeduino/sensors.ino b/speeduino/sensors.ino index 6bd9ca1b..5ada90c9 100644 --- a/speeduino/sensors.ino +++ b/speeduino/sensors.ino @@ -79,7 +79,7 @@ void initialiseADC() || (((configPage9.enable_secondarySerial == 0) && ( (configPage9.enable_intcan == 1) && (configPage9.intcan_available == 0) )) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 2) || (((configPage9.enable_secondarySerial == 0) && (configPage9.enable_intcan == 0)) && ((configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 2))) { //if current input channel is enabled as analog local pin check caninput_selxb(bits 2:3) with &12 and caninput_selxa(bits 0:1) with &3 - byte pinNumber = (configPage9.Auxinpina[currentStatus.current_caninchannel]&127); + byte pinNumber = pinTranslateAnalog(configPage9.Auxinpina[currentStatus.current_caninchannel]&63); if( pinIsUsed(pinNumber) ) { //Do nothing here as the pin is already in use. diff --git a/speeduino/speeduino.ino b/speeduino/speeduino.ino index 89486f1b..7e5a35c8 100644 --- a/speeduino/speeduino.ino +++ b/speeduino/speeduino.ino @@ -395,7 +395,7 @@ void loop() { //if current input channel is enabled as analog local pin //read analog channel specified //currentStatus.canin[13] = (configPage9.Auxinpina[currentStatus.current_caninchannel]&63); Dev test use only!127 - currentStatus.canin[currentStatus.current_caninchannel] = readAuxanalog(configPage9.Auxinpina[currentStatus.current_caninchannel]&63); + currentStatus.canin[currentStatus.current_caninchannel] = readAuxanalog(pinTranslateAnalog(configPage9.Auxinpina[currentStatus.current_caninchannel]&63)); } else if ((((configPage9.enable_secondarySerial == 1) || ((configPage9.enable_intcan == 1) && (configPage9.intcan_available == 1))) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&12) == 12) || (((configPage9.enable_secondarySerial == 0) && ( (configPage9.enable_intcan == 1) && (configPage9.intcan_available == 0) )) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 3) From dcd5074ee9394dfdd4a59ac3e1d32e8fc51283d2 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Sun, 10 Jul 2022 23:45:49 +1000 Subject: [PATCH 29/46] Signatures for 202207 --- reference/speeduino.ini | 2 +- speeduino/comms.cpp | 8 ++++---- speeduino/src/PID_v1/PID_v1.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 88db031f..c49273dd 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -7,7 +7,7 @@ MTversion = 2.25 queryCommand = "Q" - signature = "speeduino 202204-dev" + signature = "speeduino 202207" versionInfo = "S" ;This info is what is displayed to user [TunerStudio] diff --git a/speeduino/comms.cpp b/speeduino/comms.cpp index d5b4b17c..28b71ea7 100644 --- a/speeduino/comms.cpp +++ b/speeduino/comms.cpp @@ -451,8 +451,8 @@ void processSerialCommand() case 'Q': // send code version { - char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','4','-','d','e','v'} ; //Note no null terminator in array and statu variable at the start - //char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','4'} ; //Note no null terminator in array and statu variable at the start + //char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','4','-','d','e','v'} ; //Note no null terminator in array and statu variable at the start + char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','7'} ; //Note no null terminator in array and statu variable at the start sendSerialPayload(&productString, sizeof(productString)); break; } @@ -601,8 +601,8 @@ void processSerialCommand() case 'S': // send code version { - byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '.', '0', '4', '-', 'd', 'e', 'v'}; - //byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '0', '2'}; + //byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '.', '0', '4', '-', 'd', 'e', 'v'}; + byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '0', '7'}; sendSerialPayload(&productString, sizeof(productString)); currentStatus.secl = 0; //This is required in TS3 due to its stricter timings break; diff --git a/speeduino/src/PID_v1/PID_v1.cpp b/speeduino/src/PID_v1/PID_v1.cpp index 139d334a..153e8acf 100755 --- a/speeduino/src/PID_v1/PID_v1.cpp +++ b/speeduino/src/PID_v1/PID_v1.cpp @@ -90,7 +90,7 @@ void PID::SetTunings(byte Kp, byte Ki, byte Kd) ki = Ki * SampleTimeInSec; kd = Kd / SampleTimeInSec; */ - long InverseSampleTimeInSec = 100; + //long InverseSampleTimeInSec = 100; kp = Kp; ki = Ki; kd = Kd * 10; From c0c686e0ee39170ca57996efa9f28ed1dd569530 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Mon, 11 Jul 2022 00:11:08 +1000 Subject: [PATCH 30/46] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2427f1ad..b2883f6a 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ [![Build Status](https://img.shields.io/github/workflow/status/noisymime/speeduino/Build%20Firmware)](https://github.com/noisymime/speeduino/actions/workflows/build-firmware.yml) [![Unit Tests](https://img.shields.io/github/workflow/status/noisymime/speeduino/Unit%20Tests?label=Unit%20Tests)](https://github.com/noisymime/speeduino/actions/workflows/unit-tests.yml) [![Open Bounties](https://img.shields.io/bountysource/team/speeduino/activity.svg)](https://www.bountysource.com/teams/speeduino) -[![GitHub commits](https://img.shields.io/github/commits-since/noisymime/speeduino/202108.svg)](https://github.com/noisymime/speeduino/compare/202108...master) +[![GitHub commits](https://img.shields.io/github/commits-since/noisymime/speeduino/202207.svg)](https://github.com/noisymime/speeduino/compare/202207...master) ![MISRA](https://img.shields.io/azure-devops/tests/speeduino/Speeduino/1?label=MISRA&passed_label=warnings&failed_label=violations) -[![Chat on Slack](https://img.shields.io/badge/slack-speeduino-CC2B5E.svg?style=flat&logo=slack)](https://speeduino.com/home/community/slack) +[![Chat on Discord](https://img.shields.io/badge/discord-speeduino-CC2B5E.svg?style=flat&logo=discord)](https://speeduino.com/home/community/discord) ##### A low cost, DIY friendly Engine Management System (ECU) based on the Arduino framework From a8d93bd6cfaa46135a1b58c6c07f5d032a7143a7 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Mon, 11 Jul 2022 07:10:14 +1000 Subject: [PATCH 31/46] Update signatures for 202207 in legacy comms --- speeduino/comms_legacy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/speeduino/comms_legacy.cpp b/speeduino/comms_legacy.cpp index e921ac0e..9818d8c8 100644 --- a/speeduino/comms_legacy.cpp +++ b/speeduino/comms_legacy.cpp @@ -320,7 +320,7 @@ void legacySerialCommand() break; case 'Q': // send code version - Serial.print(F("speeduino 202204-dev")); + Serial.print(F("speeduino 202207")); break; case 'r': //New format for the optimised OutputChannels @@ -352,7 +352,7 @@ void legacySerialCommand() break; case 'S': // send code version - Serial.print(F("Speeduino 2022.04-dev")); + Serial.print(F("Speeduino 2022.07")); currentStatus.secl = 0; //This is required in TS3 due to its stricter timings break; From 4c3a2055b570f216aa91108a7033ec3d1adf15f7 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Wed, 27 Jul 2022 10:01:03 +1000 Subject: [PATCH 32/46] Dev signatures for 202210-dev --- reference/speeduino.ini | 2 +- speeduino/comms.cpp | 8 ++++---- speeduino/comms_legacy.cpp | 6 ++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index c49273dd..0322d632 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -7,7 +7,7 @@ MTversion = 2.25 queryCommand = "Q" - signature = "speeduino 202207" + signature = "speeduino 202210-dev" versionInfo = "S" ;This info is what is displayed to user [TunerStudio] diff --git a/speeduino/comms.cpp b/speeduino/comms.cpp index 28b71ea7..a9eb6098 100644 --- a/speeduino/comms.cpp +++ b/speeduino/comms.cpp @@ -451,8 +451,8 @@ void processSerialCommand() case 'Q': // send code version { - //char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','4','-','d','e','v'} ; //Note no null terminator in array and statu variable at the start - char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','7'} ; //Note no null terminator in array and statu variable at the start + char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','1','0','-','d','e','v'} ; //Note no null terminator in array and statu variable at the start + //char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','7'} ; //Note no null terminator in array and statu variable at the start sendSerialPayload(&productString, sizeof(productString)); break; } @@ -601,8 +601,8 @@ void processSerialCommand() case 'S': // send code version { - //byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '.', '0', '4', '-', 'd', 'e', 'v'}; - byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '0', '7'}; + byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '.', '1', '0', '-', 'd', 'e', 'v'}; + //byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '0', '7'}; sendSerialPayload(&productString, sizeof(productString)); currentStatus.secl = 0; //This is required in TS3 due to its stricter timings break; diff --git a/speeduino/comms_legacy.cpp b/speeduino/comms_legacy.cpp index 9818d8c8..626adbb3 100644 --- a/speeduino/comms_legacy.cpp +++ b/speeduino/comms_legacy.cpp @@ -320,7 +320,8 @@ void legacySerialCommand() break; case 'Q': // send code version - Serial.print(F("speeduino 202207")); + //Serial.print(F("speeduino 202207")); + Serial.print(F("speeduino 202210-dev")); break; case 'r': //New format for the optimised OutputChannels @@ -352,7 +353,8 @@ void legacySerialCommand() break; case 'S': // send code version - Serial.print(F("Speeduino 2022.07")); + //Serial.print(F("Speeduino 2022.07")); + Serial.print(F("Speeduino 2022.10-dev")); currentStatus.secl = 0; //This is required in TS3 due to its stricter timings break; From 055584f06afa327e463254248b42005abe275428 Mon Sep 17 00:00:00 2001 From: DeionSi Date: Wed, 27 Jul 2022 02:08:06 +0200 Subject: [PATCH 33/46] Volatile decoder variables (#902) * triggerToothAngle is modified by interrupts * triggerActualTeeth is never modified in interrupts --- speeduino/crankMaths.ino | 6 ++++-- speeduino/decoders.h | 2 +- speeduino/decoders.ino | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/speeduino/crankMaths.ino b/speeduino/crankMaths.ino index c09c1261..00200400 100644 --- a/speeduino/crankMaths.ino +++ b/speeduino/crankMaths.ino @@ -41,9 +41,10 @@ unsigned long angleToTime(int16_t angle, byte method) { noInterrupts(); unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime); + uint16_t tempTriggerToothAngle = triggerToothAngle; // triggerToothAngle is set by interrupts interrupts(); - returnTime = ( (toothTime * angle) / triggerToothAngle ); + returnTime = ( (toothTime * angle) / tempTriggerToothAngle ); } else { returnTime = angleToTime(angle, CRANKMATH_METHOD_INTERVAL_REV); } //Safety check. This can occur if the last tooth seen was outside the normal pattern etc } @@ -76,9 +77,10 @@ uint16_t timeToAngle(unsigned long time, byte method) { noInterrupts(); unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime); + uint16_t tempTriggerToothAngle = triggerToothAngle; // triggerToothAngle is set by interrupts interrupts(); - returnAngle = ( (unsigned long)(time * triggerToothAngle) / toothTime ); + returnAngle = ( (unsigned long)(time * tempTriggerToothAngle) / toothTime ); } else { returnAngle = timeToAngle(time, CRANKMATH_METHOD_INTERVAL_REV); } //Safety check. This can occur if the last tooth seen was outside the normal pattern etc } diff --git a/speeduino/decoders.h b/speeduino/decoders.h index c968b55b..8ce27001 100644 --- a/speeduino/decoders.h +++ b/speeduino/decoders.h @@ -233,7 +233,7 @@ extern volatile unsigned int secondaryToothCount; //Used for identifying the cur extern volatile unsigned long secondaryLastToothTime; //The time (micros()) that the last tooth was registered (Cam input) extern volatile unsigned long secondaryLastToothTime1; //The time (micros()) that the last tooth was registered (Cam input) -extern volatile uint16_t triggerActualTeeth; +extern uint16_t triggerActualTeeth; extern volatile unsigned long triggerFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) extern volatile unsigned long triggerSecFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) for the secondary input extern volatile bool validTrigger; //Is set true when the last trigger (Primary or secondary) was valid (ie passed filters) diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index c0d4bb6d..bf9c7569 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -76,7 +76,7 @@ volatile unsigned int secondaryToothCount; //Used for identifying the current se volatile unsigned long secondaryLastToothTime = 0; //The time (micros()) that the last tooth was registered (Cam input) volatile unsigned long secondaryLastToothTime1 = 0; //The time (micros()) that the last tooth was registered (Cam input) -volatile uint16_t triggerActualTeeth; +uint16_t triggerActualTeeth; volatile unsigned long triggerFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) volatile unsigned long triggerSecFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) for the secondary input volatile bool validTrigger; //Is set true when the last trigger (Primary or secondary) was valid (ie passed filters) From 6f9368763991026c69437de22a12e912435dbb70 Mon Sep 17 00:00:00 2001 From: Jon Billings Date: Wed, 27 Jul 2022 01:22:04 +0100 Subject: [PATCH 34/46] fix check for DFCO off in correctionAFRclosedLoop() (#899) line 608 has bit-and of configpage6.egotype > 0 & DFCO off. it should be logical and && --- speeduino/corrections.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speeduino/corrections.ino b/speeduino/corrections.ino index 0bcd665a..366554f1 100644 --- a/speeduino/corrections.ino +++ b/speeduino/corrections.ino @@ -605,7 +605,7 @@ byte correctionAFRClosedLoop() if( (currentStatus.runSecs > configPage6.ego_sdelay) || (configPage2.incorporateAFR == true) ) { currentStatus.afrTarget = get3DTableValue(&afrTable, currentStatus.fuelLoad, currentStatus.RPM); } //Perform the target lookup } - if((configPage6.egoType > 0) & (BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) != 1 ) ) //egoType of 0 means no O2 sensor. If DFCO is active do not run the ego controllers to prevent interator wind-up. + if((configPage6.egoType > 0) && (BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) != 1 ) ) //egoType of 0 means no O2 sensor. If DFCO is active do not run the ego controllers to prevent interator wind-up. { AFRValue = currentStatus.egoCorrection; //Need to record this here, just to make sure the correction stays 'on' even if the nextCycle count isn't ready From d22d1c046243cb4bffc2b9b46394f70262a3de35 Mon Sep 17 00:00:00 2001 From: Daniel Tobias Date: Wed, 27 Jul 2022 10:25:54 +1000 Subject: [PATCH 35/46] cl boost control above baro should use logical and/or (#901) --- speeduino/auxiliaries.ino | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/speeduino/auxiliaries.ino b/speeduino/auxiliaries.ino index 9553aa77..60b07633 100644 --- a/speeduino/auxiliaries.ino +++ b/speeduino/auxiliaries.ino @@ -391,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(((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 usually set to boost with wastegate actuator only boost level) + 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 usually 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 ) @@ -437,10 +437,7 @@ void boostControl() currentStatus.boostDuty = configPage15.boostDCWhenDisabled*100; boost_pwm_target_value = ((unsigned long)(currentStatus.boostDuty) * boost_pwm_max_count) / 10000; //Convert boost duty (Which is a % multiplied 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(); - } + if(currentStatus.boostDuty == 0) { boostDisable(); } //If boost control does nothing disable PWM completely } //MAP above boost + hyster } //Open / Cloosed loop From 4a064ad9b4e0e6ce2e623cb16e0477d4791595f3 Mon Sep 17 00:00:00 2001 From: tx_haggis <13982343+adbancroft@users.noreply.github.com> Date: Tue, 26 Jul 2022 22:51:45 -0500 Subject: [PATCH 36/46] libdivide structs can be const - saves a few bytes (#886) --- speeduino/maths.h | 10 +++++----- speeduino/maths.ino | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/speeduino/maths.h b/speeduino/maths.h index 86942753..1f9f69a9 100644 --- a/speeduino/maths.h +++ b/speeduino/maths.h @@ -10,11 +10,11 @@ inline long powint(int, unsigned int); #ifdef USE_LIBDIVIDE #include "src/libdivide/libdivide.h" -extern struct libdivide::libdivide_u16_t libdiv_u16_100; -extern struct libdivide::libdivide_s16_t libdiv_s16_100; -extern struct libdivide::libdivide_u32_t libdiv_u32_100; -extern struct libdivide::libdivide_s32_t libdiv_s32_100; -extern struct libdivide::libdivide_u32_t libdiv_u32_360; +extern const struct libdivide::libdivide_u16_t libdiv_u16_100; +extern const struct libdivide::libdivide_s16_t libdiv_s16_100; +extern const struct libdivide::libdivide_u32_t libdiv_u32_100; +extern const struct libdivide::libdivide_s32_t libdiv_s32_100; +extern const struct libdivide::libdivide_u32_t libdiv_u32_360; #endif inline uint8_t div100(uint8_t n) { diff --git a/speeduino/maths.ino b/speeduino/maths.ino index 00c7f699..186d6df9 100644 --- a/speeduino/maths.ino +++ b/speeduino/maths.ino @@ -6,13 +6,13 @@ // Constants used for libdivide. Using predefined constants saves flash and RAM (.bss) // versus calling the libdivide generator functions (E.g. libdivide_s32_gen) -libdivide::libdivide_s16_t libdiv_s16_100 = { .magic = S16_MAGIC(100), .more = S16_MORE(100) }; -libdivide::libdivide_u16_t libdiv_u16_100 = { .magic = U16_MAGIC(100), .more = U16_MORE(100) }; +const libdivide::libdivide_s16_t libdiv_s16_100 = { .magic = S16_MAGIC(100), .more = S16_MORE(100) }; +const libdivide::libdivide_u16_t libdiv_u16_100 = { .magic = U16_MAGIC(100), .more = U16_MORE(100) }; // 32-bit constants generated here: https://godbolt.org/z/vP8Kfejo9 -libdivide::libdivide_u32_t libdiv_u32_100 = { .magic = 2748779070, .more = 6 }; -libdivide::libdivide_s32_t libdiv_s32_100 = { .magic = 1374389535, .more = 5 }; -libdivide::libdivide_u32_t libdiv_u32_200 = { .magic = 2748779070, .more = 7 }; -libdivide::libdivide_u32_t libdiv_u32_360 = { .magic = 1813430637, .more = 72 }; +const libdivide::libdivide_u32_t libdiv_u32_100 = { .magic = 2748779070, .more = 6 }; +const libdivide::libdivide_s32_t libdiv_s32_100 = { .magic = 1374389535, .more = 5 }; +const libdivide::libdivide_u32_t libdiv_u32_200 = { .magic = 2748779070, .more = 7 }; +const libdivide::libdivide_u32_t libdiv_u32_360 = { .magic = 1813430637, .more = 72 }; #endif //Replace the standard arduino map() function to use the div function instead From 1c093a01fea284e9f20edda73a2fd43d1f0118bc Mon Sep 17 00:00:00 2001 From: a32guy Date: Wed, 27 Jul 2022 20:22:42 -0400 Subject: [PATCH 37/46] Add OLCL mode to initBoard() for teensy (#903) Co-authored-by: csmergs --- speeduino/board_teensy35.ino | 2 +- speeduino/board_teensy41.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/speeduino/board_teensy35.ino b/speeduino/board_teensy35.ino index b6cd84f5..0ca5e99a 100644 --- a/speeduino/board_teensy35.ino +++ b/speeduino/board_teensy35.ino @@ -23,7 +23,7 @@ void initBoard() *********************************************************************************************************** * Idle */ - if ((configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL)) + if ((configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL)) { //FlexTimer 2, compare channel 0 is used for idle FTM2_MODE |= FTM_MODE_WPDIS; // Write Protection Disable diff --git a/speeduino/board_teensy41.ino b/speeduino/board_teensy41.ino index 1cb1965d..00efecad 100644 --- a/speeduino/board_teensy41.ino +++ b/speeduino/board_teensy41.ino @@ -35,7 +35,7 @@ void initBoard() *********************************************************************************************************** * Idle */ - if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) ) + if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL)) { PIT_TCTRL0 = 0; PIT_TCTRL0 |= PIT_TCTRL_TIE; // enable Timer 1 interrupts From 148d440f6b3e39c8cbfe87f51ba73779ac376800 Mon Sep 17 00:00:00 2001 From: Tjeerd <33102280+Tjeerdie@users.noreply.github.com> Date: Tue, 2 Aug 2022 09:10:29 +0200 Subject: [PATCH 38/46] Fix for idle PWM on STM32. Enable idle timer when idle pwm is enabled. Fixes #907 Co-authored-by: Tjeerd --- speeduino/board_stm32_official.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speeduino/board_stm32_official.h b/speeduino/board_stm32_official.h index 9e2b83d0..969313e5 100644 --- a/speeduino/board_stm32_official.h +++ b/speeduino/board_stm32_official.h @@ -266,7 +266,7 @@ extern "C" char* sbrk(int incr); #define IDLE_COUNTER (TIM1)->CNT #define IDLE_COMPARE (TIM1)->CCR4 -#define IDLE_TIMER_ENABLE() (TIM1)->SR = ~TIM_FLAG_CC4; (TIM1)->DIER |= TIM_DIER_CC4IE +#define IDLE_TIMER_ENABLE() (TIM1)->SR = ~TIM_FLAG_CC4; (TIM1)->DIER |= TIM_DIER_CC4IE; (TIM1)->CR1 |= TIM_CR1_CEN; #define IDLE_TIMER_DISABLE() (TIM1)->DIER &= ~TIM_DIER_CC4IE /* From 1a3e1cc78229a131e280956522efe2c7fffbcad9 Mon Sep 17 00:00:00 2001 From: Pasi Kemppainen <48950874+pazi88@users.noreply.github.com> Date: Wed, 10 Aug 2022 04:06:28 +0300 Subject: [PATCH 39/46] Disable automatic retransmission (#910) --- speeduino/src/STM32_CAN/STM32_CAN.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/speeduino/src/STM32_CAN/STM32_CAN.h b/speeduino/src/STM32_CAN/STM32_CAN.h index 1cf19da9..0ea2e6d7 100644 --- a/speeduino/src/STM32_CAN/STM32_CAN.h +++ b/speeduino/src/STM32_CAN/STM32_CAN.h @@ -109,8 +109,8 @@ class STM32_CAN { public: // Default buffer sizes are set to 16. But this can be changed by using constructor in main code. STM32_CAN(CAN_TypeDef* canPort, CAN_PINS pins, RXQUEUE_TABLE rxSize = RX_SIZE_16, TXQUEUE_TABLE txSize = TX_SIZE_16); - // Begin. By default the automatic retransmission is enabled. If it causes problems, use begin(false) to disable it. - void begin(bool retransmission = true); + // Begin. By default the automatic retransmission is disabled in Speeduino, because it has been observed to cause sync issues. + void begin(bool retransmission = false); void setBaudRate(uint32_t baud); bool write(CAN_message_t &CAN_tx_msg, bool sendMB = false); bool read(CAN_message_t &CAN_rx_msg); From a3ccf41e438e891968b9ab02321eb3010c72f52d Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Wed, 10 Aug 2022 12:12:42 +1000 Subject: [PATCH 40/46] Allow for float values in SD log where supported with FPU --- speeduino/SD_logger.ino | 8 +++++++- speeduino/board_avr2560.h | 1 + speeduino/board_same51.h | 1 + speeduino/board_stm32_generic.h | 1 + speeduino/board_stm32_official.h | 1 + speeduino/board_teensy35.h | 1 + speeduino/board_teensy41.h | 1 + speeduino/board_template.h | 1 + speeduino/logger.h | 3 +++ speeduino/logger.ino | 33 +++++++++++++++++++++++++++++++- speeduino/maths.h | 1 + 11 files changed, 50 insertions(+), 2 deletions(-) diff --git a/speeduino/SD_logger.ino b/speeduino/SD_logger.ino index e8f1d485..1b9b05fa 100644 --- a/speeduino/SD_logger.ino +++ b/speeduino/SD_logger.ino @@ -242,7 +242,13 @@ void writeSDLogEntry() //Write the line to the ring buffer for(byte x=0; x= 32 + float entryValue = getReadableFloatLogEntry(x); + if(IS_INTEGER(entryValue)) { rb.print((uint16_t)entryValue); } + else { rb.print(entryValue); } + #else + rb.print(getReadableLogEntry(x)); + #endif if(x < (SD_LOG_NUM_FIELDS - 1)) { rb.print(","); } } rb.println(""); diff --git a/speeduino/board_avr2560.h b/speeduino/board_avr2560.h index b22339a7..3cea1d21 100644 --- a/speeduino/board_avr2560.h +++ b/speeduino/board_avr2560.h @@ -14,6 +14,7 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE (256+7+1) //Size of the serial buffer used by new comms protocol. The largest single packet is the O2 calibration which is 256 bytes + 7 bytes of overhead + #define FPU_MAX_SIZE 0 //Size of the FPU buffer. 0 means no FPU. #ifdef USE_SPI_EEPROM #define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h" typedef uint16_t eeprom_address_t; diff --git a/speeduino/board_same51.h b/speeduino/board_same51.h index 64eeae2f..e2d8b54f 100644 --- a/speeduino/board_same51.h +++ b/speeduino/board_same51.h @@ -17,6 +17,7 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE 257 //Size of the serial buffer used by new comms protocol. Additional 1 byte is for flag + #define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. #ifdef USE_SPI_EEPROM #define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h" typedef uint16_t eeprom_address_t; diff --git a/speeduino/board_stm32_generic.h b/speeduino/board_stm32_generic.h index 0b301359..ce98e3cd 100644 --- a/speeduino/board_stm32_generic.h +++ b/speeduino/board_stm32_generic.h @@ -11,6 +11,7 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) + #define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. #define TIMER_RESOLUTION 2 #define micros_safe() micros() //timer5 method is not used on anything but AVR, the micros_safe() macro is simply an alias for the normal micros() #if defined(SRAM_AS_EEPROM) diff --git a/speeduino/board_stm32_official.h b/speeduino/board_stm32_official.h index 969313e5..47dca806 100644 --- a/speeduino/board_stm32_official.h +++ b/speeduino/board_stm32_official.h @@ -25,6 +25,7 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) +#define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. #define micros_safe() micros() //timer5 method is not used on anything but AVR, the micros_safe() macro is simply an alias for the normal micros() #define TIMER_RESOLUTION 4 diff --git a/speeduino/board_teensy35.h b/speeduino/board_teensy35.h index 88dcf0b1..45e0d789 100644 --- a/speeduino/board_teensy35.h +++ b/speeduino/board_teensy35.h @@ -16,6 +16,7 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) + #define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. #define SD_LOGGING //SD logging enabled by default for Teensy 3.5 as it has the slot built in #define BOARD_MAX_DIGITAL_PINS 34 #define BOARD_MAX_IO_PINS 34 //digital pins + analog channels + 1 diff --git a/speeduino/board_teensy41.h b/speeduino/board_teensy41.h index bfbe8017..2e489725 100644 --- a/speeduino/board_teensy41.h +++ b/speeduino/board_teensy41.h @@ -16,6 +16,7 @@ #define COMPARE_TYPE uint32_t #define COUNTER_TYPE uint32_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) + #define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. #define BOARD_MAX_DIGITAL_PINS 34 #define BOARD_MAX_IO_PINS 34 //digital pins + analog channels + 1 #define EEPROM_LIB_H diff --git a/speeduino/board_template.h b/speeduino/board_template.h index 71cccc3b..cdaf6c5d 100644 --- a/speeduino/board_template.h +++ b/speeduino/board_template.h @@ -9,6 +9,7 @@ #define PORT_TYPE uint32_t //Size of the port variables (Eg inj1_pin_port). Most systems use a byte, but SAMD21 and possibly others are a 32-bit unsigned int #define PINMASK_TYPE uint32_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) + #define FPU_MAX_SIZE 0 //Size of the FPU buffer. 0 means no FPU. #define BOARD_MAX_IO_PINS 52 //digital pins + analog channels + 1 #define BOARD_MAX_DIGITAL_PINS 52 //Pretty sure this isn't right #define EEPROM_LIB_H //The name of the file that provides the EEPROM class diff --git a/speeduino/logger.h b/speeduino/logger.h index 8ad2826b..28ddcfbf 100644 --- a/speeduino/logger.h +++ b/speeduino/logger.h @@ -23,6 +23,9 @@ byte getTSLogEntry(uint16_t); int16_t getReadableLogEntry(uint16_t); +#if FPU_MAX_SIZE >= 32 + float getReadableFloatLogEntry(uint16_t); +#endif bool is2ByteEntry(uint8_t); // This array indicates which index values from the log are 2 byte values diff --git a/speeduino/logger.ino b/speeduino/logger.ino index 8442ed83..13c74120 100644 --- a/speeduino/logger.ino +++ b/speeduino/logger.ino @@ -195,7 +195,7 @@ int16_t getReadableLogEntry(uint16_t logIndex) case 11: statusValue = currentStatus.iatCorrection; break; //Air temperature Correction (%) case 12: statusValue = currentStatus.wueCorrection; break; //Warmup enrichment (%) case 13: statusValue = currentStatus.RPM; break; //rpm HB - case 14: statusValue = currentStatus.AEamount; break; //TPS acceleration enrichment (%) divided by 2 (Can exceed 255) + case 14: statusValue = currentStatus.AEamount; break; //TPS acceleration enrichment (%) case 15: statusValue = currentStatus.corrections; break; //Total GammaE (%) case 16: statusValue = currentStatus.VE1; break; //VE 1 (%) case 17: statusValue = currentStatus.VE2; break; //VE 2 (%) @@ -290,6 +290,37 @@ int16_t getReadableLogEntry(uint16_t logIndex) return statusValue; } +/** + * An expansion to the @ref getReadableLogEntry function for systems that have an FPU. It will provide a floating point value for any parameter that this is appropriate for, otherwise will return the result of @ref getReadableLogEntry. + * See logger.h for the field names and order + * @param logIndex - The log index required. Note that this is NOT the byte number, but the index in the log + * @return float value of the requested log entry. + */ +#if FPU_MAX_SIZE >= 32 +float getReadableFloatLogEntry(uint16_t logIndex) +{ + float statusValue = 0.0; + + switch(logIndex) + { + case 8: statusValue = currentStatus.battery10 / 10.0; break; //battery voltage + case 9: statusValue = currentStatus.O2 / 10.0; break; + case 18: statusValue = currentStatus.afrTarget / 10.0; break; + case 21: statusValue = currentStatus.TPS / 2.0; break; // TPS (0% to 100% = 0 to 200) + case 33: statusValue = currentStatus.O2_2 / 10.0; break; //O2 + + case 53: statusValue = currentStatus.PW1 / 1000.0; break; //Pulsewidth 1 Have to convert from uS to mS. + case 54: statusValue = currentStatus.PW2 / 1000.0; break; //Pulsewidth 2 Have to convert from uS to mS. + case 55: statusValue = currentStatus.PW3 / 1000.0; break; //Pulsewidth 3 Have to convert from uS to mS. + case 56: statusValue = currentStatus.PW4 / 1000.0; break; //Pulsewidth 4 Have to convert from uS to mS. + + default: statusValue = getReadableLogEntry(logIndex); break; //If logIndex value is NOT a float based one, use the regular function + } + + return statusValue; +} +#endif + /** * Searches the log 2 byte array to determine whether a given index is a regular single byte or a 2 byte field * Uses a boundless binary search for improved performance, but requires the fsIntIndex to remain in order diff --git a/speeduino/maths.h b/speeduino/maths.h index 1f9f69a9..3c447e28 100644 --- a/speeduino/maths.h +++ b/speeduino/maths.h @@ -71,6 +71,7 @@ inline uint32_t div360(uint32_t n) { } #define DIV_ROUND_CLOSEST(n, d) ((((n) < 0) ^ ((d) < 0)) ? (((n) - (d)/2)/(d)) : (((n) + (d)/2)/(d))) +#define IS_INTEGER(d) (d == (int32_t)d) //This is a dedicated function that specifically handles the case of mapping 0-1023 values into a 0 to X range //This is a common case because it means converting from a standard 10-bit analog input to a byte or 10-bit analog into 0-511 (Eg the temperature readings) From 509edbae22c982ece5702e148b7372dae88e9189 Mon Sep 17 00:00:00 2001 From: Josh Stewart Date: Tue, 16 Aug 2022 10:45:27 +1000 Subject: [PATCH 41/46] Increase most F temp field max values to 419F --- reference/speeduino.ini | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 0322d632..4fe2afb8 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -288,7 +288,7 @@ page = 1 #if CELSIUS aeColdTaperMin= scalar, U08, 2, "C", 1.0, -40, -40, 215, 0 ;AE cold adjustment, taper start clt (full adjustment) #else - aeColdTaperMin= scalar, U08, 2, "F", 1.8, -22.23, -40, 215, 0 ;AE cold adjustment, taper start clt (full adjustment) + aeColdTaperMin= scalar, U08, 2, "F", 1.8, -22.23, -40, 419, 0 ;AE cold adjustment, taper start clt (full adjustment) #endif aeMode = bits, U08, 3, [0:1], "TPS", "MAP", "INVALID", "INVALID" @@ -353,7 +353,7 @@ page = 1 #if CELSIUS aeColdTaperMax = scalar, U08, 39, "C", 1.0, -40, -40, 215, 0 ;AE cold adjustment, taper start clt (full adjustment) #else - aeColdTaperMax = scalar, U08, 39, "F", 1.8, -22.23, -40, 215, 0 ;AE cold adjustment, taper end clt (no adjustment) + aeColdTaperMax = scalar, U08, 39, "F", 1.8, -22.23, -40, 419, 0 ;AE cold adjustment, taper end clt (no adjustment) #endif dutyLim = scalar, U08, 40, "%", 1.0, 0.0, 0.0, 95.0, 0 @@ -399,13 +399,13 @@ page = 1 #if CELSIUS aseBins = array, U08, 79, [4], "C", 1.0, -40, -40, 215, 0 #else - aseBins = array, U08, 79, [4], "F", 1.8, -22.23, -40, 215, 0 + aseBins = array, U08, 79, [4], "F", 1.8, -22.23, -40, 419, 0 #endif primePulse = array, U08, 83, [4], "ms", 0.5, 0.0, 0.0, 127.5, 1 #if CELSIUS primeBins = array, U08, 87, [4], "C", 1.0, -40, -40, 215, 0 #else - primeBins = array, U08, 87, [4], "F", 1.8, -22.23, -40, 215, 0 + primeBins = array, U08, 87, [4], "F", 1.8, -22.23, -40, 419, 0 #endif CTPSPin = bits, U08, 91, [0:5], "Board Default", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID" CTPSPolarity = bits, U08, 91, [6:6], "Normal", "Inverted" @@ -423,7 +423,7 @@ page = 1 #if CELSIUS dfcoMinCLT = scalar, U08, 101, "C", 1.0, -40, -40, 215, 0 #else - dfcoMinCLT = scalar, U08, 101, "F", 1.8, -22.23, -40, 215, 0 + dfcoMinCLT = scalar, U08, 101, "F", 1.8, -22.23, -40, 419, 0 #endif ;VSS settings @@ -605,7 +605,7 @@ page = 4 #if CELSIUS vvtMinClt = scalar, U08, 126, "C", 1.0, -40, -40, 215, 0 #else - vvtMinClt = scalar, U08, 126, "F", 1.8, -22.23, -40, 215, 0 + vvtMinClt = scalar, U08, 126, "F", 1.8, -22.23, -40, 419, 0 #endif vvtDelay = scalar, U08, 127, "S", 5.0, 0.0, 0, 1275, 0 @@ -640,7 +640,7 @@ page = 6 #if CELSIUS egoTemp = scalar, U08, 4, "C", 1.0, -40, -40, 102.0, 0 #else - egoTemp = scalar, U08, 4, "F", 1.8, -22.23, -40, 215.0, 0 + egoTemp = scalar, U08, 4, "F", 1.8, -22.23, -40, 419.0, 0 #endif egoCount = scalar, U08, 5, "", 4.0, 0.0, 4.0, 255.0, 0 ; * ( 1 byte) vvtMode = bits, U08, 6, [0:1], "On/Off", "Open Loop", "Closed loop", "INVALID" @@ -666,7 +666,7 @@ page = 6 #if CELSIUS airDenBins = array, U08, 27, [9], "C", 1.0, -40, -40, 215, 0 ; Bins for the air density correction curve #else - airDenBins = array, U08, 27, [9], "F", 1.8, -22.23, -40, 215, 0 ; Bins for the air density correction curve + airDenBins = array, U08, 27, [9], "F", 1.8, -22.23, -40, 419, 0 ; Bins for the air density correction curve #endif airDenRates = array, U08, 36, [9], "%", 1.0, 0.0, 0, 255, 0 ; Values for the air density correction curve @@ -711,14 +711,14 @@ page = 6 #if CELSIUS iacBins = array, U08, 94, [10], "C", 1.0, -40, -40, 215, 0 #else - iacBins = array, U08, 94, [10], "F", 1.8, -22.23, -40, 215, 0 + iacBins = array, U08, 94, [10], "F", 1.8, -22.23, -40, 419, 0 #endif iacCrankSteps= array, U08, 104, [4], "Steps", 3, 0, 0, 765, 0 iacCrankDuty = array, U08, 108, [4], "Duty %", 1.0, 0, 0, 100, 0 #if CELSIUS iacCrankBins = array, U08, 112, [4], "C", 1.0, -40, -40, 215, 0 #else - iacCrankBins = array, U08, 112, [4], "F", 1.8, -22.23, -40, 215, 0 + iacCrankBins = array, U08, 112, [4], "F", 1.8, -22.23, -40, 419, 0 #endif iacAlgorithm = bits , U08, 116, [0:2], "None", "On/Off", "PWM Open loop", "PWM Closed loop", "Stepper Open Loop", "Stepper Closed Loop", "PWM Closed+Open loop", "Stepper Closed+Open loop" @@ -729,7 +729,7 @@ page = 6 #if CELSIUS iacFastTemp = scalar, U08, 117, "C", 1.0, -40, -40, 215, 0 #else - iacFastTemp = scalar, U08, 117, "F", 1.8, -22.23, -40, 215, 0 + iacFastTemp = scalar, U08, 117, "F", 1.8, -22.23, -40, 419, 0 #endif iacStepHome = scalar, U08, 118, "Steps", 3, 0, 0, 765, 0 @@ -743,14 +743,14 @@ page = 6 fanSP = scalar, U08, 121, "C", 1.0, -40, -40, 215.0, 0 fanHyster = scalar, U08, 122, "C", 1.0, 0.0, 0.0, 40, 0 #else - fanSP = scalar, U08, 121, "F", 1.8, -22.23, -40, 215.0, 0 + fanSP = scalar, U08, 121, "F", 1.8, -22.23, -40, 419.0, 0 fanHyster = scalar, U08, 122, "F", 1.0, 0.0, 0.0, 40, 0 #endif fanFreq = scalar, U08 , 123, "Hz", 2.0, 0.0, 10, 511, 0 #if CELSIUS fanPWMBins = array, U08, 124, [4], "C", 1.0, -40, -40, 215, 0 #else - fanPWMBins = array, U08, 124, [4], "F", 1.8, -22.23, -40, 215, 0 + fanPWMBins = array, U08, 124, [4], "F", 1.8, -22.23, -40, 419, 0 #endif ;-------------------------------------------------- @@ -1058,7 +1058,7 @@ page = 9 #if CELSIUS coolantProtTemp = array, U08, 173, [6], "C", 1.0, -40, -40, 215, 0 #else - coolantProtTemp = array, U08, 173, [6], "F", 1.8, -22.23, -40, 215, 0 + 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 @@ -1080,7 +1080,7 @@ page = 10 #if CELSIUS crankingEnrichBins = array, U08, 0, [4], "C", 1.0, -40, -40, 215, 0 #else - crankingEnrichBins = array, U08, 0, [4], "F", 1.8, -22.23, -40, 215, 0 + crankingEnrichBins = array, U08, 0, [4], "F", 1.8, -22.23, -40, 419, 0 #endif crankingEnrichValues= array, U08, 4, [4], "%", 5.0, 0.0, 0, 1275, 0 ; Values for the cranking enrichment curve @@ -1111,7 +1111,7 @@ page = 10 #if CELSIUS n2o_minCLT = scalar, U08, 76, "C", 1.0, -40, -40, 215, 0 #else - n2o_minCLT = scalar, U08, 76, "F", 1.8, -22.23, -40, 215, 0 + n2o_minCLT = scalar, U08, 76, "F", 1.8, -22.23, -40, 419, 0 #endif n2o_maxMAP = scalar, U08, 77, "kPa", 2.0, 0.0, 0.0, 511.0, 0 n2o_minTPS = scalar, U08, 78, "%TPS", 0.5, 0.0, 0.0, 100.0, 1 @@ -1217,7 +1217,7 @@ page = 10 #if CELSIUS wmiIAT = scalar, U08, 154, "C", 1.0, -40, -40, 215, 0 #else - wmiIAT = scalar, U08, 154, "F", 1.8, -22.23, -40, 215, 0 + wmiIAT = scalar, U08, 154, "F", 1.8, -22.23, -40, 419, 0 #endif wmiOffset = scalar, S08, 155, "ms", 1.0, 0.0, -12.7, 12.7, 0 ;Note signed int @@ -1245,7 +1245,7 @@ page = 10 #if CELSIUS fuelTempBins = array, U08, 174, [6], "C", 1.0, -40, -40, 215, 0 #else - fuelTempBins = array, U08, 174, [6], "F", 1.8, -22.23, -40, 215, 0 + fuelTempBins = array, U08, 174, [6], "F", 1.8, -22.23, -40, 419, 0 #endif fuelTempValues = array, U08, 180, [6], "%", 1.0, 0.0, 0, 255, 0 From f485eb6dcca981d082c0fc8831e322df8dde5cbe Mon Sep 17 00:00:00 2001 From: Mike501 Date: Wed, 24 Aug 2022 20:34:07 +0100 Subject: [PATCH 42/46] Revert "Merge branch 'master' into DoubleMissing" This reverts commit bda3d89bf553df40951167870c826792ba92a715. --- .github/workflows/build-firmware.yml | 16 +- .github/workflows/doxygen.yml | 17 +- .github/workflows/unit-tests.yml | 6 +- README.md | 4 +- platformio.ini | 5 +- reference/speeduino.ini | 516 ++++++++-------------- speeduino/SD_logger.ino | 27 +- speeduino/auxiliaries.ino | 13 +- speeduino/board_avr2560.h | 1 - speeduino/board_same51.h | 1 - speeduino/board_stm32_generic.h | 1 - speeduino/board_stm32_official.h | 43 +- speeduino/board_stm32_official.ino | 34 +- speeduino/board_teensy35.h | 1 - speeduino/board_teensy35.ino | 2 +- speeduino/board_teensy41.h | 6 +- speeduino/board_teensy41.ino | 8 +- speeduino/board_template.h | 1 - speeduino/canBroadcast.ino | 4 +- speeduino/cancomms.ino | 4 +- speeduino/comms.cpp | 10 +- speeduino/comms.h | 2 +- speeduino/comms_legacy.cpp | 11 +- speeduino/corrections.ino | 143 ++++-- speeduino/crankMaths.ino | 16 +- speeduino/decoders.h | 2 +- speeduino/decoders.ino | 6 +- speeduino/engineProtection.h | 1 + speeduino/engineProtection.ino | 93 +--- speeduino/globals.h | 70 +-- speeduino/globals.ino | 74 ---- speeduino/idle.h | 2 +- speeduino/idle.ino | 4 +- speeduino/init.ino | 67 +-- speeduino/int16_byte.h | 7 +- speeduino/logger.h | 3 - speeduino/logger.ino | 33 +- speeduino/maths.h | 11 +- speeduino/maths.ino | 12 +- speeduino/pages.cpp | 9 +- speeduino/pages.h | 30 +- speeduino/rtc_common.ino | 8 +- speeduino/scheduledIO.h | 3 - speeduino/scheduledIO.ino | 35 +- speeduino/scheduler.h | 2 +- speeduino/scheduler.ino | 23 +- speeduino/sensors.h | 3 + speeduino/sensors.ino | 8 +- speeduino/speeduino.h | 1 + speeduino/speeduino.ino | 9 +- speeduino/src/PID_v1/PID_v1.cpp | 40 +- speeduino/src/PID_v1/PID_v1.h | 4 - speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp | 8 - speeduino/src/STM32_CAN/STM32_CAN.h | 4 +- speeduino/storage.cpp | 185 ++++---- speeduino/storage.h | 15 +- speeduino/timers.h | 2 +- speeduino/timers.ino | 14 +- speeduino/updates.ino | 81 +--- test/test_decoders/test_decoders.cpp | 1 - test/test_fuel/test_corrections.cpp | 144 +----- test/test_fuel/test_corrections.h | 3 +- 62 files changed, 594 insertions(+), 1315 deletions(-) diff --git a/.github/workflows/build-firmware.yml b/.github/workflows/build-firmware.yml index a5d2f6f1..fafea9cd 100644 --- a/.github/workflows/build-firmware.yml +++ b/.github/workflows/build-firmware.yml @@ -34,17 +34,11 @@ jobs: python -m pip install --upgrade pip pip install --upgrade platformio - - name: Build test atmel - run: platformio run -e megaatmega2560 -e megaatmega2561 - - - name: Build test teensy - run: platformio run -e teensy35 -e teensy36 -e teensy41 - - - name: Build test STM32 - run: platformio run -e black_F407VE -e BlackPill_F401CC -e BlackPill_F411CE_USB + - name: Run PlatformIO + run: platformio run -e teensy35 -e teensy36 -e teensy41 -e black_F407VE -e megaatmega2561 -e megaatmega2560 - name: Upload to Speeduino server - if: github.event_name != 'pull_request' && github.repository_owner == 'noisymime' + if: github.event_name != 'pull_request' env: WEB_PWD: ${{ secrets.WEB_PWD }} run: | @@ -57,7 +51,7 @@ jobs: - name: Slack Notification (Passed) uses: rtCamp/action-slack-notify@v2 - if: success() && github.event_name != 'pull_request' && github.repository_owner == 'noisymime' + if: success() && github.event_name != 'pull_request' env: SLACK_CHANNEL: git SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff' @@ -69,7 +63,7 @@ jobs: - name: Slack Notification (Failed) uses: rtCamp/action-slack-notify@v2 - if: failure() && github.event_name != 'pull_request' && github.repository_owner == 'noisymime' + if: failure() && github.event_name != 'pull_request' env: SLACK_CHANNEL: git SLACK_COLOR: ${{ job.status }} # or a specific color like 'good' or '#ff00ff' diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index c4ba4823..23e38f8d 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -1,4 +1,6 @@ -name: Build and update Doxygen documentation +# This is a basic workflow to help you get started with Actions + +name: Doxygen Action # Controls when the action will run. Triggers the workflow on push or pull request # events but only for the master branch @@ -6,6 +8,8 @@ on: push: branches: [ master ] + + # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "build" @@ -18,20 +22,21 @@ jobs: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 - - name: Build Doxygen documentation - uses: mattnotmitt/doxygen-action@v1.9 + - name: Doxygen Action + uses: mattnotmitt/doxygen-action@v1.1.0 with: + # Path to Doxyfile doxyfile-path: "./Doxyfile" # default is ./Doxyfile + # Working directory working-directory: "." # default is . - name: Setup git config - if: github.repository_owner == 'noisymime' run: | git config --global user.name "GitHub Actions Bot" git config --global user.email "<>" - - name: Commit updated Doxygen documentation - if: github.event_name != 'pull_request' && github.repository_owner == 'noisymime' + - name: Commit Doxygen HTML + if: github.event_name != 'pull_request' env: GH_DOXYGEN: ${{ secrets.GH_DOXYGEN }} run: | diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index d18fcd1f..2c57852d 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -1,3 +1,5 @@ +# This is a basic workflow to help you get started with Actions + name: Unit Tests # Controls when the workflow will run @@ -11,8 +13,6 @@ on: jobs: build: - # Only try to run hardware unit tests on the upstream repository - if: github.repository_owner == 'noisymime' runs-on: ubuntu-latest @@ -67,4 +67,4 @@ jobs: SLACK_TITLE: 'Unit tests FAILED :warning:' SLACK_USERNAME: Github SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} - MSG_MINIMAL: actions url,commit + MSG_MINIMAL: actions url,commit \ No newline at end of file diff --git a/README.md b/README.md index b2883f6a..2427f1ad 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ [![Build Status](https://img.shields.io/github/workflow/status/noisymime/speeduino/Build%20Firmware)](https://github.com/noisymime/speeduino/actions/workflows/build-firmware.yml) [![Unit Tests](https://img.shields.io/github/workflow/status/noisymime/speeduino/Unit%20Tests?label=Unit%20Tests)](https://github.com/noisymime/speeduino/actions/workflows/unit-tests.yml) [![Open Bounties](https://img.shields.io/bountysource/team/speeduino/activity.svg)](https://www.bountysource.com/teams/speeduino) -[![GitHub commits](https://img.shields.io/github/commits-since/noisymime/speeduino/202207.svg)](https://github.com/noisymime/speeduino/compare/202207...master) +[![GitHub commits](https://img.shields.io/github/commits-since/noisymime/speeduino/202108.svg)](https://github.com/noisymime/speeduino/compare/202108...master) ![MISRA](https://img.shields.io/azure-devops/tests/speeduino/Speeduino/1?label=MISRA&passed_label=warnings&failed_label=violations) -[![Chat on Discord](https://img.shields.io/badge/discord-speeduino-CC2B5E.svg?style=flat&logo=discord)](https://speeduino.com/home/community/discord) +[![Chat on Slack](https://img.shields.io/badge/slack-speeduino-CC2B5E.svg?style=flat&logo=slack)](https://speeduino.com/home/community/slack) ##### A low cost, DIY friendly Engine Management System (ECU) based on the Arduino framework diff --git a/platformio.ini b/platformio.ini index 2fd48f4a..1147475b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,8 +15,7 @@ framework=arduino build_unflags = -Os build_flags = -O3 -ffast-math -fshort-enums -funroll-loops -Wall -Wextra -std=c99 lib_deps = EEPROM, Time -;test_build_project_src = true -test_build_src = yes +test_build_project_src = true debug_tool = simavr test_ignore = test_table3d_native @@ -27,7 +26,7 @@ framework=arduino build_unflags = -Os build_flags = -O3 -ffast-math -Wall -Wextra -std=c99 lib_deps = EEPROM, Time -test_build_src = yes +test_build_project_src = true [env:teensy35] ;platform=teensy diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 4fe2afb8..9e4ab026 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -7,7 +7,7 @@ MTversion = 2.25 queryCommand = "Q" - signature = "speeduino 202210-dev" + signature = "speeduino 202204-dev" versionInfo = "S" ;This info is what is displayed to user [TunerStudio] @@ -25,11 +25,6 @@ ;settingGroup = boostUnits, "Boost table units" ;settingOption = DEFAULT, "kPa" ;settingOption = BOOSTPSI, "PSI" - - settingGroup = pressure_units, "Pressure Display" - settingOption = DEFAULT, "PSI" - settingOption = pressure_bar, "BAR" - settingGroup = enablehardware_test, "Enable Hardware Test Page" settingGroup = resetcontrol_group, "Reset Control Features" @@ -227,16 +222,16 @@ ;---------------------------------------------------------------------------- endianness = little - nPages = 15 - pageSize = 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288, 256 + nPages = 14 + pageSize = 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288 ; 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", "\$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" + 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" #if mcu_stm32 blockingFactor = 121 @@ -288,7 +283,7 @@ page = 1 #if CELSIUS aeColdTaperMin= scalar, U08, 2, "C", 1.0, -40, -40, 215, 0 ;AE cold adjustment, taper start clt (full adjustment) #else - aeColdTaperMin= scalar, U08, 2, "F", 1.8, -22.23, -40, 419, 0 ;AE cold adjustment, taper start clt (full adjustment) + aeColdTaperMin= scalar, U08, 2, "F", 1.8, -22.23, -40, 215, 0 ;AE cold adjustment, taper start clt (full adjustment) #endif aeMode = bits, U08, 3, [0:1], "TPS", "MAP", "INVALID", "INVALID" @@ -353,7 +348,7 @@ page = 1 #if CELSIUS aeColdTaperMax = scalar, U08, 39, "C", 1.0, -40, -40, 215, 0 ;AE cold adjustment, taper start clt (full adjustment) #else - aeColdTaperMax = scalar, U08, 39, "F", 1.8, -22.23, -40, 419, 0 ;AE cold adjustment, taper end clt (no adjustment) + aeColdTaperMax = scalar, U08, 39, "F", 1.8, -22.23, -40, 215, 0 ;AE cold adjustment, taper end clt (no adjustment) #endif dutyLim = scalar, U08, 40, "%", 1.0, 0.0, 0.0, 95.0, 0 @@ -399,13 +394,13 @@ page = 1 #if CELSIUS aseBins = array, U08, 79, [4], "C", 1.0, -40, -40, 215, 0 #else - aseBins = array, U08, 79, [4], "F", 1.8, -22.23, -40, 419, 0 + aseBins = array, U08, 79, [4], "F", 1.8, -22.23, -40, 215, 0 #endif primePulse = array, U08, 83, [4], "ms", 0.5, 0.0, 0.0, 127.5, 1 #if CELSIUS primeBins = array, U08, 87, [4], "C", 1.0, -40, -40, 215, 0 #else - primeBins = array, U08, 87, [4], "F", 1.8, -22.23, -40, 419, 0 + primeBins = array, U08, 87, [4], "F", 1.8, -22.23, -40, 215, 0 #endif CTPSPin = bits, U08, 91, [0:5], "Board Default", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID" CTPSPolarity = bits, U08, 91, [6:6], "Normal", "Inverted" @@ -423,7 +418,7 @@ page = 1 #if CELSIUS dfcoMinCLT = scalar, U08, 101, "C", 1.0, -40, -40, 215, 0 #else - dfcoMinCLT = scalar, U08, 101, "F", 1.8, -22.23, -40, 419, 0 + dfcoMinCLT = scalar, U08, 101, "F", 1.8, -22.23, -40, 215, 0 #endif ;VSS settings @@ -463,6 +458,7 @@ 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 @@ -605,7 +601,7 @@ page = 4 #if CELSIUS vvtMinClt = scalar, U08, 126, "C", 1.0, -40, -40, 215, 0 #else - vvtMinClt = scalar, U08, 126, "F", 1.8, -22.23, -40, 419, 0 + vvtMinClt = scalar, U08, 126, "F", 1.8, -22.23, -40, 215, 0 #endif vvtDelay = scalar, U08, 127, "S", 5.0, 0.0, 0, 1275, 0 @@ -640,7 +636,7 @@ page = 6 #if CELSIUS egoTemp = scalar, U08, 4, "C", 1.0, -40, -40, 102.0, 0 #else - egoTemp = scalar, U08, 4, "F", 1.8, -22.23, -40, 419.0, 0 + egoTemp = scalar, U08, 4, "F", 1.8, -22.23, -40, 215.0, 0 #endif egoCount = scalar, U08, 5, "", 4.0, 0.0, 4.0, 255.0, 0 ; * ( 1 byte) vvtMode = bits, U08, 6, [0:1], "On/Off", "Open Loop", "Closed loop", "INVALID" @@ -659,14 +655,14 @@ page = 6 useExtBaro = bits, U08, 13, [6:6], "No", "Yes" boostMode = bits, U08, 13, [7:7], "Simple", "Full" boostPin = bits, U08, 14, [0:5], "Board Default", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" - tachoMode = bits, U08, 14, [6:6], "Fixed Duration", "Match Dwell" + unused_bit = bits, U08, 14, [6:6], "No", "Yes" useEMAP = bits, U08, 14, [7:7], "No", "Yes" brvBins = array, U08, 15, [6], "V", 0.1, 0, 6, 24, 1 ; Bins for the battery reference voltage injBatRates = array, U08, 21, [6], "%", 1, 0, 0, 255, 0 ;Values for injector pulsewidth vs voltage #if CELSIUS airDenBins = array, U08, 27, [9], "C", 1.0, -40, -40, 215, 0 ; Bins for the air density correction curve #else - airDenBins = array, U08, 27, [9], "F", 1.8, -22.23, -40, 419, 0 ; Bins for the air density correction curve + airDenBins = array, U08, 27, [9], "F", 1.8, -22.23, -40, 215, 0 ; Bins for the air density correction curve #endif airDenRates = array, U08, 36, [9], "%", 1.0, 0.0, 0, 255, 0 ; Values for the air density correction curve @@ -711,14 +707,14 @@ page = 6 #if CELSIUS iacBins = array, U08, 94, [10], "C", 1.0, -40, -40, 215, 0 #else - iacBins = array, U08, 94, [10], "F", 1.8, -22.23, -40, 419, 0 + iacBins = array, U08, 94, [10], "F", 1.8, -22.23, -40, 215, 0 #endif iacCrankSteps= array, U08, 104, [4], "Steps", 3, 0, 0, 765, 0 iacCrankDuty = array, U08, 108, [4], "Duty %", 1.0, 0, 0, 100, 0 #if CELSIUS iacCrankBins = array, U08, 112, [4], "C", 1.0, -40, -40, 215, 0 #else - iacCrankBins = array, U08, 112, [4], "F", 1.8, -22.23, -40, 419, 0 + iacCrankBins = array, U08, 112, [4], "F", 1.8, -22.23, -40, 215, 0 #endif iacAlgorithm = bits , U08, 116, [0:2], "None", "On/Off", "PWM Open loop", "PWM Closed loop", "Stepper Open Loop", "Stepper Closed Loop", "PWM Closed+Open loop", "Stepper Closed+Open loop" @@ -729,7 +725,7 @@ page = 6 #if CELSIUS iacFastTemp = scalar, U08, 117, "C", 1.0, -40, -40, 215, 0 #else - iacFastTemp = scalar, U08, 117, "F", 1.8, -22.23, -40, 419, 0 + iacFastTemp = scalar, U08, 117, "F", 1.8, -22.23, -40, 215, 0 #endif iacStepHome = scalar, U08, 118, "Steps", 3, 0, 0, 765, 0 @@ -743,14 +739,14 @@ page = 6 fanSP = scalar, U08, 121, "C", 1.0, -40, -40, 215.0, 0 fanHyster = scalar, U08, 122, "C", 1.0, 0.0, 0.0, 40, 0 #else - fanSP = scalar, U08, 121, "F", 1.8, -22.23, -40, 419.0, 0 + fanSP = scalar, U08, 121, "F", 1.8, -22.23, -40, 215.0, 0 fanHyster = scalar, U08, 122, "F", 1.0, 0.0, 0.0, 40, 0 #endif fanFreq = scalar, U08 , 123, "Hz", 2.0, 0.0, 10, 511, 0 #if CELSIUS fanPWMBins = array, U08, 124, [4], "C", 1.0, -40, -40, 215, 0 #else - fanPWMBins = array, U08, 124, [4], "F", 1.8, -22.23, -40, 419, 0 + fanPWMBins = array, U08, 124, [4], "F", 1.8, -22.23, -40, 215, 0 #endif ;-------------------------------------------------- @@ -1058,29 +1054,15 @@ page = 9 #if CELSIUS coolantProtTemp = array, U08, 173, [6], "C", 1.0, -40, -40, 215, 0 #else - coolantProtTemp = array, U08, 173, [6], "F", 1.8, -22.23, -40, 419, 0 + coolantProtTemp = array, U08, 173, [6], "F", 1.8, -22.23, -40, 215, 0 #endif - - unused179_184 = array, U08, 179, [6], "", 1, 0, 0, 255, 0 - - ; AFR engine protection - afrProtectEnabled = bits, U08, 185, [0:1], "Off", "Fixed mode", "Table mode", "INVALID" - afrProtectMAP = scalar, U08, 186, "kPa", 2.0, 0.0, 0.0, 511.0, 0 ; 8 bit value, 1 byte - afrProtectRPM = scalar, U08, 187, "RPM", 100, 0.0, 100, 25500, 0 ; 8 bit value, 1 byte - afrProtectTPS = scalar, U08, 188, "%", 0.5, 0.0, 0.0, 100.0, 1 ; 8 bit value, 1 byte -#if LAMBDA - afrProtectDeviation = scalar, U08, 189, "Lambda", {0.1 / stoich}, 0.0, 0.00, 25.5, 2 ; 8 bit value, 1 byte -#else - afrProtectDeviation = scalar, U08, 189, "AFR", 0.1, 0.0, 0.0, 25.5, 1 ; 8 bit value, 1 byte -#endif - afrProtectCutTime = scalar, U08, 190, "seconds", 0.1, 0.0, 0.0, 2.5, 1 ; 8 bit value, 1 byte - afrProtectReactivationTPS = scalar, U08, 191, "%", 0.5, 0.0, 0.0, 100.0, 1 ; 8 bit value, 1 byte + unused179_191 = array, U08, 179, [13], "", 1, 0, 0, 255, 0 page = 10 #if CELSIUS crankingEnrichBins = array, U08, 0, [4], "C", 1.0, -40, -40, 215, 0 #else - crankingEnrichBins = array, U08, 0, [4], "F", 1.8, -22.23, -40, 419, 0 + crankingEnrichBins = array, U08, 0, [4], "F", 1.8, -22.23, -40, 215, 0 #endif crankingEnrichValues= array, U08, 4, [4], "%", 5.0, 0.0, 0, 1275, 0 ; Values for the cranking enrichment curve @@ -1111,7 +1093,7 @@ page = 10 #if CELSIUS n2o_minCLT = scalar, U08, 76, "C", 1.0, -40, -40, 215, 0 #else - n2o_minCLT = scalar, U08, 76, "F", 1.8, -22.23, -40, 419, 0 + n2o_minCLT = scalar, U08, 76, "F", 1.8, -22.23, -40, 215, 0 #endif n2o_maxMAP = scalar, U08, 77, "kPa", 2.0, 0.0, 0.0, 511.0, 0 n2o_minTPS = scalar, U08, 78, "%TPS", 0.5, 0.0, 0.0, 100.0, 1 @@ -1190,20 +1172,14 @@ page = 10 fuelPressurePin = bits, U08, 136, [0:4], "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "A16", "A17", "A18", "A19", "A20", "A21", "A22", INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID - #if pressure_bar - fuelPressureMin = scalar, S08, 137, "BAR", 0.0698, 0.0, -7.0, 8.9, 2 ;Note signed int - fuelPressureMax = scalar, U08, 138, "BAR", 0.0698, 0.0, 0.0, 17.8, 2 - oilPressureMin = scalar, S08, 139, "BAR", 0.0698, 0.0, -7.0, 8.9, 2 ;Note signed int - oilPressureMax = scalar, U08, 140, "BAR", 0.0698, 0.0, 0.0, 17.8, 2 - oilPressureProtMins = array, U08, 145, [ 4], "BAR", 0.0698 0.0, 0.0, 17.8, 2 - #else + 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 - oilPressureProtMins = array, U08, 145, [ 4], "psi", 1.0, 0.0, 0.0, 255, 0 - #endif + 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 wmiEnabled = bits, U08, 149, [0:0], "Off", "On" wmiMode = bits, U08, 149, [1:2], "Simple", "Proportional", "Openloop", "Closedloop" @@ -1217,7 +1193,7 @@ page = 10 #if CELSIUS wmiIAT = scalar, U08, 154, "C", 1.0, -40, -40, 215, 0 #else - wmiIAT = scalar, U08, 154, "F", 1.8, -22.23, -40, 419, 0 + wmiIAT = scalar, U08, 154, "F", 1.8, -22.23, -40, 215, 0 #endif wmiOffset = scalar, S08, 155, "ms", 1.0, 0.0, -12.7, 12.7, 0 ;Note signed int @@ -1245,7 +1221,7 @@ page = 10 #if CELSIUS fuelTempBins = array, U08, 174, [6], "C", 1.0, -40, -40, 215, 0 #else - fuelTempBins = array, U08, 174, [6], "F", 1.8, -22.23, -40, 419, 0 + fuelTempBins = array, U08, 174, [6], "F", 1.8, -22.23, -40, 215, 0 #endif fuelTempValues = array, U08, 180, [6], "%", 1.0, 0.0, 0, 255, 0 @@ -1371,7 +1347,7 @@ page = 13 onboard_log_trigger_RPM = bits, U08, 117, [3:3], "Disabled", "Enabled" onboard_log_trigger_prot = bits, U08, 117, [4:4], "Disabled", "Enabled" onboard_log_trigger_Vbat = bits, U08, 117, [5:5], "Disabled", "Enabled" - onboard_log_trigger_Epin = bits, U08, 117, [6:7], "Disabled", "Enabled", "INVALID", "INVALID" ;In future add momentary on/off option + onboard_log_trigger_Epin = bits, U08, 117, [6:7], "Disabled", "polling", "toggle" , "INVALID" onboard_log_tr1_duration = scalar, U16, 118, "s", 1.000, 0.0, 0, 65000, 0 onboard_log_tr2_thr_on = scalar, U08, 120, "RPM", 100.0, 0.0, 0, 10000, 0 onboard_log_tr2_thr_off = scalar, U08, 121, "RPM", 100.0, 0.0, 0, 10000, 0 @@ -1381,8 +1357,7 @@ page = 13 onboard_log_tr3_thr_AFR = bits, U08, 122, [3:3], "Disabled", "Enabled" onboard_log_tr4_thr_on = scalar, U08, 123, "V", 0.1, 0.0, 0.0, 15.90, 2 ; * ( 1 byte) onboard_log_tr4_thr_off = scalar, U08, 124, "V", 0.1, 0.0, 0.0, 14.90, 2 ; * ( 1 byte) - onboard_log_tr5_Epin_pin = bits , U08, 125, [0:5], $IO_Pins_no_def - unused13_125_2 = bits , U08, 125, [6:7], ";", ",", "tab", "space" + onboard_log_tr5_thr_on = scalar, U08, 125, "pin", 1.0, 0.0, 0.0, 255, 0 ; unused12_125_127 = array, U08, 126, [2], "%", 1.0, 0.0, 0.0, 255, 0 @@ -1396,25 +1371,6 @@ 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 } @@ -1597,19 +1553,6 @@ page = 15 #endif defaultValue = vvtDelay, 60 - ; AFR protection default values - defaultValue = afrProtectEnabled, 0 - defaultValue = afrProtectMAP, 180 - defaultValue = afrProtectRPM, 4000 - defaultValue = afrProtectTPS, 80 -#if LAMBDA - defaultValue = afrProtectDeviation, 0.10 -#else - defaultValue = afrProtectDeviation, 1.47 -#endif - defaultValue = afrProtectCutTime, 0.8 - defaultValue = afrProtectReactivationTPS, 20 - ;Default pins defaultValue = fanPin, 0 defaultValue = vvt1Pin, 0 @@ -1634,6 +1577,9 @@ page = 15 defaultValue = ADCFILTER_BARO, 64 defaultValue = FILTER_FLEX, 75 + ;Again, force the setting from the controller for the trigger edges. This is particularly useful for the Oct 2018 update where the names of the edges changed + controllerPriority = TrigEdge + controllerPriority = TrigEdgeSec ;VSS Ratios and calibration need controller priority so they can be set with the command buttons controllerPriority = vssPulsesPerKm controllerPriority = vssRatio1 @@ -1670,7 +1616,7 @@ page = 15 defaultValue = onboard_log_tr3_thr_AFR, 0 defaultValue = onboard_log_tr4_thr_on, 12.5 defaultValue = onboard_log_tr4_thr_off, 7.0 - defaultValue = onboard_log_tr5_Epin_pin, 0 + defaultValue = onboard_log_tr5_thr_on, 0 defaultValue = onboard_log_csv_separator, 0 ;VSS related settings @@ -1793,7 +1739,6 @@ menuDialog = main groupChildMenu = revLimiterDialog, "Rev Limiters", { engineProtectType } groupChildMenu = boostCut, "Boost Cut", { engineProtectType } groupChildMenu = oilPressureProtection, "Oil Pressure", { engineProtectType } - groupChildMenu = afrProtect, "AFR Protection", { engineProtectType } subMenu = flexFuel, "Flex Fuel", 2 subMenu = veTableDialog, "VE Table", 0 subMenu = sparkTbl, "Spark Table", 2 @@ -2032,18 +1977,6 @@ menuDialog = main hardRevLim = "A fixed hard rev limit is a single 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" - ; AFR Protection Help - afrProtectMAP = "Minimum manifold air pressure the AFR lean protection will activate" - afrProtectRPM = "Minimum RPM the AFR lean protection will activate" - afrProtectTPS = "Minimum current throttle position for the AFR lean protection to activate" -#if LAMBDA - afrProtectDeviation = "Fixed mode = A fixed maximum lambda value (e.g. 0.95)\n\nTable mode = A maximum deviation (e.g. 0.1) from current lambda using target table + specified deviation" -#else - afrProtectDeviation = "Fixed mode = A fixed maximum AFR value (e.g. 14.0)\n\nTable mode = A maximum deviation (e.g. 1.5) from current AFR using target table + specified deviation" -#endif - afrProtectCutTime = "Time delay before activating AFR protection when all conditions has been fulfilled" - afrProtectReactivationTPS = "Going below this throttle position (%) will deactivate this protection" - 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" fuel2InputPullup = "Whether to use the built in PULLUP for the switching input. This should be Yes for a typical ground switching input" @@ -2100,7 +2033,7 @@ menuDialog = main launchPin = "The ARDUINO pin that the clutch switch is connected to. This is NOT the pin on the connector, but the pin it relates to on the arduino" launchHiLo = "Whether the signal is High or Low when the clutch pedal is engaged. For a ground switching input (Most clutch switches), this should be LOW" lnchPullRes = "Whether the internal pullup resistor is enabled or left floating. For a ground switching input (Most clutch switches), select Pullup. For a 0v-5v input, select Floating" - lnchCtrlTPS = "The minimum TPS percentage that launch control will engage at" + lnchCtrlTPS = "The minimum RPM that launch control will engage at" lnchSoftLim = "The RPM point that the launch control ignition timing adjustment will engage (When under launch conditions). Should be below the hard rev limit RPM" lnchRetard = "When under launch conditions (Eg Clutch engaged) the ignition timing will be set to this when above the Soft rev limit. This will override any other ignition modifiers" lnchHardLim = "The RPM point above which the fuel and/or ignition will be cut when launch is active (Eg Clutch engaged). See the Engine Protection dialog to set whether it is fuel, ignition or both that are cut." @@ -2310,20 +2243,15 @@ menuDialog = main onboard_log_tr3_thr_AFR = "When the bits of the AFR engine protection function are set the datalogger is started when no set anymore the logger is stopped" onboard_log_tr4_thr_on = "When the measured battery voltage is above this threshold the datalogger is started" onboard_log_tr4_thr_off = "When the measured battery voltage is below this threshold the datalogger is stopped" - onboard_log_tr5_Epin_pin = "The pin to trigger the datalogger start/stop" + onboard_log_tr5_thr_on = "The pin to trigger the datalogger start/stop" onboard_log_csv_separator = "Choose what character is used for the CSV separator between fields" battVCorMode = "The Battery Voltage Correction value from the table below can either be applied on the whole injection Pulse Width value, or only on the Open Time value." dwellTable = "Sets the dwell time in milliseconds based on RPM/load. This can be used to reduce stress/wear on ignition system where long dwell is not needed. And other areas can use longer dwell value if needed for stronger spark. Battery voltage correction is applied for these dwell values." useDwellMap = "In normal operation mode this is set to No and speeduino will use fixed running dwell value. But if different dwell values are required across engine RPM/load range, this can be set to Yes and separate Dwell table defines running dwell value." - tachoMode = "The output mode for the tacho pulse. Fixed timing will produce a pulse that is always of the same duration, which works better with mode modern digital tachos. Dwell based output creates a pulse that is matched to the coil/s dwell time. If enabled the tacho pulse duration and timing is same as coil dwell and the number of pulses is same as number of ignition events. This can work better on some styles of tacho but note that the pulse duration might become problem on higher cylinder number engines." 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." - [UserDefined] ; Enhanced TunerStudio dialogs can be defined here @@ -2485,12 +2413,11 @@ menuDialog = main panel = vss_gear_detection dialog = tacho, "Tacho" - field = "Output pin", tachoPin - field = "Tacho pulse mode", tachoMode - field = "Output speed", tachoDiv, { tachoMode == 0 } - field = "Pulse duration", tachoDuration, { tachoMode == 0 } - ;field = "Tacho sweep on boot", useTachoSweep - ;field = "Tacho sweep Max RPM", tachoSweepMaxRPM, { useTachoSweep } + field = "Output pin", tachoPin + field = "Output speed", tachoDiv + field = "Pulse duration", tachoDuration + ;field = "Tacho sweep on boot", useTachoSweep + ;field = "Tacho sweep Max RPM", tachoSweepMaxRPM, { useTachoSweep } dialog = accelEnrichments_aeSettings, "" field = "Enrichment mode", aeMode @@ -2835,19 +2762,11 @@ menuDialog = main field = "Gear 5 ", boostByGear5, { boostByGearEnabled } field = "Gear 6 ", boostByGear6, { boostByGearEnabled } - dialog = boostBaseDC, "Closed loop initial duty" - field = "Base duty cycle to be used for a given boost target", {}, { boostType == 2 } - panel = boostDCLupTbl, { boostEnabled && boostType == 1 } - - dialog = boostDCTarget, "Primary Boost table" - field = "In open loop mode, the values in this table are duty cycle %", {}, {}, { boostType == 0 } - field = "In closed loop mode, the values in this table are boost targets in kPa", {}, {}, { boostType == 1 } - panel = boostTbl - dialog = boostLoad, "" field = "Mode", boostType - panel = boostDCTarget - panel = boostBaseDC, { boostType == 1 } + 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 dialog = coolantProtection, "Coolant Based Rev Limit" panel = coolant_prot_curve, { hardRevMode == 2 } @@ -2867,25 +2786,7 @@ menuDialog = main field = "Oil Pressure Protection", oilPressureProtEnbl, { oilPressureEnable } panel = oil_pressure_prot_curve, { oilPressureEnable && oilPressureProtEnbl } - ; AFR engine protection dialog - dialog = afrProtect, "AFR Protection", yAxis - field = "AFR protection is used to prevent engine from running lean" - field = "#Note: This function requires wideband sensor and proper AFR table" - field = "" - field = "Enable AFR protection ", afrProtectEnabled, {egoType == 2} - field = "Minimum manifold air pressure ", afrProtectMAP, {afrProtectEnabled} - field = "Minimum engine RPM ", afrProtectRPM, {afrProtectEnabled} - field = "Minimum throttle position ", afrProtectTPS, {afrProtectEnabled} -#if LAMBDA - field = "Maximum lambda ", afrProtectDeviation, {afrProtectEnabled}, {afrProtectEnabled == 0 || afrProtectEnabled == 1} - field = "Maximum lambda deviation ", afrProtectDeviation, {afrProtectEnabled}, {afrProtectEnabled == 2} -#else - field = "Maximum AFR ", afrProtectDeviation, {afrProtectEnabled}, {afrProtectEnabled == 0 || afrProtectEnabled == 1} - field = "Maximum AFR deviation ", afrProtectDeviation, {afrProtectEnabled}, {afrProtectEnabled == 2} -#endif - field = "Time before cut ", afrProtectCutTime, {afrProtectEnabled} - field = "" - field = "Reactivate below throttle ", afrProtectReactivationTPS, {afrProtectEnabled} + indicatorPanel = protectIndicatorPanel, 1, { 1 } indicator = { engineProtectStatus}, "Engine Protect OFF", "Engine Protect ON", green, black, red, black @@ -3055,46 +2956,26 @@ menuDialog = main field = "Enabled", fuelPressureEnable field = "Pin", fuelPressurePin, { fuelPressureEnable } settingSelector = "Common Sensors", { fuelPressureEnable } - #if pressure_bar - settingOption = "0-10 BAR", fuelPressureMin=-1.25, fuelPressureMax=11.25 ; regular sensors give 0.5V to 4.5V for 0 bar to rated bar. Formula Vout = P x 4 / P_rated + 0.5 - settingOption = "0-100 PSI", fuelPressureMin=-0.1, fuelPressureMax=7.1 ; these are just converted psi to bar. Kept because most off-shelf are in PSI - settingOption = "0-150 PSI", fuelPressureMin=-1.25, fuelPressureMax=11.58 - #else settingOption = "0-100 PSI", fuelPressureMin=-3, fuelPressureMax=103 ; Vout = VCC x (P x .97 / 200 + 0.5) settingOption = "0-150 PSI", fuelPressureMin=-18, fuelPressureMax=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 - #endif field = "Pressure at 0v", fuelPressureMin, { fuelPressureEnable } field = "Pressure at 5v", fuelPressureMax, { fuelPressureEnable } dialog = fuelPressureDialog, "Fuel Pressure", xAxis - #if pressure_bar - gauge = fuelPressureBarGauge - #else gauge = fuelPressureGauge - #endif panel = fuelPressureSettings dialog = oilPressureSettings field = "Enabled", oilPressureEnable field = "Pin", oilPressurePin, { oilPressureEnable } settingSelector = "Common Sensors", { oilPressureEnable } - #if pressure_bar - settingOption = "0-10 BAR", oilPressureMin=-1.25, oilPressureMax=11.25 ; regular sensors give 0.5V to 4.5V for 0 bar to rated bar. Formula Vout = P x 4 / P_rated + 0.5 - settingOption = "0-100 PSI", oilPressureMin=-0.1, oilPressureMax=7.1 ; these are just converted psi to bar. Kept because most off-shelf are in PSI - settingOption = "0-150 PSI", oilPressureMin=-1.25, oilPressureMax=11.58 - #else settingOption = "0-100 PSI", oilPressureMin=-3, oilPressureMax=103 ; Vout = VCC x (P x .97 / 200 + 0.5) 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 - #endif field = "Pressure at 0v", oilPressureMin, { oilPressureEnable } field = "Pressure at 5v", oilPressureMax, { oilPressureEnable } dialog = oilPressureDialog, "Oil Pressure", xAxis - #if pressure_bar - gauge = oilPressureBarGauge - #else gauge = oilPressureGauge - #endif panel = oilPressureSettings dialog = pressureSensors, "Pressure Transducers" @@ -3114,15 +2995,12 @@ menuDialog = main panel = boostCut panel = boostByGear, { boostEnabled && vssMode > 1 } field = "Closed Loop settings" - 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 } + 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 } dialog = vvt2, "Second VVT output" field = "VVT2 Control Enabled", vvt2Enabled @@ -4159,6 +4037,10 @@ menuDialog = main field = "Real Time Clock mode", rtc_mode field = "Real Time Clock Trim +/-", rtc_trim, {rtc_mode} +; dialog = rtc_settings, "Real Time Clock" +; panel = rtc_setup +; panel = std_ms3Rtc + dialog = onboard_log_basic_setup, "Log Configuration" field = "Logger type", onboard_log_file_style ;field = "CSV separator", onboard_log_csv_separator {onboard_log_file_style == 1} @@ -4173,18 +4055,13 @@ menuDialog = main field = "On Boot", onboard_log_trigger_boot, {onboard_log_file_style} field = "On Boot log duration", onboard_log_tr1_duration, {onboard_log_file_style && onboard_log_trigger_boot} - dialog = onboard_log_trigger_RPM, "RPM" + dialog = onboard_log_trigger_RPM, "RPM" field = "RPM", onboard_log_trigger_RPM {onboard_log_file_style && !onboard_log_trigger_boot} field = "ON (Min RPM)", onboard_log_tr2_thr_on {onboard_log_file_style && onboard_log_trigger_RPM} field = "OFF (Max RPM)", onboard_log_tr2_thr_off {onboard_log_file_style && onboard_log_trigger_RPM} - dialog = onboard_log_trigger_prot, "Engine protection" + dialog = onboard_log_trigger_prot, "Engine protection" field = "Engine protection", onboard_log_trigger_prot {onboard_log_file_style && !onboard_log_trigger_boot} - - dialog = onboard_log_trigger_Epin, "External Switch" - field = "Board pin", onboard_log_trigger_Epin {onboard_log_file_style && !onboard_log_trigger_boot} - field = "Pin number", onboard_log_tr5_Epin_pin {onboard_log_file_style && onboard_log_trigger_Epin} - ; field = "RPM", onboard_log_tr3_thr_RPM {onboard_log_file_style && onboard_log_trigger_prot} ; field = "MAP", onboard_log_tr3_thr_MAP {onboard_log_file_style && onboard_log_trigger_prot} ; field = "Oil", onboard_log_tr3_thr_Oil {onboard_log_file_style && onboard_log_trigger_prot} @@ -4195,6 +4072,9 @@ menuDialog = main ; field = "ON threshold", onboard_log_tr4_thr_on {onboard_log_file_style && onboard_log_trigger_Vbat} ; field = "OFF threshold", onboard_log_tr4_thr_off {onboard_log_file_style && onboard_log_trigger_Vbat} +; dialog = onboard_log_trigger_Epin, "Board pin" +; field = "Board pin", onboard_log_trigger_Epin {onboard_log_file_style&& !onboard_log_trigger_boot} +; field = "Pin number", onboard_log_tr5_thr_on {onboard_log_file_style && onboard_log_trigger_Epin} dialog = rtc_settings, "Real Time Clock" field = "Mode", rtc_mode @@ -4205,7 +4085,6 @@ menuDialog = main ;field = "Above RPM", onboard_log_trigger_RPM panel = onboard_log_trigger_RPM panel = onboard_log_trigger_prot - panel = onboard_log_trigger_Epin ;field = "With battery", onboard_log_trigger_Vbat dialog = onboard_log_setup, "On-board logger", border @@ -4555,13 +4434,9 @@ cmdVSSratio6 = "E\x99\x06" ; Oil Pressure protection curve curve = oil_pressure_prot_curve, "Oil Pressure Protection" - columnLabel = "RPM", "Minimum" + columnLabel = "RPM", "Minimum PSI" xAxis = 0, 8000, 9 - #if pressure_bar - yAxis = 0, 10.0, 3 - #else - yAxis = 0, 150, 3 - #endif + yAxis = 0, 150, 3 xBins = oilPressureProtRPM, rpm yBins = oilPressureProtMins size = 400, 200 @@ -4675,14 +4550,6 @@ cmdVSSratio6 = "E\x99\x06" gridHeight = 3.0 upDownLabel = "HIGHER", "LOWER" - table = boostDCLupTbl, boostDutyLookup, "Base duty for closed loop", 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 @@ -4896,13 +4763,8 @@ cmdVSSratio6 = "E\x99\x06" #endif flexGauge = flex, "Flex sensor", "%", 0, 100, -1, -1, 999, 999, 0, 0 - fuelPressureGauge = fuelPressure, "Fuel Pressure (PSI)", "PSI", -15, 100, 0, 20, 200, 245, 0, 0 - oilPressureGauge = oilPressure, "Oil Pressure (PSI)", "PSI", -15, 100, 0, 20, 200, 245, 0, 0 - fuelPressureBarGauge = fuelPressure_bar,"Fuel Pressure (BAR)", "BAR", -1.0, 7.0, 0.5, 1.4, 14.0, 17.0, 1, 1 - oilPressureBarGauge = oilPressure_bar, "Oil Pressure (BAR)", "BAR", -1.0, 7.0, 0.5, 1.4, 14.0, 17.0, 1, 1 - fuelPressurekPaGauge = fuelPressure_kpa,"Fuel Pressure (kPa)", "kPa", -100, 700, 50, 140, 1400, 1700, 0, 0 - oilPressurekPaGauge = oilPressure_kpa, "Oil Pressure (kPa)", "kPa", -100, 700, 50, 140, 1400, 1700, 0, 0 - + fuelPressureGauge = fuelPressure, "Fuel Pressure", "PSI", -15, 100, 0, 20, 200, 245, 0, 0 + oilPressureGauge = oilPressure, "Oil Pressure", "PSI", -15, 100, 0, 20, 200, 245, 0, 0 gaugeCategory = "Auxiliary Input Channels" AuxInGauge0 = auxin_gauge0, { stringValue(AUXin00Alias) }, "", 0, 1024, -1, -1, 1025, 1025, 0, 0 @@ -5112,7 +4974,7 @@ cmdVSSratio6 = "E\x99\x06" engineProtectMAP = bits, U08, 84, [1:1] engineProtectOil = bits, U08, 84, [2:2] engineProtectAFR = bits, U08, 84, [3:3] - engineProtectCoolant = bits, U08, 84, [4:4] + engineProtectCoolant = bits, U08, 84, [4:4] engineProtectOth = bits, U08, 84, [5:6] ; Unused for now IOError = bits, U08, 84, [7:7] unused1 = scalar, U08, 84, "ADC",1.000, 0.000 @@ -5174,11 +5036,6 @@ cmdVSSratio6 = "E\x99\x06" time = { timeNow } seconds = { secl } - fuelPressure_bar = { fuelPressure * 0.06894757 } - oilPressure_bar = { oilPressure * 0.06894757 } - fuelPressure_kpa = { fuelPressure * 6.894757 } - oilPressure_kpa = { oilPressure * 6.894757 } - throttle = { tps }, "%" revolutionTime = { rpm ? ( 60000.0 / rpm) : 0 } @@ -5253,127 +5110,122 @@ cmdVSSratio6 = "E\x99\x06" ;------------------------------------------------------------------------------- [Datalog] - ; Full datalog. - ; - ; Default user-defined log emulates the full datalog. - ; - ; The entries are saved in the datalog file in the order in - ; which they appear in the list below. - ; - ; Channel - Case sensitive name of output channel to be logged. - ; Label - String written to header line of log. Be careful - ; about changing these, as programs like MSLVV and - ; MSTweak key off specific column names. - ; Type - Data type of output, converted before writing. - ; Format - C-style output format of data. - ; - ; Channel Label Type Format - ; -------------- ---------- ----- ------ - entry = time, "Time", float, "%.3f" - entry = secl, "SecL", int, "%d" - entry = rpm, "RPM", int, "%d" - entry = map, "MAP", int, "%d" - entry = MAPxRPM, "MAPxRPM", int, "%d" - entry = tps, "TPS", float, "%.1f" - entry = afr, "AFR", float, "%.3f" - entry = lambda, "Lambda", float, "%.3f" - entry = iat, "IAT", int, "%d" - entry = coolant, "CLT", int, "%d" - entry = engine, "Engine", int, "%d" - entry = DFCOOn, "DFCO", int, "%d" - entry = egoCorrection, "Gego", int, "%d" - entry = airCorrection, "Gair", int, "%d" - entry = bat_correction, "Gbattery", int, "%d" - entry = warmupEnrich, "Gwarm", int, "%d" - entry = baroCorrection, "Gbaro", int, "%d" - entry = gammaEnrich, "Gammae", int, "%d" - entry = accelEnrich, "Accel Enrich", int, "%d" - entry = veCurr, "VE (Current)", int, "%d" - entry = VE1, "VE1", int, "%d" - entry = VE2, "VE2", int, "%d" - entry = pulseWidth, "PW", float, "%.3f" - entry = afrTarget, "AFR Target", float, "%.3f" - entry = lambdaTarget, "Lambda Target", float, "%.3f" - entry = pulseWidth2, "PW2", float, "%.3f" - entry = dutyCycle, "DutyCycle1", float, "%.1f" - entry = TPSdot, "TPS DOT", int, "%d", { aeMode == 0 } - entry = advance, "Advance (Current)",int, "%d" - entry = dwell, "Dwell", float, "%.1f" - entry = batteryVoltage, "Battery V", float, "%.1f" - entry = rpmDOT, "rpm/s", int, "%d" - entry = flex, "Eth %", int, "%d", { flexEnabled } - entry = flexFuelCor, "GflexFuel", int, "%d", { flexEnabled } - entry = fuelTemp, "Fuel Temp", int, "%d", { flexEnabled } - entry = fuelTempCor, "GfuelTemp", int, "%d", { flexEnabled } - entry = errorNum, "Error #", int, "%d", { errorNum } - entry = currentError, "Error ID", int, "%d", { errorNum } - entry = map_psi, "Boost PSI", float, "%.1f" - entry = boostTarget, "Boost Target", int, "%d", { boostEnabled } - entry = boostDuty, "Boost Duty", int, "%d", { boostEnabled } - entry = boostCutOut , "Boost cut", int, "%d" - entry = launchHard , "Hard Launch", int, "%d" - entry = hardLimitOn , "Hard Limiter", int, "%d" - entry = idleControlOn, "Idle Control", int, "%d" - entry = idleLoad, "IAC value", int, "%d" - entry = CLIdleTarget, "Idle Target RPM", int, "%%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled - entry = CLIdleDelta, "Idle RPM Delta", int, "%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled - entry = baro, "Baro Pressure", int, "%d" - entry = nitrousOn, "Nitrous", int, "%d", { n2o_enable > 0 } - entry = fanStatus, "Fan", int, "%d" - entry = syncLossCounter, "Sync Loss #", int, "%d" - entry = vvt1Angle, "VVT1 Angle", int, "%.1f", { vvtEnabled > 0 } - entry = vvt1Target, "VVT1 Target Angle",int, "%.1f", { vvtEnabled > 0 && vvtMode == 2 } ;;Only show when using close loop vvt - entry = vvt1Duty, "VVT1 Duty", int, "%.1f", { vvtEnabled > 0 } - entry = vss, "Wheel Speed (kph)",int, "%d", { vssMode > 1 } - entry = vssMPH, "Wheel Speed (mph)",int, "%d", { vssMode > 1 } - entry = gear, "Gear", int, "%d", { vssMode > 1 } - entry = fuelPressure, "Fuel Pressure", int, "%d", { fuelPressureEnable > 0 } - entry = oilPressure, "Oil Pressure", int, "%d", { oilPressureEnable > 0 } - entry = vvt2Angle, "VVT2 Angle", int, "%.1f", { vvt2Enabled > 0 } - entry = vvt2Target, "VVT2 Target Angle",int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } ;;Only show when using close loop vvt - entry = vvt2Duty, "VVT2 Duty", int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } - entry = fanDuty, "FAN Duty", int, "%%.1f", { fanEnable == 2 } - entry = loopsPerSecond, "Loops/s", int, "%d" - entry = loopsPerRev, "Loops/rev", int, "%.2f" - entry = wmiPW, "WMI Duty Cycle", int, "%d", { wmiEnabled == 1 } - entry = MAPdot, "MAP DOT", int, "%d", { aeMode == 1 } + ; Full datalog. + ; + ; Default user-defined log emulates the full datalog. + ; + ; The entries are saved in the datalog file in the order in + ; which they appear in the list below. + ; + ; Channel - Case sensitive name of output channel to be logged. + ; Label - String written to header line of log. Be careful + ; about changing these, as programs like MSLVV and + ; MSTweak key off specific column names. + ; Type - Data type of output, converted before writing. + ; Format - C-style output format of data. + ; + ; Channel Label Type Format + ; -------------- ---------- ----- ------ + entry = time, "Time", float, "%.3f" + entry = secl, "SecL", int, "%d" + entry = rpm, "RPM", int, "%d" + entry = map, "MAP", int, "%d" + entry = MAPxRPM, "MAPxRPM", int, "%d" + entry = tps, "TPS", float, "%.1f" + entry = afr, "AFR", float, "%.3f" + entry = lambda, "Lambda", float, "%.3f" + entry = iat, "IAT", int, "%d" + entry = coolant, "CLT", int, "%d" + entry = engine, "Engine", int, "%d" + entry = DFCOOn, "DFCO", int, "%d" + entry = egoCorrection, "Gego", int, "%d" + entry = airCorrection, "Gair", int, "%d" + entry = bat_correction, "Gbattery", int, "%d" + entry = warmupEnrich, "Gwarm", int, "%d" + entry = baroCorrection, "Gbaro", int, "%d" + entry = gammaEnrich, "Gammae", int, "%d" + entry = accelEnrich, "Accel Enrich", int, "%d" + entry = veCurr, "VE (Current)", int, "%d" + entry = VE1, "VE1", int, "%d" + entry = VE2, "VE2", int, "%d" + entry = pulseWidth, "PW", float, "%.3f" + entry = afrTarget, "AFR Target", float, "%.3f" + entry = lambdaTarget, "Lambda Target", float, "%.3f" + entry = pulseWidth2, "PW2", float, "%.3f" + entry = dutyCycle, "DutyCycle1", float, "%.1f" + entry = TPSdot, "TPS DOT", int, "%d" { aeMode == 0 } + entry = advance, "Advance (Current)",int, "%d" + entry = dwell, "Dwell", float, "%.1f" + entry = batteryVoltage, "Battery V", float, "%.1f" + entry = rpmDOT, "rpm/s", int, "%d" + entry = flex, "Eth %", int, "%d", { flexEnabled } + entry = flexFuelCor, "GflexFuel", int, "%d", { flexEnabled } + entry = fuelTemp, "Fuel Temp", int, "%d", { flexEnabled } + entry = fuelTempCor, "GfuelTemp", int, "%d", { flexEnabled } + entry = errorNum, "Error #", int, "%d", { errorNum } + entry = currentError, "Error ID", int, "%d", { errorNum } + entry = map_psi, "Boost PSI", float, "%.1f" + entry = boostTarget, "Boost Target", int, "%d", { boostEnabled } + entry = boostDuty, "Boost Duty", int, "%d", { boostEnabled } + entry = boostCutOut , "Boost cut", int, "%d" + entry = launchHard , "Hard Launch", int, "%d" + entry = hardLimitOn , "Hard Limiter", int, "%d" + entry = idleControlOn, "Idle Control", int, "%d" + entry = idleLoad, "IAC value", int, "%d" + entry = CLIdleTarget, "Idle Target RPM", int, "%%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled + entry = CLIdleDelta, "Idle RPM Delta", int, "%d", { iacAlgorithm == 3 || iacAlgorithm == 5 || iacAlgorithm == 6 || iacAlgorithm == 7 || idleAdvEnabled >= 1 } ;Only show for closed loop idle modes and if idle advance is enabled + entry = baro, "Baro Pressure", int, "%d" + entry = nitrousOn, "Nitrous", int, "%d", { n2o_enable > 0 } + entry = fanStatus, "Fan", int, "%d" + entry = syncLossCounter, "Sync Loss #", int, "%d" + entry = vvt1Angle, "VVT1 Angle", int, "%.1f", { vvtEnabled > 0 } + entry = vvt1Target, "VVT1 Target Angle",int, "%.1f", { vvtEnabled > 0 && vvtMode == 2 } ;;Only show when using close loop vvt + entry = vvt1Duty, "VVT1 Duty", int, "%.1f", { vvtEnabled > 0 } + entry = vss, "Wheel Speed (kph)",int, "%d", { vssMode > 1 } + entry = vssMPH, "Wheel Speed (mph)",int, "%d", { vssMode > 1 } + entry = gear, "Gear", int, "%d", { vssMode > 1 } + entry = fuelPressure, "Fuel Pressure", int, "%d", { fuelPressureEnable > 0 } + entry = oilPressure, "Oil Pressure", int, "%d", { oilPressureEnable > 0 } + entry = vvt2Angle, "VVT2 Angle", int, "%.1f", { vvt2Enabled > 0 } + entry = vvt2Target, "VVT2 Target Angle",int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } ;;Only show when using close loop vvt + entry = vvt2Duty, "VVT2 Duty", int, "%.1f", { vvt2Enabled > 0 && vvtMode == 2 } + entry = fanDuty, "FAN Duty", int, "%%.1f", { fanEnable == 2 } + entry = loopsPerSecond, "Loops/s", int, "%d" + entry = loopsPerRev, "Loops/rev", int, "%.2f" + entry = wmiPW, "WMI Duty Cycle", int, "%d", { wmiEnabled == 1 } + entry = MAPdot, "MAP DOT", int, "%d" { aeMode == 1 } - entry = auxin_gauge0, { stringValue(AUXin00Alias) }, int, "%d", {(caninput_sel0b != 0)} - entry = auxin_gauge1, { stringValue(AUXin01Alias) }, int, "%d", { (caninput_sel1b != 0)} - entry = auxin_gauge2, { stringValue(AUXin02Alias) }, int, "%d", { (caninput_sel2b != 0)} - entry = auxin_gauge3, { stringValue(AUXin03Alias) }, int, "%d", { (caninput_sel3b != 0)} - entry = auxin_gauge4, { stringValue(AUXin04Alias) }, int, "%d", { (caninput_sel4b != 0)} - entry = auxin_gauge5, { stringValue(AUXin05Alias) }, int, "%d", { (caninput_sel5b != 0)} - entry = auxin_gauge6, { stringValue(AUXin06Alias) }, int, "%d", { (caninput_sel6b != 0)} - entry = auxin_gauge7, { stringValue(AUXin07Alias) }, int, "%d", { (caninput_sel7b != 0)} - entry = auxin_gauge8, { stringValue(AUXin08Alias) }, int, "%d", { (caninput_sel8b != 0)} - entry = auxin_gauge9, { stringValue(AUXin09Alias) }, int, "%d", { (caninput_sel9b != 0)} - entry = auxin_gauge10, { stringValue(AUXin10Alias) }, int, "%d", { (caninput_sel10b != 0)} - entry = auxin_gauge11, { stringValue(AUXin11Alias) }, int, "%d", { (caninput_sel11b != 0)} - entry = auxin_gauge12, { stringValue(AUXin12Alias) }, int, "%d", { (caninput_sel12b != 0)} - entry = auxin_gauge13, { stringValue(AUXin13Alias) }, int, "%d", { (caninput_sel13b != 0)} - entry = auxin_gauge14, { stringValue(AUXin14Alias) }, int, "%d", { (caninput_sel14b != 0)} - entry = auxin_gauge15, { stringValue(AUXin15Alias) }, int, "%d", { (caninput_sel15b != 0)} - entry = outputsStatus0, { stringValue(prgm_out00Alias)}, int, "%d", { (outputPin[0] != 0)} - entry = outputsStatus1, { stringValue(prgm_out01Alias)}, int, "%d", { (outputPin[1] != 0)} - entry = outputsStatus2, { stringValue(prgm_out02Alias)}, int, "%d", { (outputPin[2] != 0)} - entry = outputsStatus3, { stringValue(prgm_out03Alias)}, int, "%d", { (outputPin[3] != 0)} - entry = outputsStatus4, { stringValue(prgm_out04Alias)}, int, "%d", { (outputPin[4] != 0)} - entry = outputsStatus5, { stringValue(prgm_out05Alias)}, int, "%d", { (outputPin[5] != 0)} - entry = outputsStatus6, { stringValue(prgm_out06Alias)}, int, "%d", { (outputPin[6] != 0)} - entry = outputsStatus7, { stringValue(prgm_out07Alias)}, int, "%d", { (outputPin[7] != 0)} + entry = auxin_gauge0, { stringValue(AUXin00Alias) }, int, "%d", {(caninput_sel0b != 0)} + entry = auxin_gauge1, { stringValue(AUXin01Alias) }, int, "%d", { (caninput_sel1b != 0)} + entry = auxin_gauge2, { stringValue(AUXin02Alias) }, int, "%d", { (caninput_sel2b != 0)} + entry = auxin_gauge3, { stringValue(AUXin03Alias) }, int, "%d", { (caninput_sel3b != 0)} + entry = auxin_gauge4, { stringValue(AUXin04Alias) }, int, "%d", { (caninput_sel4b != 0)} + entry = auxin_gauge5, { stringValue(AUXin05Alias) }, int, "%d", { (caninput_sel5b != 0)} + entry = auxin_gauge6, { stringValue(AUXin06Alias) }, int, "%d", { (caninput_sel6b != 0)} + entry = auxin_gauge7, { stringValue(AUXin07Alias) }, int, "%d", { (caninput_sel7b != 0)} + entry = auxin_gauge8, { stringValue(AUXin08Alias) }, int, "%d", { (caninput_sel8b != 0)} + entry = auxin_gauge9, { stringValue(AUXin09Alias) }, int, "%d", { (caninput_sel9b != 0)} + entry = auxin_gauge10, { stringValue(AUXin10Alias) }, int, "%d", { (caninput_sel10b != 0)} + entry = auxin_gauge11, { stringValue(AUXin11Alias) }, int, "%d", { (caninput_sel11b != 0)} + entry = auxin_gauge12, { stringValue(AUXin12Alias) }, int, "%d", { (caninput_sel12b != 0)} + entry = auxin_gauge13, { stringValue(AUXin13Alias) }, int, "%d", { (caninput_sel13b != 0)} + entry = auxin_gauge14, { stringValue(AUXin14Alias) }, int, "%d", { (caninput_sel14b != 0)} + entry = auxin_gauge15, { stringValue(AUXin15Alias) }, int, "%d", { (caninput_sel15b != 0)} + entry = outputsStatus0, { stringValue(prgm_out00Alias)}, int, "%d", { (outputPin[0] != 0)} + entry = outputsStatus1, { stringValue(prgm_out01Alias)}, int, "%d", { (outputPin[1] != 0)} + entry = outputsStatus2, { stringValue(prgm_out02Alias)}, int, "%d", { (outputPin[2] != 0)} + entry = outputsStatus3, { stringValue(prgm_out03Alias)}, int, "%d", { (outputPin[3] != 0)} + entry = outputsStatus4, { stringValue(prgm_out04Alias)}, int, "%d", { (outputPin[4] != 0)} + entry = outputsStatus5, { stringValue(prgm_out05Alias)}, int, "%d", { (outputPin[5] != 0)} + entry = outputsStatus6, { stringValue(prgm_out06Alias)}, int, "%d", { (outputPin[6] != 0)} + entry = outputsStatus7, { stringValue(prgm_out07Alias)}, int, "%d", { (outputPin[7] != 0)} - entry = advance1, "Advance 1", int, "%d" - entry = advance2, "Advance 2", int, "%d" - entry = emap, "EMAP", int, "%d", { useEMAP } - entry = fuelLoad, "FuelLoad", float, "%.1f" - entry = ignLoad, "IgnitionLoad", float, "%.1f" - entry = syncStatus, "Sync status", int, "%d" - entry = engineProtectRPM, "Engine Prot. RPM", int, "activeInactive", { engineProtectType } - entry = engineProtectMAP, "Engine Prot. MAP", int, "activeInactive", { engineProtectType && boostCutEnabled } - entry = engineProtectOil, "Engine Prot. Oil Pressure", int, "activeInactive", { engineProtectType && oilPressureProtEnbl && oilPressureEnable } - entry = engineProtectAFR, "Engine Prot. AFR", int, "activeInactive", { engineProtectType && afrProtectEnabled && {egoType == 2} } - entry = engineProtectCoolant, "Engine Prot. CLT", int, "activeInactive", { engineProtectType } + entry = advance1, "Advance 1", int, "%d" + entry = advance2, "Advance 2", int, "%d" + entry = emap, "EMAP", int, "%d", { useEMAP } + entry = fuelLoad, "FuelLoad", float, "%.1f" + entry = ignLoad, "IgnitionLoad", float, "%.1f" + entry = syncStatus, "Sync status", int, "%d" [LoggerDefinition] ; valid logger types: composite, tooth, trigger, csv diff --git a/speeduino/SD_logger.ino b/speeduino/SD_logger.ino index 1b9b05fa..5d47975a 100644 --- a/speeduino/SD_logger.ino +++ b/speeduino/SD_logger.ino @@ -242,13 +242,7 @@ void writeSDLogEntry() //Write the line to the ring buffer for(byte x=0; x= 32 - float entryValue = getReadableFloatLogEntry(x); - if(IS_INTEGER(entryValue)) { rb.print((uint16_t)entryValue); } - else { rb.print(entryValue); } - #else - rb.print(getReadableLogEntry(x)); - #endif + rb.print(getReadableLogEntry(x)); if(x < (SD_LOG_NUM_FIELDS - 1)) { rb.print(","); } } rb.println(""); @@ -362,12 +356,9 @@ void checkForSDStart() } - if((configPage13.onboard_log_trigger_Epin) && (SD_status == SD_STATUS_READY) ) + if(( configPage13.onboard_log_trigger_Epin) && (SD_status == SD_STATUS_READY) ) { - if(digitalRead(pinSDEnable) == LOW) - { - beginSDLogging(); //Setup the log file, preallocation, header row - } + } } @@ -381,7 +372,6 @@ void checkForSDStop() bool log_RPM = false; bool log_prot = false; bool log_Vbat = false; - bool log_Epin = false; //Logging only needs to be stopped if already active if(SD_status == SD_STATUS_ACTIVE) @@ -414,17 +404,8 @@ void checkForSDStop() } - //External Pin - if(configPage13.onboard_log_trigger_Epin) - { - if(digitalRead(pinSDEnable) == LOW) - { - log_Epin = true; - } - } - //Check all conditions to see if we should stop logging - if( (log_boot == false) && (log_RPM == false) && (log_prot == false) && (log_Vbat == false) && (log_Epin == false) && (manualLogActive == false) ) + if( (log_boot == false) && (log_RPM == false) && (log_prot == false) && (log_Vbat == false) && (manualLogActive == false) ) { endSDLogging(); //Setup the log file, preallocation, header row } diff --git a/speeduino/auxiliaries.ino b/speeduino/auxiliaries.ino index 60b07633..645bb477 100644 --- a/speeduino/auxiliaries.ino +++ b/speeduino/auxiliaries.ino @@ -367,6 +367,7 @@ void boostByGear() } } +#define BOOST_HYSTER 40 void boostControl() { if( configPage6.boostEnabled==1 ) @@ -391,7 +392,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(((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 usually set to boost with wastegate actuator only boost level) + if(currentStatus.MAP >= currentStatus.baro ) //Only engage boost control above baro pressure { //If flex fuel is enabled, there can be an adder to the boost target based on ethanol content if( configPage2.flexEnabled == 1 ) @@ -414,7 +415,7 @@ void boostControl() else { boostPID.SetTunings(configPage6.boostKP, configPage6.boostKI, configPage6.boostKD); } } - bool PIDcomputed = boostPID.Compute(get3DTableValue(&boostTableLookupDuty, currentStatus.boostTarget, currentStatus.RPM) * 100/2); //Compute() returns false if the required interval has not yet passed. + bool PIDcomputed = boostPID.Compute(); //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 { @@ -432,12 +433,8 @@ void boostControl() } else { - 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 % multiplied 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) { boostDisable(); } //If boost control does nothing disable PWM completely + //Boost control does nothing if kPa below the hysteresis point + boostDisable(); } //MAP above boost + hyster } //Open / Cloosed loop diff --git a/speeduino/board_avr2560.h b/speeduino/board_avr2560.h index 3cea1d21..b22339a7 100644 --- a/speeduino/board_avr2560.h +++ b/speeduino/board_avr2560.h @@ -14,7 +14,6 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE (256+7+1) //Size of the serial buffer used by new comms protocol. The largest single packet is the O2 calibration which is 256 bytes + 7 bytes of overhead - #define FPU_MAX_SIZE 0 //Size of the FPU buffer. 0 means no FPU. #ifdef USE_SPI_EEPROM #define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h" typedef uint16_t eeprom_address_t; diff --git a/speeduino/board_same51.h b/speeduino/board_same51.h index e2d8b54f..64eeae2f 100644 --- a/speeduino/board_same51.h +++ b/speeduino/board_same51.h @@ -17,7 +17,6 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE 257 //Size of the serial buffer used by new comms protocol. Additional 1 byte is for flag - #define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. #ifdef USE_SPI_EEPROM #define EEPROM_LIB_H "src/SPIAsEEPROM/SPIAsEEPROM.h" typedef uint16_t eeprom_address_t; diff --git a/speeduino/board_stm32_generic.h b/speeduino/board_stm32_generic.h index ce98e3cd..0b301359 100644 --- a/speeduino/board_stm32_generic.h +++ b/speeduino/board_stm32_generic.h @@ -11,7 +11,6 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) - #define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. #define TIMER_RESOLUTION 2 #define micros_safe() micros() //timer5 method is not used on anything but AVR, the micros_safe() macro is simply an alias for the normal micros() #if defined(SRAM_AS_EEPROM) diff --git a/speeduino/board_stm32_official.h b/speeduino/board_stm32_official.h index 47dca806..550ea970 100644 --- a/speeduino/board_stm32_official.h +++ b/speeduino/board_stm32_official.h @@ -25,7 +25,6 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) -#define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. #define micros_safe() micros() //timer5 method is not used on anything but AVR, the micros_safe() macro is simply an alias for the normal micros() #define TIMER_RESOLUTION 4 @@ -68,7 +67,7 @@ extern "C" char* sbrk(int incr); #ifndef PB11 //Hack for F4 BlackPills #define PB11 PB10 #endif - //Hack to allow compilation on small STM boards + //Hack to alow compile on small STM boards #ifndef A10 #define A10 PA0 #define A11 PA1 @@ -196,20 +195,20 @@ extern "C" char* sbrk(int incr); #define IGN8_COMPARE (TIM4)->CCR4 -#define FUEL1_TIMER_ENABLE() (TIM3)->CR1 |= TIM_CR1_CEN; (TIM3)->SR = ~TIM_FLAG_CC1; (TIM3)->DIER |= TIM_DIER_CC1IE -#define FUEL2_TIMER_ENABLE() (TIM3)->CR1 |= TIM_CR1_CEN; (TIM3)->SR = ~TIM_FLAG_CC2; (TIM3)->DIER |= TIM_DIER_CC2IE -#define FUEL3_TIMER_ENABLE() (TIM3)->CR1 |= TIM_CR1_CEN; (TIM3)->SR = ~TIM_FLAG_CC3; (TIM3)->DIER |= TIM_DIER_CC3IE -#define FUEL4_TIMER_ENABLE() (TIM3)->CR1 |= TIM_CR1_CEN; (TIM3)->SR = ~TIM_FLAG_CC4; (TIM3)->DIER |= TIM_DIER_CC4IE +#define FUEL1_TIMER_ENABLE() (TIM3)->SR = ~TIM_FLAG_CC1; (TIM3)->DIER |= TIM_DIER_CC1IE +#define FUEL2_TIMER_ENABLE() (TIM3)->SR = ~TIM_FLAG_CC2; (TIM3)->DIER |= TIM_DIER_CC2IE +#define FUEL3_TIMER_ENABLE() (TIM3)->SR = ~TIM_FLAG_CC3; (TIM3)->DIER |= TIM_DIER_CC3IE +#define FUEL4_TIMER_ENABLE() (TIM3)->SR = ~TIM_FLAG_CC4; (TIM3)->DIER |= TIM_DIER_CC4IE #define FUEL1_TIMER_DISABLE() (TIM3)->DIER &= ~TIM_DIER_CC1IE #define FUEL2_TIMER_DISABLE() (TIM3)->DIER &= ~TIM_DIER_CC2IE #define FUEL3_TIMER_DISABLE() (TIM3)->DIER &= ~TIM_DIER_CC3IE #define FUEL4_TIMER_DISABLE() (TIM3)->DIER &= ~TIM_DIER_CC4IE -#define IGN1_TIMER_ENABLE() (TIM2)->CR1 |= TIM_CR1_CEN; (TIM2)->SR = ~TIM_FLAG_CC1; (TIM2)->DIER |= TIM_DIER_CC1IE -#define IGN2_TIMER_ENABLE() (TIM2)->CR1 |= TIM_CR1_CEN; (TIM2)->SR = ~TIM_FLAG_CC2; (TIM2)->DIER |= TIM_DIER_CC2IE -#define IGN3_TIMER_ENABLE() (TIM2)->CR1 |= TIM_CR1_CEN; (TIM2)->SR = ~TIM_FLAG_CC3; (TIM2)->DIER |= TIM_DIER_CC3IE -#define IGN4_TIMER_ENABLE() (TIM2)->CR1 |= TIM_CR1_CEN; (TIM2)->SR = ~TIM_FLAG_CC4; (TIM2)->DIER |= TIM_DIER_CC4IE +#define IGN1_TIMER_ENABLE() (TIM2)->SR = ~TIM_FLAG_CC1; (TIM2)->DIER |= TIM_DIER_CC1IE +#define IGN2_TIMER_ENABLE() (TIM2)->SR = ~TIM_FLAG_CC2; (TIM2)->DIER |= TIM_DIER_CC2IE +#define IGN3_TIMER_ENABLE() (TIM2)->SR = ~TIM_FLAG_CC3; (TIM2)->DIER |= TIM_DIER_CC3IE +#define IGN4_TIMER_ENABLE() (TIM2)->SR = ~TIM_FLAG_CC4; (TIM2)->DIER |= TIM_DIER_CC4IE #define IGN1_TIMER_DISABLE() (TIM2)->DIER &= ~TIM_DIER_CC1IE #define IGN2_TIMER_DISABLE() (TIM2)->DIER &= ~TIM_DIER_CC2IE @@ -217,20 +216,20 @@ extern "C" char* sbrk(int incr); #define IGN4_TIMER_DISABLE() (TIM2)->DIER &= ~TIM_DIER_CC4IE -#define FUEL5_TIMER_ENABLE() (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->SR = ~TIM_FLAG_CC1; (TIM5)->DIER |= TIM_DIER_CC1IE -#define FUEL6_TIMER_ENABLE() (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->SR = ~TIM_FLAG_CC2; (TIM5)->DIER |= TIM_DIER_CC2IE -#define FUEL7_TIMER_ENABLE() (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->SR = ~TIM_FLAG_CC3; (TIM5)->DIER |= TIM_DIER_CC3IE -#define FUEL8_TIMER_ENABLE() (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->CR1 |= TIM_CR1_CEN; (TIM5)->SR = ~TIM_FLAG_CC4; (TIM5)->DIER |= TIM_DIER_CC4IE +#define FUEL5_TIMER_ENABLE() (TIM5)->SR = ~TIM_FLAG_CC1; (TIM5)->DIER |= TIM_DIER_CC1IE +#define FUEL6_TIMER_ENABLE() (TIM5)->SR = ~TIM_FLAG_CC2; (TIM5)->DIER |= TIM_DIER_CC2IE +#define FUEL7_TIMER_ENABLE() (TIM5)->SR = ~TIM_FLAG_CC3; (TIM5)->DIER |= TIM_DIER_CC3IE +#define FUEL8_TIMER_ENABLE() (TIM5)->SR = ~TIM_FLAG_CC4; (TIM5)->DIER |= TIM_DIER_CC4IE #define FUEL5_TIMER_DISABLE() (TIM5)->DIER &= ~TIM_DIER_CC1IE #define FUEL6_TIMER_DISABLE() (TIM5)->DIER &= ~TIM_DIER_CC2IE #define FUEL7_TIMER_DISABLE() (TIM5)->DIER &= ~TIM_DIER_CC3IE #define FUEL8_TIMER_DISABLE() (TIM5)->DIER &= ~TIM_DIER_CC4IE -#define IGN5_TIMER_ENABLE() (TIM4)->CR1 |= TIM_CR1_CEN; (TIM4)->SR = ~TIM_FLAG_CC1; (TIM4)->DIER |= TIM_DIER_CC1IE -#define IGN6_TIMER_ENABLE() (TIM4)->CR1 |= TIM_CR1_CEN; (TIM4)->SR = ~TIM_FLAG_CC2; (TIM4)->DIER |= TIM_DIER_CC2IE -#define IGN7_TIMER_ENABLE() (TIM4)->CR1 |= TIM_CR1_CEN; (TIM4)->SR = ~TIM_FLAG_CC3; (TIM4)->DIER |= TIM_DIER_CC3IE -#define IGN8_TIMER_ENABLE() (TIM4)->CR1 |= TIM_CR1_CEN; (TIM4)->SR = ~TIM_FLAG_CC4; (TIM4)->DIER |= TIM_DIER_CC4IE +#define IGN5_TIMER_ENABLE() (TIM4)->SR = ~TIM_FLAG_CC1; (TIM4)->DIER |= TIM_DIER_CC1IE +#define IGN6_TIMER_ENABLE() (TIM4)->SR = ~TIM_FLAG_CC2; (TIM4)->DIER |= TIM_DIER_CC2IE +#define IGN7_TIMER_ENABLE() (TIM4)->SR = ~TIM_FLAG_CC3; (TIM4)->DIER |= TIM_DIER_CC3IE +#define IGN8_TIMER_ENABLE() (TIM4)->SR = ~TIM_FLAG_CC4; (TIM4)->DIER |= TIM_DIER_CC4IE #define IGN5_TIMER_DISABLE() (TIM4)->DIER &= ~TIM_DIER_CC1IE #define IGN6_TIMER_DISABLE() (TIM4)->DIER &= ~TIM_DIER_CC2IE @@ -244,13 +243,13 @@ extern "C" char* sbrk(int incr); *********************************************************************************************************** * Auxiliaries */ -#define ENABLE_BOOST_TIMER() (TIM1)->SR = ~TIM_FLAG_CC2; (TIM1)->DIER |= TIM_DIER_CC2IE; (TIM1)->CR1 |= TIM_CR1_CEN; +#define ENABLE_BOOST_TIMER() (TIM1)->SR = ~TIM_FLAG_CC2; (TIM1)->DIER |= TIM_DIER_CC2IE #define DISABLE_BOOST_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC2IE -#define ENABLE_VVT_TIMER() (TIM1)->SR = ~TIM_FLAG_CC3; (TIM1)->DIER |= TIM_DIER_CC3IE; (TIM1)->CR1 |= TIM_CR1_CEN; +#define ENABLE_VVT_TIMER() (TIM1)->SR = ~TIM_FLAG_CC3; (TIM1)->DIER |= TIM_DIER_CC3IE #define DISABLE_VVT_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC3IE -#define ENABLE_FAN_TIMER() (TIM1)->SR = ~TIM_FLAG_CC1; (TIM1)->DIER |= TIM_DIER_CC1IE; (TIM1)->CR1 |= TIM_CR1_CEN; +#define ENABLE_FAN_TIMER() (TIM1)->SR = ~TIM_FLAG_CC1; (TIM1)->DIER |= TIM_DIER_CC1IE #define DISABLE_FAN_TIMER() (TIM1)->DIER &= ~TIM_DIER_CC1IE #define BOOST_TIMER_COMPARE (TIM1)->CCR2 @@ -267,7 +266,7 @@ extern "C" char* sbrk(int incr); #define IDLE_COUNTER (TIM1)->CNT #define IDLE_COMPARE (TIM1)->CCR4 -#define IDLE_TIMER_ENABLE() (TIM1)->SR = ~TIM_FLAG_CC4; (TIM1)->DIER |= TIM_DIER_CC4IE; (TIM1)->CR1 |= TIM_CR1_CEN; +#define IDLE_TIMER_ENABLE() (TIM1)->SR = ~TIM_FLAG_CC4; (TIM1)->DIER |= TIM_DIER_CC4IE #define IDLE_TIMER_DISABLE() (TIM1)->DIER &= ~TIM_DIER_CC4IE /* diff --git a/speeduino/board_stm32_official.ino b/speeduino/board_stm32_official.ino index 565c0a3c..a336ef03 100644 --- a/speeduino/board_stm32_official.ino +++ b/speeduino/board_stm32_official.ino @@ -94,10 +94,7 @@ STM32RTC& rtc = STM32RTC::getInstance(); * Real Time clock for datalogging/time stamping */ #ifdef RTC_ENABLED - //Check if RTC time has been set earlier. If yes, RTC will use LSE_CLOCK. If not, default LSI_CLOCK is used, to prevent hanging on boot. - if (rtc.isTimeSet()) { - rtc.setClockSource(STM32RTC::LSE_CLOCK); //Initialise external clock for RTC if clock is set. That is the only clock running of VBAT - } + rtc.setClockSource(STM32RTC::LSE_CLOCK); //Initialise external clock for RTC. That is the only clock running of VBAT rtc.begin(); // initialise RTC 24H format #endif /* @@ -281,7 +278,34 @@ STM32RTC& rtc = STM32RTC::getInstance(); Timer4.attachInterrupt(4, ignitionSchedule8Interrupt); #endif - + Timer1.resume(); + DISABLE_BOOST_TIMER(); //Make sure it is disabled. It's is enabled by default on the library + DISABLE_VVT_TIMER(); //Make sure it is disabled. It's is enabled by default on the library + IDLE_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + Timer2.resume(); + IGN1_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + IGN2_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + IGN3_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + IGN4_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + Timer3.resume(); + FUEL1_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + FUEL2_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + FUEL3_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + FUEL4_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + #if (IGN_CHANNELS >= 5) + Timer4.resume(); + IGN5_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + IGN6_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + IGN7_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + IGN8_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + #endif + #if (INJ_CHANNELS >= 5) + Timer5.resume(); + FUEL5_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + FUEL6_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + FUEL7_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + FUEL8_TIMER_DISABLE(); //Make sure it is disabled. It's is enabled by default on the library + #endif } uint16_t freeRam() diff --git a/speeduino/board_teensy35.h b/speeduino/board_teensy35.h index 45e0d789..88dcf0b1 100644 --- a/speeduino/board_teensy35.h +++ b/speeduino/board_teensy35.h @@ -16,7 +16,6 @@ #define COMPARE_TYPE uint16_t #define COUNTER_TYPE uint16_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) - #define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. #define SD_LOGGING //SD logging enabled by default for Teensy 3.5 as it has the slot built in #define BOARD_MAX_DIGITAL_PINS 34 #define BOARD_MAX_IO_PINS 34 //digital pins + analog channels + 1 diff --git a/speeduino/board_teensy35.ino b/speeduino/board_teensy35.ino index 0ca5e99a..b6cd84f5 100644 --- a/speeduino/board_teensy35.ino +++ b/speeduino/board_teensy35.ino @@ -23,7 +23,7 @@ void initBoard() *********************************************************************************************************** * Idle */ - if ((configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL)) + if ((configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL)) { //FlexTimer 2, compare channel 0 is used for idle FTM2_MODE |= FTM_MODE_WPDIS; // Write Protection Disable diff --git a/speeduino/board_teensy41.h b/speeduino/board_teensy41.h index 2e489725..b3e7d6a6 100644 --- a/speeduino/board_teensy41.h +++ b/speeduino/board_teensy41.h @@ -10,19 +10,17 @@ uint16_t freeRam(); void doSystemReset(); void jumpToBootloader(); - time_t getTeensy3Time(); #define PORT_TYPE uint32_t //Size of the port variables #define PINMASK_TYPE uint32_t #define COMPARE_TYPE uint32_t #define COUNTER_TYPE uint32_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) - #define FPU_MAX_SIZE 32 //Size of the FPU buffer. 0 means no FPU. + #define SD_LOGGING //SD logging enabled by default for Teensy 4.1 as it has the slot built in #define BOARD_MAX_DIGITAL_PINS 34 #define BOARD_MAX_IO_PINS 34 //digital pins + analog channels + 1 #define EEPROM_LIB_H typedef int eeprom_address_t; - //#define RTC_ENABLED - //#define SD_LOGGING //SD logging enabled by default for Teensy 4.1 as it has the slot built in + #define RTC_ENABLED #define RTC_LIB_H "TimeLib.h" #define SD_CONFIG SdioConfig(FIFO_SDIO) //Set Teensy to use SDIO in FIFO mode. This is the fastest SD mode on Teensy as it offloads most of the writes diff --git a/speeduino/board_teensy41.ino b/speeduino/board_teensy41.ino index 00efecad..0a903660 100644 --- a/speeduino/board_teensy41.ino +++ b/speeduino/board_teensy41.ino @@ -35,7 +35,7 @@ void initBoard() *********************************************************************************************************** * Idle */ - if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OLCL)) + if( (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_OL) || (configPage6.iacAlgorithm == IAC_ALGORITHM_PWM_CL) ) { PIT_TCTRL0 = 0; PIT_TCTRL0 |= PIT_TCTRL_TIE; // enable Timer 1 interrupts @@ -266,12 +266,6 @@ uint16_t freeRam() return (uint16_t)stackTop - heapTop; } -//This function is used for attempting to set the RTC time during compile -time_t getTeensy3Time() -{ - return Teensy3Clock.get(); -} - void doSystemReset() { return; } void jumpToBootloader() { return; } diff --git a/speeduino/board_template.h b/speeduino/board_template.h index cdaf6c5d..71cccc3b 100644 --- a/speeduino/board_template.h +++ b/speeduino/board_template.h @@ -9,7 +9,6 @@ #define PORT_TYPE uint32_t //Size of the port variables (Eg inj1_pin_port). Most systems use a byte, but SAMD21 and possibly others are a 32-bit unsigned int #define PINMASK_TYPE uint32_t #define SERIAL_BUFFER_SIZE 517 //Size of the serial buffer used by new comms protocol. For SD transfers this must be at least 512 + 1 (flag) + 4 (sector) - #define FPU_MAX_SIZE 0 //Size of the FPU buffer. 0 means no FPU. #define BOARD_MAX_IO_PINS 52 //digital pins + analog channels + 1 #define BOARD_MAX_DIGITAL_PINS 52 //Pretty sure this isn't right #define EEPROM_LIB_H //The name of the file that provides the EEPROM class diff --git a/speeduino/canBroadcast.ino b/speeduino/canBroadcast.ino index 04dec41d..2ef6c7ad 100644 --- a/speeduino/canBroadcast.ino +++ b/speeduino/canBroadcast.ino @@ -74,7 +74,7 @@ void DashMessage(uint16_t DashMessageID) outMsg.buf[0] = 0x00; //Check engine light (binary 10), Cruise light (binary 1000), EML (binary 10000). outMsg.buf[1] = 0x00; //LSB Fuel consumption outMsg.buf[2] = 0x00; //MSB Fuel Consumption - if (currentStatus.coolant > 159) { outMsg.buf[3] = 0x08; } //Turn on overheat light if coolant temp hits 120 degrees celsius. + if (currentStatus.coolant > 159) { outMsg.buf[3] = 0x08; } //Turn on overheat light if coolant temp hits 120 degrees celcius. else { outMsg.buf[3] = 0x00; } //Overheat light off at normal engine temps. outMsg.buf[4] = 0x7E; //this is oil temp break; @@ -113,4 +113,4 @@ void DashMessage(uint16_t DashMessageID) break; } } -#endif +#endif \ No newline at end of file diff --git a/speeduino/cancomms.ino b/speeduino/cancomms.ino index f5f9806c..ebe83c6c 100644 --- a/speeduino/cancomms.ino +++ b/speeduino/cancomms.ino @@ -73,7 +73,7 @@ void secondserial_Command() Glow = Gdata[(configPage9.caninput_source_start_byte[destcaninchannel]&7)]; if ((BIT_CHECK(configPage9.caninput_source_num_bytes,destcaninchannel) > 0)) //if true then num bytes is 2 { - if ((configPage9.caninput_source_start_byte[destcaninchannel]&7) < 8) //you can't have a 2 byte value starting at byte 7(8 on the list) + if ((configPage9.caninput_source_start_byte[destcaninchannel]&7) < 8) //you cant have a 2 byte value starting at byte 7(8 on the list) { Ghigh = Gdata[((configPage9.caninput_source_start_byte[destcaninchannel]&7)+1)]; } @@ -423,7 +423,7 @@ void sendCancommand(uint8_t cmdtype, uint16_t canaddress, uint8_t candata1, uint break; case 2: // requests via serial3 - CANSerial.print("R"); //send "R" to request data from the sourcecanAddress whose value is sent next + CANSerial.print("R"); //send "R" to request data from the sourcecanAddress whos value is sent next CANSerial.write(candata1); //the currentStatus.current_caninchannel CANSerial.write(lowByte(sourcecanAddress) ); //send lsb first CANSerial.write(highByte(sourcecanAddress) ); diff --git a/speeduino/comms.cpp b/speeduino/comms.cpp index a9eb6098..9c25442e 100644 --- a/speeduino/comms.cpp +++ b/speeduino/comms.cpp @@ -451,8 +451,8 @@ void processSerialCommand() case 'Q': // send code version { - char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','1','0','-','d','e','v'} ; //Note no null terminator in array and statu variable at the start - //char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','7'} ; //Note no null terminator in array and statu variable at the start + char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','4','-','d','e','v'} ; //Note no null terminator in array and statu variable at the start + //char productString[] = { SERIAL_RC_OK, 's','p','e','e','d','u','i','n','o',' ','2','0','2','2','0','4'} ; //Note no null terminator in array and statu variable at the start sendSerialPayload(&productString, sizeof(productString)); break; } @@ -527,7 +527,7 @@ void processSerialCommand() serialPayload[13] = 0; serialPayload[14] = 0; - //Unknown purpose for last 2 bytes + //Unkown purpose for last 2 bytes serialPayload[15] = 0; serialPayload[16] = 0; @@ -601,8 +601,8 @@ void processSerialCommand() case 'S': // send code version { - byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '.', '1', '0', '-', 'd', 'e', 'v'}; - //byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '0', '7'}; + byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '.', '0', '4', '-', 'd', 'e', 'v'}; + //byte productString[] = { SERIAL_RC_OK, 'S', 'p', 'e', 'e', 'd', 'u', 'i', 'n', 'o', ' ', '2', '0', '2', '2', '0', '2'}; sendSerialPayload(&productString, sizeof(productString)); currentStatus.secl = 0; //This is required in TS3 due to its stricter timings break; diff --git a/speeduino/comms.h b/speeduino/comms.h index ea086f9a..9e84a2c4 100644 --- a/speeduino/comms.h +++ b/speeduino/comms.h @@ -73,7 +73,7 @@ extern bool serialWriteInProgress; extern bool serialReceivePending; /**< Whether or not a serial request has only been partially received. This occurs when a the length has been received in the serial buffer, but not all of the payload or CRC has yet been received. */ -void parseSerial();//This is the heart of the Command Line Interpreter. All that needed to be done was to make it human readable. +void parseSerial();//This is the heart of the Command Line Interpeter. All that needed to be done was to make it human readable. void processSerialCommand(); void sendSerialReturnCode(byte returnCode); void sendSerialPayload(void*, uint16_t payloadLength); diff --git a/speeduino/comms_legacy.cpp b/speeduino/comms_legacy.cpp index 626adbb3..0aa503cc 100644 --- a/speeduino/comms_legacy.cpp +++ b/speeduino/comms_legacy.cpp @@ -320,8 +320,7 @@ void legacySerialCommand() break; case 'Q': // send code version - //Serial.print(F("speeduino 202207")); - Serial.print(F("speeduino 202210-dev")); + Serial.print(F("speeduino 202204-dev")); break; case 'r': //New format for the optimised OutputChannels @@ -353,8 +352,7 @@ void legacySerialCommand() break; case 'S': // send code version - //Serial.print(F("Speeduino 2022.07")); - Serial.print(F("Speeduino 2022.10-dev")); + Serial.print(F("Speeduino 2022.04-dev")); currentStatus.secl = 0; //This is required in TS3 due to its stricter timings break; @@ -1045,11 +1043,6 @@ 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/corrections.ino b/speeduino/corrections.ino index 366554f1..50c7f423 100644 --- a/speeduino/corrections.ino +++ b/speeduino/corrections.ino @@ -70,6 +70,78 @@ void initialiseCorrections() Calls all the other corrections functions and combines their results. This is the only function that should be called from anywhere outside the file */ +uint16_t correctionsFuel1() +{ + #define MAX_CORRECTIONS 3 //The maximum number of corrections allowed before the sum is reprocessed + uint32_t sumCorrections = 100; + byte activeCorrections = 0; + uint16_t result; //temporary variable to store the result of each corrections function + + //The values returned by each of the correction functions are multiplied together and then divided back to give a single 0-255 value. + currentStatus.wueCorrection = correctionWUE(); + if (currentStatus.wueCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.wueCorrection); activeCorrections++; } + + result = correctionASE(); + if (result != 100) { sumCorrections = (sumCorrections * result); activeCorrections++; } + + result = correctionCranking(); + if (result != 100) { sumCorrections = (sumCorrections * result); activeCorrections++; } + if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } // Need to check this to ensure that sumCorrections doesn't overflow. Can occur when the number of corrections is greater than 3 (Which is 100^4) as 100^5 can overflow + + currentStatus.AEamount = correctionAccel(); + if (configPage2.aeApplyMode == AE_MODE_MULTIPLIER) + { + if (currentStatus.AEamount != 100) { sumCorrections = (sumCorrections * currentStatus.AEamount); activeCorrections++; } + if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } + } + + result = correctionFloodClear(); + if (result != 100) { sumCorrections = (sumCorrections * result); activeCorrections++; } + if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } + + currentStatus.egoCorrection = correctionAFRClosedLoop(); + if (currentStatus.egoCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.egoCorrection); activeCorrections++; } + if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } + + currentStatus.batCorrection = correctionBatVoltage(); + if (configPage2.battVCorMode == BATTV_COR_MODE_OPENTIME) + { + inj_opentime_uS = configPage2.injOpen * currentStatus.batCorrection; // Apply voltage correction to injector open time. + } + if (configPage2.battVCorMode == BATTV_COR_MODE_WHOLE) + { + if (currentStatus.batCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.batCorrection); activeCorrections++; } + if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } + } + + currentStatus.iatCorrection = correctionIATDensity(); + if (currentStatus.iatCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.iatCorrection); activeCorrections++; } + if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } + + currentStatus.baroCorrection = correctionBaro(); + if (currentStatus.baroCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.baroCorrection); activeCorrections++; } + if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } + + currentStatus.flexCorrection = correctionFlex(); + if (currentStatus.flexCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.flexCorrection); activeCorrections++; } + if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } + + currentStatus.fuelTempCorrection = correctionFuelTemp(); + if (currentStatus.fuelTempCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.fuelTempCorrection); activeCorrections++; } + if (activeCorrections == MAX_CORRECTIONS) { sumCorrections = sumCorrections / powint(100,activeCorrections); activeCorrections = 0; } + + currentStatus.launchCorrection = correctionLaunch(); + if (currentStatus.launchCorrection != 100) { sumCorrections = (sumCorrections * currentStatus.launchCorrection); activeCorrections++; } + + bitWrite(currentStatus.status1, BIT_STATUS1_DFCO, correctionDFCO()); + if ( BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) == 1 ) { sumCorrections = 0; } + + sumCorrections = sumCorrections / powint(100,activeCorrections); + + if(sumCorrections > 1500) { sumCorrections = 1500; } //This is the maximum allowable increase during cranking + return (uint16_t)sumCorrections; +} + uint16_t correctionsFuel() { uint32_t sumCorrections = 100; @@ -79,8 +151,8 @@ uint16_t correctionsFuel() currentStatus.wueCorrection = correctionWUE(); if (currentStatus.wueCorrection != 100) { sumCorrections = div100(sumCorrections * currentStatus.wueCorrection); } - currentStatus.ASEValue = correctionASE(); - if (currentStatus.ASEValue != 100) { sumCorrections = div100(sumCorrections * currentStatus.ASEValue); } + result = correctionASE(); + if (result != 100) { sumCorrections = div100(sumCorrections * result); } result = correctionCranking(); if (result != 100) { sumCorrections = div100(sumCorrections * result); } @@ -141,7 +213,7 @@ static inline byte correctionsFuel_new() //The values returned by each of the correction functions are multiplied together and then divided back to give a single 0-255 value. currentStatus.wueCorrection = correctionWUE(); numCorrections++; - currentStatus.ASEValue = correctionASE(); numCorrections++; + uint16_t correctionASEvalue = correctionASE(); numCorrections++; uint16_t correctionCrankingValue = correctionCranking(); numCorrections++; currentStatus.AEamount = correctionAccel(); numCorrections++; uint8_t correctionFloodClearValue = correctionFloodClear(); numCorrections++; @@ -157,7 +229,7 @@ static inline byte correctionsFuel_new() if ( BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) == 1 ) { sumCorrections = 0; } sumCorrections = currentStatus.wueCorrection \ - + currentStatus.ASEValue \ + + correctionASEvalue \ + correctionCrankingValue \ + currentStatus.AEamount \ + correctionFloodClearValue \ @@ -216,61 +288,52 @@ uint16_t correctionCranking() unsigned long taperStart = (unsigned long) crankingValue * 100 / currentStatus.ASEValue; crankingValue = (uint16_t) map(crankingEnrichTaper, 0, configPage10.crankingEnrichTaper, taperStart, 100); //Taper from start value to 100% if (crankingValue < 100) { crankingValue = 100; } //Sanity check - if( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) ) { crankingEnrichTaper++; } + if( BIT_CHECK(TIMER_mask, BIT_TIMER_10HZ) ) { crankingEnrichTaper++; } } return crankingValue; } -/** After Start Enrichment calculation. +/** Afer Start Enrichment calculation. * This is a short period (Usually <20 seconds) immediately after the engine first fires (But not when cranking) * where an additional amount of fuel is added (Over and above the WUE amount). * * @return uint8_t The After Start Enrichment modifier as a %. 100% = No modification. - */ + */ byte correctionASE() { - int16_t ASEValue = currentStatus.ASEValue; + int16_t ASEValue; //Two checks are required: //1) Is the engine run time less than the configured ase time //2) Make sure we're not still cranking - if( BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) != true ) + if ( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) || (currentStatus.ASEValue == 0) ) { - if ( BIT_CHECK(LOOP_TIMER, BIT_TIMER_10HZ) || (currentStatus.ASEValue == 0) ) + if ( (currentStatus.runSecs < (table2D_getValue(&ASECountTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET))) && !(BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) ) { - if ( (currentStatus.runSecs < (table2D_getValue(&ASECountTable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET))) && !(BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) ) + BIT_SET(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as active. + ASEValue = 100 + table2D_getValue(&ASETable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); + aseTaper = 0; + } + else + { + if ( (!BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) && (aseTaper < configPage2.aseTaperTime) ) //Cranking check needs to be here also, so cranking and afterstart enrichments won't run simultaneously { BIT_SET(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as active. - ASEValue = 100 + table2D_getValue(&ASETable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET); - aseTaper = 0; + ASEValue = 100 + map(aseTaper, 0, configPage2.aseTaperTime, table2D_getValue(&ASETable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET), 0); + aseTaper++; } else { - if ( aseTaper < configPage2.aseTaperTime ) //Check if we've reached the end of the taper time - { - BIT_SET(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as active. - ASEValue = 100 + map(aseTaper, 0, configPage2.aseTaperTime, table2D_getValue(&ASETable, currentStatus.coolant + CALIBRATION_TEMPERATURE_OFFSET), 0); - aseTaper++; - } - else - { - BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as inactive. - ASEValue = 100; - } + BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as inactive. + ASEValue = 100; } - - //Safety checks - if(ASEValue > 255) { ASEValue = 255; } - if(ASEValue < 0) { ASEValue = 0; } - ASEValue = (byte)ASEValue; } + + //Safety checks + if(ASEValue > 255) { ASEValue = 255; } + if(ASEValue < 0) { ASEValue = 0; } + currentStatus.ASEValue = (byte)ASEValue; } - else - { - //Engine is cranking, ASE disabled - BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ASE); //Mark ASE as inactive. - ASEValue = 100; - } - return ASEValue; + return currentStatus.ASEValue; } /** Acceleration enrichment correction calculation. @@ -302,7 +365,7 @@ uint16_t correctionAccel() else if(configPage2.aeMode == AE_MODE_TPS) { //Get the TPS rate change - TPS_change = (currentStatus.TPS - currentStatus.TPSlast); + TPS_change = (currentStatus.TPS - TPSlast); //TPS_rateOfChange = ldiv(1000000, (TPS_time - TPSlast_time)).quot * TPS_change; //This is the % per second that the TPS has moved TPS_rateOfChange = (TPS_READ_FREQUENCY * TPS_change) / 2; //This is the % per second that the TPS has moved, adjusted for the 0.5% resolution of the TPS if(TPS_rateOfChange >= 0) { currentStatus.tpsDOT = TPS_rateOfChange / 10; } //The TAE bins are divided by 10 in order to allow them to be stored in a byte @@ -368,7 +431,7 @@ uint16_t correctionAccel() else { int16_t taperRange = trueTaperMax - trueTaperMin; - int16_t taperPercent = ((currentStatus.RPM - trueTaperMin) * 100UL) / taperRange; //The percentage of the way through the RPM taper range + int16_t taperPercent = ((currentStatus.RPM - trueTaperMin) * 100) / taperRange; //The percentage of the way through the RPM taper range accelValue = percentage((100-taperPercent), accelValue); //Calculate the above percentage of the calculated accel amount. } } @@ -427,7 +490,7 @@ uint16_t correctionAccel() else { int16_t taperRange = trueTaperMax - trueTaperMin; - int16_t taperPercent = ((currentStatus.RPM - trueTaperMin) * 100UL) / taperRange; //The percentage of the way through the RPM taper range + int16_t taperPercent = ((currentStatus.RPM - trueTaperMin) * 100) / taperRange; //The percentage of the way through the RPM taper range accelValue = percentage( (100 - taperPercent), accelValue); //Calculate the above percentage of the calculated accel amount. } } @@ -605,7 +668,7 @@ byte correctionAFRClosedLoop() if( (currentStatus.runSecs > configPage6.ego_sdelay) || (configPage2.incorporateAFR == true) ) { currentStatus.afrTarget = get3DTableValue(&afrTable, currentStatus.fuelLoad, currentStatus.RPM); } //Perform the target lookup } - if((configPage6.egoType > 0) && (BIT_CHECK(currentStatus.status1, BIT_STATUS1_DFCO) != 1 ) ) //egoType of 0 means no O2 sensor. If DFCO is active do not run the ego controllers to prevent interator wind-up. + if( configPage6.egoType > 0 ) //egoType of 0 means no O2 sensor { AFRValue = currentStatus.egoCorrection; //Need to record this here, just to make sure the correction stays 'on' even if the nextCycle count isn't ready diff --git a/speeduino/crankMaths.ino b/speeduino/crankMaths.ino index 00200400..687dc37c 100644 --- a/speeduino/crankMaths.ino +++ b/speeduino/crankMaths.ino @@ -21,7 +21,7 @@ int rpmDelta; * * Currently 4 methods are planned and/or available: * 1) Last interval based on a full revolution -* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependent) +* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependant) * 3) Closed loop error correction (Alpha-beta filter) * 4) 2nd derivative prediction (Speed + acceleration) */ @@ -41,10 +41,9 @@ unsigned long angleToTime(int16_t angle, byte method) { noInterrupts(); unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime); - uint16_t tempTriggerToothAngle = triggerToothAngle; // triggerToothAngle is set by interrupts interrupts(); - returnTime = ( (toothTime * angle) / tempTriggerToothAngle ); + returnTime = ( (toothTime * angle) / triggerToothAngle ); } else { returnTime = angleToTime(angle, CRANKMATH_METHOD_INTERVAL_REV); } //Safety check. This can occur if the last tooth seen was outside the normal pattern etc } @@ -56,7 +55,7 @@ unsigned long angleToTime(int16_t angle, byte method) * Convert a time (uS) into an angle at current speed * Currently 4 methods are planned and/or available: * 1) Last interval based on a full revolution -* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependent) +* 2) Last interval based on the time between the last 2 teeth (Crank Pattern dependant) * 3) Closed loop error correction (Alpha-beta filter) * 4) 2nd derivative prediction (Speed + acceleration) */ @@ -77,10 +76,9 @@ uint16_t timeToAngle(unsigned long time, byte method) { noInterrupts(); unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime); - uint16_t tempTriggerToothAngle = triggerToothAngle; // triggerToothAngle is set by interrupts interrupts(); - returnAngle = ( (unsigned long)(time * tempTriggerToothAngle) / toothTime ); + returnAngle = ( (unsigned long)(time * triggerToothAngle) / toothTime ); } else { returnAngle = timeToAngle(time, CRANKMATH_METHOD_INTERVAL_REV); } //Safety check. This can occur if the last tooth seen was outside the normal pattern etc } @@ -136,7 +134,7 @@ void doCrankSpeedCalcs() rpmDelta = (toothDeltaV << 10) / (6 * toothDeltaT); } - timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpmDelta).quot; //This gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low resolution triggers + timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpmDelta).quot; //This give accuracy down to 0.1 of a degree and can provide noticably better timing results on low res triggers timePerDegree = timePerDegreex16 / 16; } else @@ -157,10 +155,10 @@ void doCrankSpeedCalcs() { //long timeThisRevolution = (micros_safe() - toothOneTime); interrupts(); - //Take into account any likely acceleration that has occurred since the last full revolution completed: + //Take into account any likely accleration that has occurred since the last full revolution completed: //long rpm_adjust = (timeThisRevolution * (long)currentStatus.rpmDOT) / 1000000; long rpm_adjust = 0; - timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpm_adjust).quot; //The use of a x16 value gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low resolution triggers + timePerDegreex16 = ldiv( 2666656L, currentStatus.RPM + rpm_adjust).quot; //The use of a x16 value gives accuracy down to 0.1 of a degree and can provide noticeably better timing results on low res triggers timePerDegree = timePerDegreex16 / 16; } } diff --git a/speeduino/decoders.h b/speeduino/decoders.h index 8ce27001..c968b55b 100644 --- a/speeduino/decoders.h +++ b/speeduino/decoders.h @@ -233,7 +233,7 @@ extern volatile unsigned int secondaryToothCount; //Used for identifying the cur extern volatile unsigned long secondaryLastToothTime; //The time (micros()) that the last tooth was registered (Cam input) extern volatile unsigned long secondaryLastToothTime1; //The time (micros()) that the last tooth was registered (Cam input) -extern uint16_t triggerActualTeeth; +extern volatile uint16_t triggerActualTeeth; extern volatile unsigned long triggerFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) extern volatile unsigned long triggerSecFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) for the secondary input extern volatile bool validTrigger; //Is set true when the last trigger (Primary or secondary) was valid (ie passed filters) diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index bf9c7569..72d9a04e 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -76,7 +76,7 @@ volatile unsigned int secondaryToothCount; //Used for identifying the current se volatile unsigned long secondaryLastToothTime = 0; //The time (micros()) that the last tooth was registered (Cam input) volatile unsigned long secondaryLastToothTime1 = 0; //The time (micros()) that the last tooth was registered (Cam input) -uint16_t triggerActualTeeth; +volatile uint16_t triggerActualTeeth; volatile unsigned long triggerFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) volatile unsigned long triggerSecFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) for the secondary input volatile bool validTrigger; //Is set true when the last trigger (Primary or secondary) was valid (ie passed filters) @@ -3227,7 +3227,7 @@ void triggerSetEndTeeth_Daihatsu() /** Harley Davidson (V2) with 2 unevenly Spaced Teeth. Within the decoder code, the sync tooth is referred to as tooth #1. Derived from GMX7 and adapted for Harley. -Only rising Edge is used for simplicity.The second input is ignored, as it does not help to resolve cam position. +Only rising Edge is used for simplicity.The second input is ignored, as it does not help to desolve cam position. * @defgroup dec_harley Harley Davidson * @{ */ @@ -4618,7 +4618,6 @@ void triggerPri_Vmax() toothOneTime = curTime; currentStatus.hasSync = true; setFilter((curGap/1.75));//Angle to this tooth is 70, next is in 40, compensating. - currentStatus.startRevolutions++; //Counter } else if (toothCurrentCount==2) { @@ -4652,6 +4651,7 @@ void triggerPri_Vmax() } toothLastMinusOneToothTime = toothLastToothTime; toothLastToothTime = curTime; + currentStatus.startRevolutions++; //Counter if (triggerFilterTime > 50000){//The first pulse seen triggerFilterTime = 0; } diff --git a/speeduino/engineProtection.h b/speeduino/engineProtection.h index d98f5312..09a05b43 100644 --- a/speeduino/engineProtection.h +++ b/speeduino/engineProtection.h @@ -2,6 +2,7 @@ #define HARD_REV_FIXED 1 #define HARD_REV_COOLANT 2 + byte checkEngineProtect(); byte checkRevLimit(); byte checkBoostLimit(); diff --git a/speeduino/engineProtection.ino b/speeduino/engineProtection.ino index 87f18c54..5a87ed5a 100644 --- a/speeduino/engineProtection.ino +++ b/speeduino/engineProtection.ino @@ -112,98 +112,7 @@ byte checkOilPressureLimit() byte checkAFRLimit() { - static bool checkAFRLimitActive = false; - static bool afrProtectCountEnabled = false; - static unsigned long afrProtectCount = 0; - static constexpr char X2_MULTIPLIER = 2; - static constexpr char X100_MULTIPLIER = 100; - - /* - To use this function, a wideband sensor is required. - - First of all, check whether engine protection is enabled, - thereafter check whether AFR protection is enabled and at last - if wideband sensor is used. - - After confirmation, the following conditions has to be met: - - MAP above x kPa - - RPM above x - - TPS above x % - - AFR threshold (AFR target + defined maximum deviation) - - Time before cut - - See afrProtect variables in globals.h for more information. - - If all conditions above are true, a specified time delay is starting - to count down in which leads to the engine protection function - to be activated using selected protection cut method (e.g. ignition, - fuel or both). - - For reactivation, the following condition has to be met: - - TPS below x % - */ - - /* - Do 3 checks here; - - whether engine protection is enabled - - whether AFR protection is enabled - - whether wideband sensor is used - */ - if(configPage6.engineProtectType != PROTECT_CUT_OFF && configPage9.afrProtectEnabled && configPage6.egoType == EGO_TYPE_WIDE) { - /* Conditions */ - bool mapCondition = (currentStatus.MAP >= (configPage9.afrProtectMinMAP * X2_MULTIPLIER)) ? true : false; - bool rpmCondition = (currentStatus.RPMdiv100 >= configPage9.afrProtectMinRPM) ? true : false; - bool tpsCondition = (currentStatus.TPS >= configPage9.afrProtectMinTPS) ? true : false; - - /* - Depending on selected mode, this could either be fixed AFR value or a - value set to be the maximum deviation from AFR target table. - - 1 = fixed value mode, 2 = target table mode - */ - bool afrCondition; - switch(configPage9.afrProtectEnabled) - { - case 1: afrCondition = (currentStatus.O2 >= configPage9.afrProtectDeviation) ? true : false; break; /* Fixed value */ - case 2: afrCondition = (currentStatus.O2 >= (currentStatus.afrTarget + configPage9.afrProtectDeviation)) ? true : false; break; /* Deviation from target table */ - default: afrCondition = false; /* Unknown mode. Shouldn't even get here */ - } - - /* Check if conditions above are fulfilled */ - if(mapCondition && rpmCondition && tpsCondition && afrCondition) - { - /* All conditions fulfilled - start counter for 'protection delay' */ - if(!afrProtectCountEnabled) - { - afrProtectCountEnabled = true; - afrProtectCount = millis(); - } - - /* Check if countdown has reached its target, if so then instruct to cut */ - if(millis() >= (afrProtectCount + (configPage9.afrProtectCutTime * X100_MULTIPLIER))) - { - checkAFRLimitActive = true; - BIT_SET(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_AFR); - } - } - else - { - /* Conditions have presumably changed - deactivate and reset counter */ - if(afrProtectCountEnabled) - { - afrProtectCountEnabled = false; - afrProtectCount = 0; - } - } - - /* Check if condition for reactivation is fulfilled */ - if(checkAFRLimitActive && (currentStatus.TPS <= configPage9.afrProtectReactivationTPS)) - { - checkAFRLimitActive = false; - afrProtectCountEnabled = false; - BIT_CLEAR(currentStatus.engineProtectStatus, ENGINE_PROTECT_BIT_AFR); - } - } + byte checkAFRLimitActive = 0; return checkAFRLimitActive; } diff --git a/speeduino/globals.h b/speeduino/globals.h index e90b862e..fc101311 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -248,10 +248,6 @@ #define COMPOSITE_LOG_TRIG 2 #define COMPOSITE_LOG_SYNC 3 -#define EGO_TYPE_OFF 0 -#define EGO_TYPE_NARROW 1 -#define EGO_TYPE_WIDE 2 - #define INJ_TYPE_PORT 0 #define INJ_TYPE_TBODY 1 @@ -283,9 +279,6 @@ #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 @@ -450,7 +443,6 @@ 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 @@ -611,7 +603,6 @@ extern volatile byte HWTest_INJ; /**< Each bit in this variable represents extern volatile byte HWTest_INJ_50pc; /**< Each bit in this variable represents one of the injector channels and it's 50% HW test status */ extern volatile byte HWTest_IGN; /**< Each bit in this variable represents one of the ignition channels and it's HW test status */ extern volatile byte HWTest_IGN_50pc; /**< Each bit in this variable represents one of the ignition channels and it's 50% HW test status */ -extern byte maxIgnOutputs; /**< Used for rolling rev limiter to indicate how many total ignition channels should currently be firing */ extern byte resetControl; ///< resetControl needs to be here (as global) because using the config page (4) directly can prevent burning the setting @@ -622,9 +613,9 @@ extern volatile byte LOOP_TIMER; //These functions all do checks on a pin to determine if it is already in use by another (higher importance) function #define pinIsInjector(pin) ( ((pin) == pinInjector1) || ((pin) == pinInjector2) || ((pin) == pinInjector3) || ((pin) == pinInjector4) || ((pin) == pinInjector5) || ((pin) == pinInjector6) || ((pin) == pinInjector7) || ((pin) == pinInjector8) ) #define pinIsIgnition(pin) ( ((pin) == pinCoil1) || ((pin) == pinCoil2) || ((pin) == pinCoil3) || ((pin) == pinCoil4) || ((pin) == pinCoil5) || ((pin) == pinCoil6) || ((pin) == pinCoil7) || ((pin) == pinCoil8) ) -//#define pinIsOutput(pin) ( pinIsInjector((pin)) || pinIsIgnition((pin)) || ((pin) == pinFuelPump) || ((pin) == pinFan) || ((pin) == pinVVT_1) || ((pin) == pinVVT_2) || ( ((pin) == pinBoost) && configPage6.boostEnabled) || ((pin) == pinIdle1) || ((pin) == pinIdle2) || ((pin) == pinTachOut) || ((pin) == pinStepperEnable) || ((pin) == pinStepperStep) ) -#define pinIsSensor(pin) ( ((pin) == pinCLT) || ((pin) == pinIAT) || ((pin) == pinMAP) || ((pin) == pinTPS) || ((pin) == pinO2) || ((pin) == pinBat) || (((pin) == pinFlex) && (configPage2.flexEnabled != 0)) ) -//#define pinIsUsed(pin) ( pinIsSensor((pin)) || pinIsOutput((pin)) || pinIsReserved((pin)) ) +#define pinIsOutput(pin) ( pinIsInjector((pin)) || pinIsIgnition((pin)) || ((pin) == pinFuelPump) || ((pin) == pinFan) || ((pin) == pinVVT_1) || ((pin) == pinVVT_2) || ( ((pin) == pinBoost) && configPage6.boostEnabled) || ((pin) == pinIdle1) || ((pin) == pinIdle2) || ((pin) == pinTachOut) || ((pin) == pinStepperEnable) || ((pin) == pinStepperStep) ) +#define pinIsSensor(pin) ( ((pin) == pinCLT) || ((pin) == pinIAT) || ((pin) == pinMAP) || ((pin) == pinTPS) || ((pin) == pinO2) || ((pin) == pinBat) ) +#define pinIsUsed(pin) ( pinIsSensor((pin)) || pinIsOutput((pin)) || pinIsReserved((pin)) ) /** The status struct with current values for all 'live' variables. * In current version this is 64 bytes. Instantiated as global currentStatus. @@ -646,7 +637,6 @@ struct statuses { byte TPS; /**< The current TPS reading (0% - 100%). Is the tpsADC value after the calibration is applied */ byte tpsADC; /**< byte (valued: 0-255) representation of the TPS. Downsampled from the original 10-bit (0-1023) reading, but before any calibration is applied */ byte tpsDOT; /**< TPS delta over time. Measures the % per second that the TPS is changing. Value is divided by 10 to be stored in a byte */ - byte TPSlast; /**< The previous TPS reading */ byte mapDOT; /**< MAP delta over time. Measures the kpa per second that the MAP is changing. Value is divided by 10 to be stored in a byte */ volatile int rpmDOT; /**< RPM delta over time (RPM increase / s ?) */ byte VE; /**< The current VE value being used in the fuel calculation. Can be the same as VE1 or VE2, or a calculated value of both. */ @@ -809,7 +799,7 @@ struct config2 { //config2 in ini byte fuelAlgorithm : 3;///< Fuel algorithm - 0=Manifold pressure/MAP (LOAD_SOURCE_MAP, default, proven), 1=Throttle/TPS (LOAD_SOURCE_TPS), 2=IMAP/EMAP (LOAD_SOURCE_IMAPEMAP) - byte fixAngEnable : 1; ///< Whether fixed/locked timing is enabled (0=disable, 1=enable, See @ref configPage4.FixAng) + byte fixAngEnable : 1; ///< Whether fixed/locked timing is enabled (0=diable, 1=enable, See @ref configPage4.FixAng) byte nInjectors : 4; ///< Number of injectors @@ -819,8 +809,8 @@ struct config2 { byte legacyMAP : 1; ///< Legacy MAP reading behaviour byte baroCorr : 1; // Unused ? byte injLayout : 2; /**< Injector Layout - 0=INJ_PAIRED (number outputs == number cyls/2, timed over 1 crank rev), 1=INJ_SEMISEQUENTIAL (like paired, but number outputs == number cyls, only for 4 cyl), - 2=INJ_BANKED (2 outputs are used), 3=INJ_SEQUENTIAL (number outputs == number cyls, timed over full cycle, 2 crank revs) */ - byte perToothIgn : 1; ///< Experimental / New ignition mode ... (?) (See decoders.ino) + 2=INJ_BANKED (2 outputs are used), 3=INJ_SEQUENTIAL (number ouputs == number cyls, timed over full cycle, 2 crank revs) */ + byte perToothIgn : 1; ///< Experimental / New ign. mode ... (?) (See decoders.ino) byte dfcoEnabled : 1; ///< Whether or not DFCO (deceleration fuel cut-off) is turned on byte aeColdTaperMax; ///< AE cold modifier, taper end temp (no modifier applied, was primePulse in early versions) @@ -1060,7 +1050,7 @@ struct config6 { byte useExtBaro : 1; byte boostMode : 1; /// Boost control mode: 0=Simple (BOOST_MODE_SIMPLE) or 1=full (BOOST_MODE_FULL) byte boostPin : 6; - byte tachoMode : 1; /// Whether to use fixed tacho pulse duration or match to dwell duration + byte unused_bit : 1; //Previously was VVTasOnOff byte useEMAP : 1; ///< Enable EMAP byte voltageCorrectionBins[6]; //X axis bins for voltage correction tables byte injVoltageCorrectionValues[6]; //Correction table for injector PW vs battery voltage @@ -1185,13 +1175,13 @@ struct config9 { byte unused10_182; byte unused10_183; 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 */ - byte afrProtectMinTPS; /* < Minimum TPS. */ - byte afrProtectDeviation; /* < Maximum deviation from AFR target table. Stored value is multiplied by 10 */ - byte afrProtectCutTime; /* < Time in ms before cut. Stored value is divided by 100. Maximum of 2550 ms */ - byte afrProtectReactivationTPS; /* Disable engine protection cut once below this TPS percentage */ + byte unused10_185; + byte unused10_186; + byte unused10_187; + byte unused10_188; + byte unused10_189; + byte unused10_190; + byte unused10_191; #if defined(CORE_AVR) }; @@ -1398,7 +1388,7 @@ struct config13 { uint8_t outputDelay[8]; ///< Output write delay for each programmable I/O (Unit: 0.1S) uint8_t firstDataIn[8]; ///< Set of first I/O vars to compare uint8_t secondDataIn[8];///< Set of second I/O vars to compare - uint8_t outputTimeLimit[8]; ///< Output delay for each programmable I/O, kindOfLimiting bit dependent(Unit: 0.1S) + uint8_t outputTimeLimit[8]; ///< Output delay for each programmable I/O, kindOfLimiting bit dependant(Unit: 0.1S) uint8_t unused_13[8]; // Unused int16_t firstTarget[8]; ///< first target value to compare with numeric comp int16_t secondTarget[8];///< second target value to compare with bitwise op @@ -1428,11 +1418,10 @@ struct config13 { byte onboard_log_tr3_thr_AFR :1; // "Disabled", "Enabled" byte onboard_log_tr4_thr_on; // "V", 0.1, 0.0, 0.0, 15.90, 2 ; * ( 1 byte) byte onboard_log_tr4_thr_off; // "V", 0.1, 0.0, 0.0, 15.90, 2 ; * ( 1 byte) - byte onboard_log_tr5_Epin_pin :6; // "pin", 0, 0, 0, 1, 255, 0 ; - byte unused13_125_2 :2; + byte onboard_log_tr5_thr_on; // "pin", 0, 0, 0, 1, 255, 0 ; - byte unused12_126_127[2]; + byte unused12_125_127[2]; #if defined(CORE_AVR) }; @@ -1440,24 +1429,6 @@ 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 @@ -1530,10 +1501,9 @@ extern byte pinFuelPressure; extern byte pinOilPressure; extern byte pinWMIEmpty; // Water tank empty sensor extern byte pinWMIIndicator; // No water indicator bulb -extern byte pinWMIEnabled; // ON-OFF output to relay/pump/solenoid +extern byte pinWMIEnabled; // ON-OFF ouput to relay/pump/solenoid extern byte pinMC33810_1_CS; extern byte pinMC33810_2_CS; -extern byte pinSDEnable; //Input for manually enabling SD logging #ifdef USE_SPI_EEPROM extern byte pinSPIFlash_CS; #endif @@ -1551,7 +1521,6 @@ 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 */ @@ -1566,7 +1535,4 @@ extern struct table2D cltCalibrationTable; /**< A 32 bin array containing the co extern struct table2D iatCalibrationTable; /**< A 32 bin array containing the inlet air temperature sensor calibration values */ extern struct table2D o2CalibrationTable; /**< A 32 bin array containing the O2 sensor calibration values */ -bool pinIsOutput(byte pin); -bool pinIsUsed(byte pin); - #endif // GLOBALS_H diff --git a/speeduino/globals.ino b/speeduino/globals.ino index 3b209693..56f496c0 100644 --- a/speeduino/globals.ino +++ b/speeduino/globals.ino @@ -15,7 +15,6 @@ 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 @@ -159,7 +158,6 @@ volatile byte HWTest_INJ = 0; /**< Each bit in this variable represents one of t volatile byte HWTest_INJ_50pc = 0; /**< Each bit in this variable represents one of the injector channels and it's 50% HW test status */ volatile byte HWTest_IGN = 0; /**< Each bit in this variable represents one of the ignition channels and it's HW test status */ volatile byte HWTest_IGN_50pc = 0; -byte maxIgnOutputs = 1; /**< Used for rolling rev limiter to indicate how many total ignition channels should currently be firing */ //This needs to be here because using the config page directly can prevent burning the setting @@ -246,7 +244,6 @@ byte pinWMIIndicator; // No water indicator bulb byte pinWMIEnabled; // ON-OFF output to relay/pump/solenoid byte pinMC33810_1_CS; byte pinMC33810_2_CS; -byte pinSDEnable; #ifdef USE_SPI_EEPROM byte pinSPIFlash_CS; #endif @@ -258,7 +255,6 @@ 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 */ @@ -273,73 +269,3 @@ struct table2D iatCalibrationTable; uint16_t o2Calibration_bins[32]; uint8_t o2Calibration_values[32]; struct table2D o2CalibrationTable; - -//These function do checks on a pin to determine if it is already in use by another (higher importance) active function -inline bool pinIsOutput(byte pin) -{ - bool used = false; - bool isIdlePWM = (configPage6.iacAlgorithm > 0) && ((configPage6.iacAlgorithm <= 3) || (configPage6.iacAlgorithm == 6)); - bool isIdleSteper = (configPage6.iacAlgorithm > 3) && (configPage6.iacAlgorithm != 6); - //Injector? - if ((pin == pinInjector1) - || ((pin == pinInjector2) && (configPage2.nInjectors > 1)) - || ((pin == pinInjector3) && (configPage2.nInjectors > 2)) - || ((pin == pinInjector4) && (configPage2.nInjectors > 3)) - || ((pin == pinInjector5) && (configPage2.nInjectors > 4)) - || ((pin == pinInjector6) && (configPage2.nInjectors > 5)) - || ((pin == pinInjector7) && (configPage2.nInjectors > 6)) - || ((pin == pinInjector8) && (configPage2.nInjectors > 7))) - { - used = true; - } - //Ignition? - if ((pin == pinCoil1) - || ((pin == pinCoil2) && (maxIgnOutputs > 1)) - || ((pin == pinCoil3) && (maxIgnOutputs > 2)) - || ((pin == pinCoil4) && (maxIgnOutputs > 3)) - || ((pin == pinCoil5) && (maxIgnOutputs > 4)) - || ((pin == pinCoil6) && (maxIgnOutputs > 5)) - || ((pin == pinCoil7) && (maxIgnOutputs > 6)) - || ((pin == pinCoil8) && (maxIgnOutputs > 7))) - { - used = true; - } - //Functions? - if ((pin == pinFuelPump) - || ((pin == pinFan) && (configPage2.fanEnable == 1)) - || ((pin == pinVVT_1) && (configPage6.vvtEnabled > 0)) - || ((pin == pinVVT_1) && (configPage10.wmiEnabled > 0)) - || ((pin == pinVVT_2) && (configPage10.vvt2Enabled > 0)) - || ((pin == pinBoost) && (configPage6.boostEnabled == 1)) - || ((pin == pinIdle1) && isIdlePWM) - || ((pin == pinIdle2) && isIdlePWM && (configPage6.iacChannels == 1)) - || ((pin == pinStepperEnable) && isIdleSteper) - || ((pin == pinStepperStep) && isIdleSteper) - || ((pin == pinStepperDir) && isIdleSteper) - || (pin == pinTachOut) ) - { - used = true; - } - //Forbiden or hardware reserved? (Defined at board_xyz.h file) - if ( pinIsReserved(pin) ) { used = true; } - - return used; -} - -inline bool pinIsUsed(byte pin) -{ - bool used = false; - - //Analog input? - if ( pinIsSensor(pin) ) - { - used = true; - } - //Functions? - if ( pinIsOutput(pin) ) - { - used = true; - } - - return used; -} diff --git a/speeduino/idle.h b/speeduino/idle.h index 5e1eb8e9..a05dc363 100644 --- a/speeduino/idle.h +++ b/speeduino/idle.h @@ -30,7 +30,7 @@ struct StepperIdle int curIdleStep; //Tracks the current location of the stepper int targetIdleStep; //What the targeted step is volatile StepperStatus stepperStatus; - volatile unsigned long stepStartTime; + volatile unsigned long stepStartTime; //The time the curren byte lessAirDirection; byte moreAirDirection; }; diff --git a/speeduino/idle.ino b/speeduino/idle.ino index 066970a3..097c89b4 100644 --- a/speeduino/idle.ino +++ b/speeduino/idle.ino @@ -273,7 +273,7 @@ void initialiseIdleUpOutput() if (configPage2.idleUpOutputInv == 1) { idleUpOutputHIGH = LOW; idleUpOutputLOW = HIGH; } else { idleUpOutputHIGH = HIGH; idleUpOutputLOW = LOW; } - if(configPage2.idleUpEnabled > 0) { digitalWrite(pinIdleUpOutput, idleUpOutputLOW); } //Initialise program with the idle up output in the off state if it is enabled. + digitalWrite(pinIdleUpOutput, idleUpOutputLOW); //Initialise program with the idle up output in the off state currentStatus.idleUpOutputActive = false; idleUpOutput_pin_port = portOutputRegister(digitalPinToPort(pinIdleUpOutput)); @@ -544,7 +544,7 @@ void idleControl() idle_cl_target_rpm = (uint16_t)currentStatus.CLIdleTarget * 10; //Multiply the byte target value back out by 10 if( BIT_CHECK(LOOP_TIMER, BIT_TIMER_1HZ) ) { idlePID.SetTunings(configPage6.idleKP, configPage6.idleKI, configPage6.idleKD); } //Re-read the PID settings once per second - if((currentStatus.RPM - idle_cl_target_rpm > configPage2.iacRPMlimitHysteresis*10) || (currentStatus.TPS > configPage2.iacTPSlimit)){ //reset integral to zero when TPS is bigger than set value in TS (opening throttle so not idle anymore). OR when RPM higher than Idle Target + RPM Histeresis (coming back from high rpm with throttle closed) + if((currentStatus.RPM - idle_cl_target_rpm > configPage2.iacRPMlimitHysteresis*10) || (currentStatus.TPS > configPage2.iacTPSlimit)){ //reset integral to zero when TPS is bigger than set value in TS (opening throttle so not idle anymore). OR when RPM higher than Idle Target + RPM Histeresis (comming back from high rpm with throttle closed) idlePID.ResetIntegeral(); } PID_computed = idlePID.Compute(true, FeedForwardTerm); diff --git a/speeduino/init.ino b/speeduino/init.ino index 43f854b5..4bfdedbc 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -1482,7 +1482,7 @@ void setPinMapping(byte boardID) //https://github.com/stm32duino/Arduino_Core_STM32/blob/master/variants/Generic_F411Cx/variant.h#L28 //pins PA12, PA11 are used for USB or CAN couldn't be used for GPIO //pins PB12, PB13, PB14 and PB15 are used to SPI FLASH - //PB2 can't be used as input because it's the BOOT pin + //PB2 can't be used as input becuase is BOOT pin pinInjector1 = PB7; //Output pin injector 1 is on pinInjector2 = PB6; //Output pin injector 2 is on pinInjector3 = PB5; //Output pin injector 3 is on @@ -1813,7 +1813,6 @@ void setPinMapping(byte boardID) pinTrigger3 = 20; //The Cam sensor 2 pin pinTPS = A2;//TPS input pin pinMAP = A3; //MAP sensor pin - pinEMAP = A15; //EMAP sensor pin pinIAT = A0; //IAT sensor pin pinCLT = A1; //CLT sensor pin pinO2 = A8; //O2 Sensor pin @@ -1835,11 +1834,6 @@ void setPinMapping(byte boardID) pinFlex = 2; // Flex sensor pinResetControl = 43; //Reset control output pinVSS = 3; //VSS input pin - pinWMIEmpty = 31; //(placeholder) - pinWMIIndicator = 33; //(placeholder) - pinWMIEnabled = 35; //(placeholder) - pinIdleUp = 37; //(placeholder) - pinCTPS = A6; //(placeholder) #elif defined(STM32F407xx) pinInjector1 = PB15; //Output pin injector 1 pinInjector2 = PB14; //Output pin injector 2 @@ -1861,7 +1855,6 @@ void setPinMapping(byte boardID) pinTrigger2 = PD4; //The Cam Sensor pin pinTPS = PA2;//TPS input pin pinMAP = PA3; //MAP sensor pin - pinEMAP = PC5; //EMAP sensor pin pinIAT = PA0; //IAT sensor pin pinCLT = PA1; //CLS sensor pin pinO2 = PB0; //O2 Sensor pin @@ -1883,11 +1876,6 @@ void setPinMapping(byte boardID) pinFlex = PD7; // Flex sensor pinResetControl = PB7; //Reset control output pinVSS = PB6; //VSS input pin - pinWMIEmpty = PD15; //(placeholder) - pinWMIIndicator = PD13; //(placeholder) - pinWMIEnabled = PE15; //(placeholder) - pinIdleUp = PE14; //(placeholder) - pinCTPS = PA6; //(placeholder) #endif break; @@ -2222,52 +2210,6 @@ void setPinMapping(byte boardID) #endif break; - - case 56: - #if defined(CORE_TEENSY) - //Pin mappings for the Bear Cub (Teensy 4.1) - pinInjector1 = 6; - pinInjector2 = 7; - pinInjector3 = 9; - pinInjector4 = 8; - pinInjector5 = 0; //Not used - pinCoil1 = 2; - pinCoil2 = 3; - pinCoil3 = 4; - pinCoil4 = 5; - - pinTrigger = 20; //The CAS pin - pinTrigger2 = 21; //The Cam Sensor pin - pinFlex = 37; // Flex sensor - pinMAP = A5; //MAP sensor pin - pinBaro = A4; //Baro sensor pin - pinBat = A15; //Battery reference voltage pin - pinTPS = A3; //TPS input pin - pinIAT = A0; //IAT sensor pin - pinCLT = A1; //CLS sensor pin - pinO2 = A2; //O2 Sensor pin - pinLaunch = 36; - - pinSpareTemp1 = A16; //spare Analog input 1 - pinSpareTemp2 = A17; //spare Analog input 2 - pinTachOut = 38; //Tacho output pin - pinIdle1 = 27; //Single wire idle control - pinIdle2 = 26; //2 wire idle control. Shared with Spare 1 output - pinFuelPump = 10; //Fuel pump output - pinVVT_1 = 28; //Default VVT output - pinStepperDir = 32; //Direction pin for DRV8825 driver - pinStepperStep = 31; //Step pin for DRV8825 driver - pinStepperEnable = 30; //Enable pin for DRV8825 driver - pinBoost = 24; //Boost control - pinSpareLOut1 = 29; //low current output spare1 - pinSpareLOut2 = 26; //low current output spare2 - pinSpareLOut3 = 28; //low current output spare3 - pinSpareLOut4 = 29; //low current output spare4 - pinFan = 25; //Pin for the fan output - pinResetControl = 46; //Reset control output PLACEHOLDER value for now - - #endif - break; case 60: @@ -2617,11 +2559,8 @@ void setPinMapping(byte boardID) if ( (configPage10.wmiIndicatorPin != 0) && (configPage10.wmiIndicatorPin < BOARD_MAX_IO_PINS) ) { pinWMIIndicator = pinTranslate(configPage10.wmiIndicatorPin); } if ( (configPage10.wmiEnabledPin != 0) && (configPage10.wmiEnabledPin < BOARD_MAX_IO_PINS) ) { pinWMIEnabled = pinTranslate(configPage10.wmiEnabledPin); } if ( (configPage10.vvt2Pin != 0) && (configPage10.vvt2Pin < BOARD_MAX_IO_PINS) ) { pinVVT_2 = pinTranslate(configPage10.vvt2Pin); } - if ( (configPage13.onboard_log_trigger_Epin != 0 ) && (configPage13.onboard_log_trigger_Epin != 0) && (configPage13.onboard_log_tr5_Epin_pin < BOARD_MAX_IO_PINS) ) { pinSDEnable = pinTranslate(configPage13.onboard_log_tr5_Epin_pin); } - //Currently there's no default pin for Idle Up - pinIdleUp = pinTranslate(configPage2.idleUpPin); //Currently there's no default pin for Idle Up Output @@ -2822,10 +2761,6 @@ void setPinMapping(byte boardID) { pinMode(pinOilPressure, INPUT); } - if( (configPage13.onboard_log_trigger_Epin > 0) && (!pinIsOutput(pinSDEnable)) ) - { - pinMode(pinSDEnable, INPUT); - } if(configPage10.wmiEnabled > 0) { pinMode(pinWMIEnabled, OUTPUT); diff --git a/speeduino/int16_byte.h b/speeduino/int16_byte.h index 9680a653..c7c093b0 100644 --- a/speeduino/int16_byte.h +++ b/speeduino/int16_byte.h @@ -12,7 +12,7 @@ typedef uint8_t byte; /** @brief Represents a 16-bit value as a byte. Useful for I/O. - * + * * Often we need to deal internally with values that fit in 16-bits but do * not require much accuracy. E.g. table axes in RPM. For these values we can * save storage space (EEPROM) by scaling to/from 8-bits using a fixed divisor. @@ -23,12 +23,11 @@ public: /** * @brief Construct - * * @param factor The factor to multiply when converting \c byte to \c int16_t * @param divider The factor to divide by when converting \c int16_t to \c byte * * \c divider could be computed from \c factor, but including it as a parameter - * allows callers to create \c factor instances at compile time. + * allows callers to create \c factor instances at compile tiem. */ constexpr int16_byte(uint8_t factor, const libdivide::libdivide_s16_t ÷r) : _factor(factor), _divider(divider) @@ -46,4 +45,4 @@ private: libdivide::libdivide_s16_t _divider; }; -/** @} */ +/** @} */ \ No newline at end of file diff --git a/speeduino/logger.h b/speeduino/logger.h index 28ddcfbf..8ad2826b 100644 --- a/speeduino/logger.h +++ b/speeduino/logger.h @@ -23,9 +23,6 @@ byte getTSLogEntry(uint16_t); int16_t getReadableLogEntry(uint16_t); -#if FPU_MAX_SIZE >= 32 - float getReadableFloatLogEntry(uint16_t); -#endif bool is2ByteEntry(uint8_t); // This array indicates which index values from the log are 2 byte values diff --git a/speeduino/logger.ino b/speeduino/logger.ino index 13c74120..8442ed83 100644 --- a/speeduino/logger.ino +++ b/speeduino/logger.ino @@ -195,7 +195,7 @@ int16_t getReadableLogEntry(uint16_t logIndex) case 11: statusValue = currentStatus.iatCorrection; break; //Air temperature Correction (%) case 12: statusValue = currentStatus.wueCorrection; break; //Warmup enrichment (%) case 13: statusValue = currentStatus.RPM; break; //rpm HB - case 14: statusValue = currentStatus.AEamount; break; //TPS acceleration enrichment (%) + case 14: statusValue = currentStatus.AEamount; break; //TPS acceleration enrichment (%) divided by 2 (Can exceed 255) case 15: statusValue = currentStatus.corrections; break; //Total GammaE (%) case 16: statusValue = currentStatus.VE1; break; //VE 1 (%) case 17: statusValue = currentStatus.VE2; break; //VE 2 (%) @@ -290,37 +290,6 @@ int16_t getReadableLogEntry(uint16_t logIndex) return statusValue; } -/** - * An expansion to the @ref getReadableLogEntry function for systems that have an FPU. It will provide a floating point value for any parameter that this is appropriate for, otherwise will return the result of @ref getReadableLogEntry. - * See logger.h for the field names and order - * @param logIndex - The log index required. Note that this is NOT the byte number, but the index in the log - * @return float value of the requested log entry. - */ -#if FPU_MAX_SIZE >= 32 -float getReadableFloatLogEntry(uint16_t logIndex) -{ - float statusValue = 0.0; - - switch(logIndex) - { - case 8: statusValue = currentStatus.battery10 / 10.0; break; //battery voltage - case 9: statusValue = currentStatus.O2 / 10.0; break; - case 18: statusValue = currentStatus.afrTarget / 10.0; break; - case 21: statusValue = currentStatus.TPS / 2.0; break; // TPS (0% to 100% = 0 to 200) - case 33: statusValue = currentStatus.O2_2 / 10.0; break; //O2 - - case 53: statusValue = currentStatus.PW1 / 1000.0; break; //Pulsewidth 1 Have to convert from uS to mS. - case 54: statusValue = currentStatus.PW2 / 1000.0; break; //Pulsewidth 2 Have to convert from uS to mS. - case 55: statusValue = currentStatus.PW3 / 1000.0; break; //Pulsewidth 3 Have to convert from uS to mS. - case 56: statusValue = currentStatus.PW4 / 1000.0; break; //Pulsewidth 4 Have to convert from uS to mS. - - default: statusValue = getReadableLogEntry(logIndex); break; //If logIndex value is NOT a float based one, use the regular function - } - - return statusValue; -} -#endif - /** * Searches the log 2 byte array to determine whether a given index is a regular single byte or a 2 byte field * Uses a boundless binary search for improved performance, but requires the fsIntIndex to remain in order diff --git a/speeduino/maths.h b/speeduino/maths.h index 3c447e28..86942753 100644 --- a/speeduino/maths.h +++ b/speeduino/maths.h @@ -10,11 +10,11 @@ inline long powint(int, unsigned int); #ifdef USE_LIBDIVIDE #include "src/libdivide/libdivide.h" -extern const struct libdivide::libdivide_u16_t libdiv_u16_100; -extern const struct libdivide::libdivide_s16_t libdiv_s16_100; -extern const struct libdivide::libdivide_u32_t libdiv_u32_100; -extern const struct libdivide::libdivide_s32_t libdiv_s32_100; -extern const struct libdivide::libdivide_u32_t libdiv_u32_360; +extern struct libdivide::libdivide_u16_t libdiv_u16_100; +extern struct libdivide::libdivide_s16_t libdiv_s16_100; +extern struct libdivide::libdivide_u32_t libdiv_u32_100; +extern struct libdivide::libdivide_s32_t libdiv_s32_100; +extern struct libdivide::libdivide_u32_t libdiv_u32_360; #endif inline uint8_t div100(uint8_t n) { @@ -71,7 +71,6 @@ inline uint32_t div360(uint32_t n) { } #define DIV_ROUND_CLOSEST(n, d) ((((n) < 0) ^ ((d) < 0)) ? (((n) - (d)/2)/(d)) : (((n) + (d)/2)/(d))) -#define IS_INTEGER(d) (d == (int32_t)d) //This is a dedicated function that specifically handles the case of mapping 0-1023 values into a 0 to X range //This is a common case because it means converting from a standard 10-bit analog input to a byte or 10-bit analog into 0-511 (Eg the temperature readings) diff --git a/speeduino/maths.ino b/speeduino/maths.ino index 186d6df9..00c7f699 100644 --- a/speeduino/maths.ino +++ b/speeduino/maths.ino @@ -6,13 +6,13 @@ // Constants used for libdivide. Using predefined constants saves flash and RAM (.bss) // versus calling the libdivide generator functions (E.g. libdivide_s32_gen) -const libdivide::libdivide_s16_t libdiv_s16_100 = { .magic = S16_MAGIC(100), .more = S16_MORE(100) }; -const libdivide::libdivide_u16_t libdiv_u16_100 = { .magic = U16_MAGIC(100), .more = U16_MORE(100) }; +libdivide::libdivide_s16_t libdiv_s16_100 = { .magic = S16_MAGIC(100), .more = S16_MORE(100) }; +libdivide::libdivide_u16_t libdiv_u16_100 = { .magic = U16_MAGIC(100), .more = U16_MORE(100) }; // 32-bit constants generated here: https://godbolt.org/z/vP8Kfejo9 -const libdivide::libdivide_u32_t libdiv_u32_100 = { .magic = 2748779070, .more = 6 }; -const libdivide::libdivide_s32_t libdiv_s32_100 = { .magic = 1374389535, .more = 5 }; -const libdivide::libdivide_u32_t libdiv_u32_200 = { .magic = 2748779070, .more = 7 }; -const libdivide::libdivide_u32_t libdiv_u32_360 = { .magic = 1813430637, .more = 72 }; +libdivide::libdivide_u32_t libdiv_u32_100 = { .magic = 2748779070, .more = 6 }; +libdivide::libdivide_s32_t libdiv_s32_100 = { .magic = 1374389535, .more = 5 }; +libdivide::libdivide_u32_t libdiv_u32_200 = { .magic = 2748779070, .more = 7 }; +libdivide::libdivide_u32_t libdiv_u32_360 = { .magic = 1813430637, .more = 72 }; #endif //Replace the standard arduino map() function to use the div function instead diff --git a/speeduino/pages.cpp b/speeduino/pages.cpp index 3d583482..59ed76ba 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, 256 }; +constexpr const uint16_t PROGMEM ini_page_sizes[] = { 0, 128, 288, 288, 128, 288, 128, 240, 384, 192, 192, 288, 192, 128, 288 }; // ========================= Table size calculations ========================= // Note that these should be computed at compile time, assuming the correct @@ -398,13 +398,6 @@ 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 6fd88da1..247db4d5 100644 --- a/speeduino/pages.h +++ b/speeduino/pages.h @@ -13,22 +13,20 @@ 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 boostvvtPage2 15 - +#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 // ============================== Per-byte page access ========================== diff --git a/speeduino/rtc_common.ino b/speeduino/rtc_common.ino index 48eebca2..ba9bf233 100644 --- a/speeduino/rtc_common.ino +++ b/speeduino/rtc_common.ino @@ -7,7 +7,7 @@ void initRTC() { - #if defined(CORE_TEENSY35) || defined(CORE_TEENSY36)|| defined(CORE_TEENSY41) + #if defined(CORE_TEENSY35) || defined(CORE_TEENSY36) setSyncProvider(getTeensy3Time); #elif defined(CORE_STM32) @@ -114,12 +114,6 @@ void rtc_setTime(byte second, byte minute, byte hour, byte day, byte month, uint setTime(hour, minute, second, day, month, year); Teensy3Clock.set(now()); #elif defined(CORE_STM32) - //If RTC time has not been set earlier (no battery etc.) we need to stop the RTC and restart it with LSE_CLOCK to have accurate RTC. - if (!rtc.isTimeSet()) { - rtc.end(); - rtc.setClockSource(STM32RTC::LSE_CLOCK); - rtc.begin(); - } rtc.setTime(hour, minute, second); //year in stm32 rtc is a byte. so subtract year 2000 to fit rtc.setDate(day, month, (year-2000)); diff --git a/speeduino/scheduledIO.h b/speeduino/scheduledIO.h index 5ccab4c7..410dce3c 100644 --- a/speeduino/scheduledIO.h +++ b/speeduino/scheduledIO.h @@ -125,9 +125,6 @@ void coil6Toggle(); void coil7Toggle(); void coil8Toggle(); -void tachoOutputOn(); -void tachoOutputOff(); - /* #ifndef USE_MC33810 #define openInjector1() *inj1_pin_port |= (inj1_pin_mask); BIT_SET(currentStatus.status1, BIT_STATUS1_INJ1) diff --git a/speeduino/scheduledIO.ino b/speeduino/scheduledIO.ino index 0b8d5fd4..20aec342 100644 --- a/speeduino/scheduledIO.ino +++ b/speeduino/scheduledIO.ino @@ -73,29 +73,29 @@ void closeInjector3and7() { closeInjector3(); closeInjector7(); } void openInjector4and8() { openInjector4(); openInjector8(); } void closeInjector4and8() { closeInjector4(); closeInjector8(); } -inline void beginCoil1Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1Charging_DIRECT(); } else { coil1Charging_MC33810(); } tachoOutputOn(); } -inline void endCoil1Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1StopCharging_DIRECT(); } else { coil1StopCharging_MC33810(); } tachoOutputOff(); } +inline void beginCoil1Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1Charging_DIRECT(); } else { coil1Charging_MC33810(); } tachoOutputFlag = READY; } +inline void endCoil1Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil1StopCharging_DIRECT(); } else { coil1StopCharging_MC33810(); } } -inline void beginCoil2Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2Charging_DIRECT(); } else { coil2Charging_MC33810(); } tachoOutputOn(); } -inline void endCoil2Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2StopCharging_DIRECT(); } else { coil2StopCharging_MC33810(); } tachoOutputOff(); } +inline void beginCoil2Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2Charging_DIRECT(); } else { coil2Charging_MC33810(); } tachoOutputFlag = READY; } +inline void endCoil2Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil2StopCharging_DIRECT(); } else { coil2StopCharging_MC33810(); } } -inline void beginCoil3Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3Charging_DIRECT(); } else { coil3Charging_MC33810(); } tachoOutputOn(); } -inline void endCoil3Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3StopCharging_DIRECT(); } else { coil3StopCharging_MC33810(); } tachoOutputOff(); } +inline void beginCoil3Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3Charging_DIRECT(); } else { coil3Charging_MC33810(); } tachoOutputFlag = READY; } +inline void endCoil3Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil3StopCharging_DIRECT(); } else { coil3StopCharging_MC33810(); } } -inline void beginCoil4Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4Charging_DIRECT(); } else { coil4Charging_MC33810(); } tachoOutputOn(); } -inline void endCoil4Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4StopCharging_DIRECT(); } else { coil4StopCharging_MC33810(); } tachoOutputOff(); } +inline void beginCoil4Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4Charging_DIRECT(); } else { coil4Charging_MC33810(); } tachoOutputFlag = READY; } +inline void endCoil4Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil4StopCharging_DIRECT(); } else { coil4StopCharging_MC33810(); } } -inline void beginCoil5Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5Charging_DIRECT(); } else { coil5Charging_MC33810(); } tachoOutputOn(); } -inline void endCoil5Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5StopCharging_DIRECT(); } else { coil5StopCharging_MC33810(); } tachoOutputOff(); } +inline void beginCoil5Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5Charging_DIRECT(); } else { coil5Charging_MC33810(); } tachoOutputFlag = READY; } +inline void endCoil5Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil5StopCharging_DIRECT(); } else { coil5StopCharging_MC33810(); } } -inline void beginCoil6Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6Charging_DIRECT(); } else { coil6Charging_MC33810(); } tachoOutputOn(); } -inline void endCoil6Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6StopCharging_DIRECT(); } else { coil6StopCharging_MC33810(); } tachoOutputOff(); } +inline void beginCoil6Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6Charging_DIRECT(); } else { coil6Charging_MC33810(); } tachoOutputFlag = READY; } +inline void endCoil6Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil6StopCharging_DIRECT(); } else { coil6StopCharging_MC33810(); } } -inline void beginCoil7Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7Charging_DIRECT(); } else { coil7Charging_MC33810(); } tachoOutputOn(); } -inline void endCoil7Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7StopCharging_DIRECT(); } else { coil7StopCharging_MC33810(); } tachoOutputOff(); } +inline void beginCoil7Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7Charging_DIRECT(); } else { coil7Charging_MC33810(); } tachoOutputFlag = READY; } +inline void endCoil7Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil7StopCharging_DIRECT(); } else { coil7StopCharging_MC33810(); } } -inline void beginCoil8Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8Charging_DIRECT(); } else { coil8Charging_MC33810(); } tachoOutputOn(); } -inline void endCoil8Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8StopCharging_DIRECT(); } else { coil8StopCharging_MC33810(); } tachoOutputOff(); } +inline void beginCoil8Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8Charging_DIRECT(); } else { coil8Charging_MC33810(); } tachoOutputFlag = READY; } +inline void endCoil8Charge() { if(ignitionOutputControl != OUTPUT_CONTROL_MC33810) { coil8StopCharging_DIRECT(); } else { coil8StopCharging_MC33810(); } } //The below 3 calls are all part of the rotary ignition mode inline void beginTrailingCoilCharge() { beginCoil2Charge(); } @@ -126,7 +126,4 @@ void endCoil3and7Charge() { endCoil3Charge(); endCoil7Charge(); } void beginCoil4and8Charge() { beginCoil4Charge(); beginCoil8Charge(); } void endCoil4and8Charge() { endCoil4Charge(); endCoil8Charge(); } -void tachoOutputOn() { if(configPage6.tachoMode) { TACHO_PULSE_LOW(); } else { tachoOutputFlag = READY; } } -void tachoOutputOff() { if(configPage6.tachoMode) { TACHO_PULSE_HIGH(); } } - void nullCallback() { return; } diff --git a/speeduino/scheduler.h b/speeduino/scheduler.h index b99def18..4c24da60 100644 --- a/speeduino/scheduler.h +++ b/speeduino/scheduler.h @@ -108,7 +108,7 @@ void setIgnitionSchedule8(void (*startCallback)(), unsigned long timeout, unsign inline void refreshIgnitionSchedule1(unsigned long timeToEnd) __attribute__((always_inline)); -//The ARM cores use separate functions for their ISRs +//The ARM cores use seprate functions for their ISRs #if defined(ARDUINO_ARCH_STM32) || defined(CORE_TEENSY) static inline void fuelSchedule1Interrupt(); static inline void fuelSchedule2Interrupt(); diff --git a/speeduino/scheduler.ino b/speeduino/scheduler.ino index ac1d22b2..0265f19a 100644 --- a/speeduino/scheduler.ino +++ b/speeduino/scheduler.ino @@ -116,23 +116,10 @@ void initialiseSchedulers() IGN2_TIMER_ENABLE(); IGN3_TIMER_ENABLE(); IGN4_TIMER_ENABLE(); -#if (IGN_CHANNELS >= 5) IGN5_TIMER_ENABLE(); IGN6_TIMER_ENABLE(); IGN7_TIMER_ENABLE(); IGN8_TIMER_ENABLE(); -#endif - - FUEL1_TIMER_ENABLE(); - FUEL2_TIMER_ENABLE(); - FUEL3_TIMER_ENABLE(); - FUEL4_TIMER_ENABLE(); -#if (INJ_CHANNELS >= 5) - FUEL5_TIMER_ENABLE(); - FUEL6_TIMER_ENABLE(); - FUEL7_TIMER_ENABLE(); - FUEL8_TIMER_ENABLE(); -#endif ignitionSchedule1.schedulesSet = 0; ignitionSchedule2.schedulesSet = 0; @@ -1250,7 +1237,7 @@ static inline void ignitionSchedule4Interrupt() //Most ARM chips can simply call ignitionSchedule4.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule4.startTime = micros(); if(ignitionSchedule4.endScheduleSetByDecoder == true) { SET_COMPARE(IGN4_COMPARE, ignitionSchedule4.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN4_COMPARE, IGN4_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule4.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs + else { SET_COMPARE(IGN4_COMPARE, IGN4_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule4.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha } else if (ignitionSchedule4.Status == RUNNING) { @@ -1291,7 +1278,7 @@ static inline void ignitionSchedule5Interrupt() //Most ARM chips can simply call ignitionSchedule5.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule5.startTime = micros(); if(ignitionSchedule5.endScheduleSetByDecoder == true) { SET_COMPARE(IGN5_COMPARE, ignitionSchedule5.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN5_COMPARE, IGN5_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule5.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs + else { SET_COMPARE(IGN5_COMPARE, IGN5_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule5.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha } else if (ignitionSchedule5.Status == RUNNING) { @@ -1332,7 +1319,7 @@ static inline void ignitionSchedule6Interrupt() //Most ARM chips can simply call ignitionSchedule6.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule6.startTime = micros(); if(ignitionSchedule6.endScheduleSetByDecoder == true) { SET_COMPARE(IGN6_COMPARE, ignitionSchedule6.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN6_COMPARE, IGN6_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule6.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs + else { SET_COMPARE(IGN6_COMPARE, IGN6_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule6.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha } else if (ignitionSchedule6.Status == RUNNING) { @@ -1373,7 +1360,7 @@ static inline void ignitionSchedule7Interrupt() //Most ARM chips can simply call ignitionSchedule7.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule7.startTime = micros(); if(ignitionSchedule7.endScheduleSetByDecoder == true) { SET_COMPARE(IGN7_COMPARE, ignitionSchedule7.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN7_COMPARE, IGN7_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule7.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs + else { SET_COMPARE(IGN7_COMPARE, IGN7_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule7.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha } else if (ignitionSchedule7.Status == RUNNING) { @@ -1414,7 +1401,7 @@ static inline void ignitionSchedule8Interrupt() //Most ARM chips can simply call ignitionSchedule8.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback) ignitionSchedule8.startTime = micros(); if(ignitionSchedule8.endScheduleSetByDecoder == true) { SET_COMPARE(IGN8_COMPARE, ignitionSchedule8.endCompare); } //If the decoder has set the end compare value, assign it to the next compare - else { SET_COMPARE(IGN8_COMPARE, IGN8_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule8.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow that can occur at low RPMs + else { SET_COMPARE(IGN8_COMPARE, IGN8_COUNTER + uS_TO_TIMER_COMPARE(ignitionSchedule8.duration) ); } //If the decoder based timing isn't set, doing this here prevents a potential overflow tha } else if (ignitionSchedule8.Status == RUNNING) { diff --git a/speeduino/sensors.h b/speeduino/sensors.h index bfadf33c..38f5f35a 100644 --- a/speeduino/sensors.h +++ b/speeduino/sensors.h @@ -52,6 +52,9 @@ unsigned long EMAPrunningValue; //As above but for EMAP unsigned int MAPcount; //Number of samples taken in the current MAP cycle uint32_t MAPcurRev; //Tracks which revolution we're sampling on bool auxIsEnabled; +byte TPSlast; /**< The previous TPS reading */ +unsigned long TPS_time; //The time the TPS sample was taken +unsigned long TPSlast_time; //The time the previous TPS sample was taken uint16_t MAPlast; /**< The previous MAP reading */ unsigned long MAP_time; //The time the MAP sample was taken unsigned long MAPlast_time; //The time the previous MAP sample was taken diff --git a/speeduino/sensors.ino b/speeduino/sensors.ino index 5ada90c9..24021b58 100644 --- a/speeduino/sensors.ino +++ b/speeduino/sensors.ino @@ -79,7 +79,7 @@ void initialiseADC() || (((configPage9.enable_secondarySerial == 0) && ( (configPage9.enable_intcan == 1) && (configPage9.intcan_available == 0) )) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 2) || (((configPage9.enable_secondarySerial == 0) && (configPage9.enable_intcan == 0)) && ((configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 2))) { //if current input channel is enabled as analog local pin check caninput_selxb(bits 2:3) with &12 and caninput_selxa(bits 0:1) with &3 - byte pinNumber = pinTranslateAnalog(configPage9.Auxinpina[currentStatus.current_caninchannel]&63); + byte pinNumber = (configPage9.Auxinpina[currentStatus.current_caninchannel]&127); if( pinIsUsed(pinNumber) ) { //Do nothing here as the pin is already in use. @@ -96,7 +96,7 @@ void initialiseADC() else if ((((configPage9.enable_secondarySerial == 1) || ((configPage9.enable_intcan == 1) && (configPage9.intcan_available == 1))) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&12) == 12) || (((configPage9.enable_secondarySerial == 0) && ( (configPage9.enable_intcan == 1) && (configPage9.intcan_available == 0) )) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 3) || (((configPage9.enable_secondarySerial == 0) && (configPage9.enable_intcan == 0)) && ((configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 3))) - { //if current input channel is enabled as digital local pin check caninput_selxb(bits 2:3) with &12 and caninput_selxa(bits 0:1) with &3 + { //if current input channel is enabled as digital local pin check caninput_selxb(bits 2:3) wih &12 and caninput_selxa(bits 0:1) with &3 byte pinNumber = (configPage9.Auxinpinb[currentStatus.current_caninchannel]&63) + 1; if( pinIsUsed(pinNumber) ) { @@ -397,7 +397,8 @@ static inline void readMAP() void readTPS(bool useFilter) { - currentStatus.TPSlast = currentStatus.TPS; + TPSlast = currentStatus.TPS; + TPSlast_time = TPS_time; #if defined(ANALOG_ISR) byte tempTPS = fastMap1023toX(AnChannel[pinTPS-A0], 255); //Get the current raw TPS ADC value and map it into a byte #else @@ -438,6 +439,7 @@ void readTPS(bool useFilter) else { currentStatus.CTPSActive = digitalRead(pinCTPS); } //Inverted mode (5v activates closed throttle position sensor) } else { currentStatus.CTPSActive = 0; } + TPS_time = micros(); } void readCLT(bool useFilter) diff --git a/speeduino/speeduino.h b/speeduino/speeduino.h index b8a2ba8f..68258ad2 100644 --- a/speeduino/speeduino.h +++ b/speeduino/speeduino.h @@ -38,6 +38,7 @@ extern uint16_t inj_opentime_uS; /**< The injector opening time. This is set wit extern bool ignitionOn; /**< The current state of the ignition system (on or off) */ extern bool fuelOn; /**< The current state of the fuel system (on or off) */ +extern byte maxIgnOutputs; /**< Used for rolling rev limiter to indicate how many total ignition channels should currently be firing */ extern byte curRollingCut; /**< Rolling rev limiter, current ignition channel being cut */ extern byte rollingCutCounter; /**< how many times (revolutions) the ignition has been cut in a row */ extern uint32_t rollingCutLastRev; /**< Tracks whether we're on the same or a different rev for the rolling cut */ diff --git a/speeduino/speeduino.ino b/speeduino/speeduino.ino index 7e5a35c8..e7d44364 100644 --- a/speeduino/speeduino.ino +++ b/speeduino/speeduino.ino @@ -78,6 +78,7 @@ uint16_t inj_opentime_uS = 0; bool ignitionOn = false; /**< The current state of the ignition system (on or off) */ bool fuelOn = false; /**< The current state of the fuel system (on or off) */ +byte maxIgnOutputs = 1; /**< Used for rolling rev limiter to indicate how many total ignition channels should currently be firing */ byte curRollingCut = 0; /**< Rolling rev limiter, current ignition channel being cut */ byte rollingCutCounter = 0; /**< how many times (revolutions) the ignition has been cut in a row */ uint32_t rollingCutLastRev = 0; /**< Tracks whether we're on the same or a different rev for the rolling cut */ @@ -100,7 +101,7 @@ inline uint16_t applyFuelTrimToPW(trimTable3d *pTrimTable, int16_t fuelLoad, int /** Speeduino main loop. * - * Main loop chores (roughly in the order that they are performed): + * Main loop chores (roughly in order they are preformed): * - Check if serial comms or tooth logging are in progress (send or receive, prioritise communication) * - Record loop timing vars * - Check tooth time, update @ref statuses (currentStatus) variables @@ -395,7 +396,7 @@ void loop() { //if current input channel is enabled as analog local pin //read analog channel specified //currentStatus.canin[13] = (configPage9.Auxinpina[currentStatus.current_caninchannel]&63); Dev test use only!127 - currentStatus.canin[currentStatus.current_caninchannel] = readAuxanalog(pinTranslateAnalog(configPage9.Auxinpina[currentStatus.current_caninchannel]&63)); + currentStatus.canin[currentStatus.current_caninchannel] = readAuxanalog(configPage9.Auxinpina[currentStatus.current_caninchannel]&63); } else if ((((configPage9.enable_secondarySerial == 1) || ((configPage9.enable_intcan == 1) && (configPage9.intcan_available == 1))) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&12) == 12) || (((configPage9.enable_secondarySerial == 0) && ( (configPage9.enable_intcan == 1) && (configPage9.intcan_available == 0) )) && (configPage9.caninput_sel[currentStatus.current_caninchannel]&3) == 3) @@ -1327,7 +1328,7 @@ uint16_t PW(int REQ_FUEL, byte VE, long MAP, uint16_t corrections, int injOpen) if ( configPage2.multiplyMAP == MULTIPLY_MAP_MODE_100) { iMAP = ((unsigned int)MAP << 7) / 100; } else if( configPage2.multiplyMAP == MULTIPLY_MAP_MODE_BARO) { iMAP = ((unsigned int)MAP << 7) / currentStatus.baro; } - if ( (configPage2.includeAFR == true) && (configPage6.egoType == EGO_TYPE_WIDE) && (currentStatus.runSecs > configPage6.ego_sdelay) ) { + if ( (configPage2.includeAFR == true) && (configPage6.egoType == 2) && (currentStatus.runSecs > configPage6.ego_sdelay) ) { iAFR = ((unsigned int)currentStatus.O2 << 7) / currentStatus.afrTarget; //Include AFR (vs target) if enabled } if ( (configPage2.incorporateAFR == true) && (configPage2.includeAFR == false) ) { @@ -1340,7 +1341,7 @@ uint16_t PW(int REQ_FUEL, byte VE, long MAP, uint16_t corrections, int injOpen) unsigned long intermediate = ((uint32_t)REQ_FUEL * (uint32_t)iVE) >> 7; //Need to use an intermediate value to avoid overflowing the long if ( configPage2.multiplyMAP > 0 ) { intermediate = (intermediate * (unsigned long)iMAP) >> 7; } - if ( (configPage2.includeAFR == true) && (configPage6.egoType == EGO_TYPE_WIDE) && (currentStatus.runSecs > configPage6.ego_sdelay) ) { + if ( (configPage2.includeAFR == true) && (configPage6.egoType == 2) && (currentStatus.runSecs > configPage6.ego_sdelay) ) { //EGO type must be set to wideband and the AFR warmup time must've elapsed for this to be used intermediate = (intermediate * (unsigned long)iAFR) >> 7; } diff --git a/speeduino/src/PID_v1/PID_v1.cpp b/speeduino/src/PID_v1/PID_v1.cpp index 153e8acf..cd731d9c 100755 --- a/speeduino/src/PID_v1/PID_v1.cpp +++ b/speeduino/src/PID_v1/PID_v1.cpp @@ -54,21 +54,21 @@ bool PID::Compute() /*Compute all the working error variables*/ long input = *myInput; long error = *mySetpoint - input; - ITerm += (ki * error); + ITerm += (ki * error)/100; if(ITerm > outMax) ITerm= outMax; - else if(ITerm < outMin) ITerm = outMin; + else if(ITerm < outMin) ITerm= outMin; long dInput = (input - lastInput); /*Compute PID Output*/ - long output = (kp * error) + ITerm- (kd * dInput); + long output = (kp * error)/100 + ITerm- (kd * dInput)/100; if(output > outMax) { output = outMax; } else if(output < outMin) { output = outMin; } - *myOutput = output/1000; + *myOutput = output; /*Remember some variables for next time*/ lastInput = input; - lastTime = now; + //lastTime = now; return true; } //else return false; @@ -90,10 +90,10 @@ void PID::SetTunings(byte Kp, byte Ki, byte Kd) ki = Ki * SampleTimeInSec; kd = Kd / SampleTimeInSec; */ - //long InverseSampleTimeInSec = 100; + long InverseSampleTimeInSec = 100000 / SampleTime; kp = Kp; - ki = Ki; - kd = Kd * 10; + ki = (Ki * 100) / InverseSampleTimeInSec; + kd = (Kd * InverseSampleTimeInSec) / 100; if(controllerDirection ==REVERSE) { @@ -129,8 +129,8 @@ void PID::SetSampleTime(int NewSampleTime) void PID::SetOutputLimits(long Min, long Max) { if(Min >= Max) return; - outMin = Min*1000; - outMax = Max*1000; + outMin = Min; + outMax = Max; if(inAuto) { @@ -553,18 +553,6 @@ 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); @@ -579,19 +567,19 @@ bool integerPID_ideal::Compute(uint16_t FeedForward) ITerm += error; - // uint16_t bias = 50; //Base target DC% + uint16_t bias = 50; //Base target DC% long output = 0; if(ki != 0) { - output = ((outMax * limitMultiplier * 100) - FeedForward) / (long)ki; + output = ((outMax - bias) * limitMultiplier * 100) / (long)ki; if (output < 0) { output = 0; } } if (ITerm > output) { ITerm = output; } if(ki != 0) { - output = (FeedForward - (-outMin * limitMultiplier * 100)) / (long)ki; + output = ((bias - outMin) * limitMultiplier * 100) / (long)ki; if (output < 0) { output = 0; } } else { output = 0; } @@ -599,7 +587,7 @@ bool integerPID_ideal::Compute(uint16_t FeedForward) /*Compute PID Output*/ output = (kp * error) + (ki * ITerm) + (kd * (error - lastError)); - 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. + 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. //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 b3e9b274..694c1f3e 100755 --- a/speeduino/src/PID_v1/PID_v1.h +++ b/speeduino/src/PID_v1/PID_v1.h @@ -175,10 +175,6 @@ 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/src/SPIAsEEPROM/SPIAsEEPROM.cpp b/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp index e0f52567..0fb3e975 100644 --- a/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp +++ b/speeduino/src/SPIAsEEPROM/SPIAsEEPROM.cpp @@ -394,14 +394,6 @@ int8_t InternalSTM32F4_EEPROM_Class::writeFlashBytes(uint32_t flashAddress, byte uint16_t data = 0; uint32_t offset = 0; uint32_t countaddress = translatedAddress; - - //Clear any flash errors before try writing to flash to prevent write failures. - if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR); - if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR); - if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGPERR) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGPERR); - if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR); - if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR ) != RESET) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR); - HAL_FLASH_Unlock(); while (countaddress < translatedAddress + length) { memcpy(&data, buf + offset, sizeof(uint16_t)); diff --git a/speeduino/src/STM32_CAN/STM32_CAN.h b/speeduino/src/STM32_CAN/STM32_CAN.h index 0ea2e6d7..1cf19da9 100644 --- a/speeduino/src/STM32_CAN/STM32_CAN.h +++ b/speeduino/src/STM32_CAN/STM32_CAN.h @@ -109,8 +109,8 @@ class STM32_CAN { public: // Default buffer sizes are set to 16. But this can be changed by using constructor in main code. STM32_CAN(CAN_TypeDef* canPort, CAN_PINS pins, RXQUEUE_TABLE rxSize = RX_SIZE_16, TXQUEUE_TABLE txSize = TX_SIZE_16); - // Begin. By default the automatic retransmission is disabled in Speeduino, because it has been observed to cause sync issues. - void begin(bool retransmission = false); + // Begin. By default the automatic retransmission is enabled. If it causes problems, use begin(false) to disable it. + void begin(bool retransmission = true); void setBaudRate(uint32_t baud); bool write(CAN_message_t &CAN_tx_msg, bool sendMB = false); bool read(CAN_message_t &CAN_rx_msg); diff --git a/speeduino/storage.cpp b/speeduino/storage.cpp index ca95d1ef..f32c1c87 100644 --- a/speeduino/storage.cpp +++ b/speeduino/storage.cpp @@ -13,10 +13,16 @@ A full copy of the license may be found in the projects root directory #include "pages.h" #include "table3d_axis_io.h" +//The maximum number of write operations that will be performed in one go. If we try to write to the EEPROM too fast (Each write takes ~3ms) then the rest of the system can hang) +#if defined(CORE_STM32) || defined(CORE_TEENSY) & !defined(USE_SPI_EEPROM) +#define EEPROM_MAX_WRITE_BLOCK 64 +#else +#define EEPROM_MAX_WRITE_BLOCK 24 +//#define EEPROM_MAX_WRITE_BLOCK 8 +#endif #define EEPROM_DATA_VERSION 0 - // Calibration data is stored at the end of the EEPROM (This is in case any further calibration tables are needed as they are large blocks) #define STORAGE_END 0xFFF // Should be E2END? #define EEPROM_CALIBRATION_CLT_VALUES (STORAGE_END-sizeof(cltCalibration_values)) @@ -27,12 +33,13 @@ A full copy of the license may be found in the projects root directory #define EEPROM_CALIBRATION_O2_BINS (EEPROM_CALIBRATION_O2_VALUES-sizeof(o2Calibration_bins)) #define EEPROM_LAST_BARO (EEPROM_CALIBRATION_O2_BINS-1) - +static bool eepromWritesPending = false; +static bool forceBurn = false; uint32_t deferEEPROMWritesUntil = 0; bool isEepromWritePending() { - return BIT_CHECK(currentStatus.status4, BIT_STATUS4_BURNPENDING); + return eepromWritesPending; } /** Write all config pages to EEPROM. @@ -41,21 +48,21 @@ void writeAllConfig() { uint8_t pageCount = getPageCount(); uint8_t page = 1U; - writeConfig(page); - page = page + 1; - while (page 0) { canWrite = (counter <= write_block_size); } - else { canWrite = (counter <= (write_block_size * 8)); } //Write to EEPROM more aggressively if the engine is not running + if(currentStatus.RPM > 0) { canWrite = (counter <= EEPROM_MAX_WRITE_BLOCK); } + else { canWrite = (counter <= (EEPROM_MAX_WRITE_BLOCK * 8)); } //Write to EEPROM more aggressively if the engine is not running return canWrite; } @@ -95,7 +95,7 @@ struct write_location { static inline write_location write_range(const byte *pStart, const byte *pEnd, write_location location) { - while ( location.can_write() && pStart!=pEnd) + while ( (location.can_write() || forceBurn) && pStart!=pEnd) { location.update(*pStart); ++pStart; @@ -111,7 +111,7 @@ static inline write_location write(const table_row_iterator &row, write_location static inline write_location write(table_value_iterator it, write_location location) { - while (location.can_write() && !it.at_end()) + while ((location.can_write() || forceBurn) && !it.at_end()) { location = write(*it, location); ++it; @@ -122,7 +122,7 @@ static inline write_location write(table_value_iterator it, write_location locat static inline write_location write(table_axis_iterator it, write_location location) { const int16_byte *pConverter = table3d_axis_io::get_converter(it.domain()); - while (location.can_write() && !it.at_end()) + while ((location.can_write() || forceBurn) && !it.at_end()) { location.update(pConverter->to_byte(*it)); ++location; @@ -151,30 +151,9 @@ and writes them to EEPROM as per the layout defined in storage.h. */ void writeConfig(uint8_t pageNum) { -//The maximum number of write operations that will be performed in one go. -//If we try to write to the EEPROM too fast (Each write takes ~3ms) then -//the rest of the system can hang) -#if defined(CORE_STM32) || defined(CORE_TEENSY) & !defined(USE_SPI_EEPROM) - uint8_t EEPROM_MAX_WRITE_BLOCK = 64; -#else - uint8_t EEPROM_MAX_WRITE_BLOCK = 24; + write_location result = { 0, 0 }; -#ifdef CORE_AVR - //In order to prevent missed pulses during EEPROM writes on AVR, scale the - //maximum write block size based on the RPM. - //This calculation is based on EEPROM writes taking approximately 4ms per byte - //(Actual value is 3.8ms, so 4ms has some safety margin) - if(currentStatus.RPM > 65) //Min RPM of 65 prevents overflow of uint8_t - { - EEPROM_MAX_WRITE_BLOCK = (uint8_t)(15000U / currentStatus.RPM); - EEPROM_MAX_WRITE_BLOCK = max(EEPROM_MAX_WRITE_BLOCK, 1); - EEPROM_MAX_WRITE_BLOCK = min(EEPROM_MAX_WRITE_BLOCK, 24); //Any higher than this will cause comms timeouts on AVR - } -#endif - -#endif - - write_location result = { 0, 0, EEPROM_MAX_WRITE_BLOCK }; + //if(micros() < deferEEPROMWritesUntil) { result.counter = (EEPROM_MAX_WRITE_BLOCK + 1); } //If we are deferring writes then we don't want to write anything. This will force can_write() to return false and the write will be skipped. switch(pageNum) { @@ -183,7 +162,7 @@ void writeConfig(uint8_t pageNum) | Fuel table (See storage.h for data layout) - Page 1 | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&fuelTable, decltype(fuelTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG1_MAP)); + result = writeTable(&fuelTable, fuelTable.type_key, { EEPROM_CONFIG1_MAP, 0 }); break; case veSetPage: @@ -191,7 +170,7 @@ void writeConfig(uint8_t pageNum) | Config page 2 (See storage.h for data layout) | 64 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage2, (byte *)&configPage2+sizeof(configPage2), result.changeWriteAddress(EEPROM_CONFIG2_START)); + result = write_range((byte *)&configPage2, (byte *)&configPage2+sizeof(configPage2), { EEPROM_CONFIG2_START, 0 }); break; case ignMapPage: @@ -199,7 +178,7 @@ void writeConfig(uint8_t pageNum) | Ignition table (See storage.h for data layout) - Page 1 | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&ignitionTable, decltype(ignitionTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG3_MAP)); + result = writeTable(&ignitionTable, ignitionTable.type_key, { EEPROM_CONFIG3_MAP, 0 }); break; case ignSetPage: @@ -207,7 +186,7 @@ void writeConfig(uint8_t pageNum) | Config page 2 (See storage.h for data layout) | 64 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage4, (byte *)&configPage4+sizeof(configPage4), result.changeWriteAddress(EEPROM_CONFIG4_START)); + result = write_range((byte *)&configPage4, (byte *)&configPage4+sizeof(configPage4), { EEPROM_CONFIG4_START, 0 }); break; case afrMapPage: @@ -215,7 +194,7 @@ void writeConfig(uint8_t pageNum) | AFR table (See storage.h for data layout) - Page 5 | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&afrTable, decltype(afrTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG5_MAP)); + result = writeTable(&afrTable, afrTable.type_key, { EEPROM_CONFIG5_MAP, 0 }); break; case afrSetPage: @@ -223,7 +202,7 @@ void writeConfig(uint8_t pageNum) | Config page 3 (See storage.h for data layout) | 64 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage6, (byte *)&configPage6+sizeof(configPage6), result.changeWriteAddress(EEPROM_CONFIG6_START)); + result = write_range((byte *)&configPage6, (byte *)&configPage6+sizeof(configPage6), { EEPROM_CONFIG6_START, 0 }); break; case boostvvtPage: @@ -231,9 +210,9 @@ void writeConfig(uint8_t pageNum) | Boost and vvt tables (See storage.h for data layout) - Page 8 | 8x8 table itself + the 8 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&boostTable, decltype(boostTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG7_MAP1)); - result = writeTable(&vvtTable, decltype(vvtTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG7_MAP2)); - result = writeTable(&stagingTable, decltype(stagingTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG7_MAP3)); + result = writeTable(&boostTable, boostTable.type_key, { EEPROM_CONFIG7_MAP1, 0 }); + result = writeTable(&vvtTable, vvtTable.type_key, { EEPROM_CONFIG7_MAP2, result.counter }); + result = writeTable(&stagingTable, stagingTable.type_key, { EEPROM_CONFIG7_MAP3, result.counter }); break; case seqFuelPage: @@ -241,14 +220,14 @@ void writeConfig(uint8_t pageNum) | Fuel trim tables (See storage.h for data layout) - Page 9 | 6x6 tables itself + the 6 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&trim1Table, decltype(trim1Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP1)); - result = writeTable(&trim2Table, decltype(trim2Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP2)); - result = writeTable(&trim3Table, decltype(trim3Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP3)); - result = writeTable(&trim4Table, decltype(trim4Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP4)); - result = writeTable(&trim5Table, decltype(trim5Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP5)); - result = writeTable(&trim6Table, decltype(trim6Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP6)); - result = writeTable(&trim7Table, decltype(trim7Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP7)); - result = writeTable(&trim8Table, decltype(trim8Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG8_MAP8)); + result = writeTable(&trim1Table, trim1Table.type_key, { EEPROM_CONFIG8_MAP1, 0 }); + result = writeTable(&trim2Table, trim2Table.type_key, { EEPROM_CONFIG8_MAP2, result.counter }); + result = writeTable(&trim3Table, trim3Table.type_key, { EEPROM_CONFIG8_MAP3, result.counter }); + result = writeTable(&trim4Table, trim4Table.type_key, { EEPROM_CONFIG8_MAP4, result.counter }); + result = writeTable(&trim5Table, trim5Table.type_key, { EEPROM_CONFIG8_MAP5, result.counter }); + result = writeTable(&trim6Table, trim6Table.type_key, { EEPROM_CONFIG8_MAP6, result.counter }); + result = writeTable(&trim7Table, trim7Table.type_key, { EEPROM_CONFIG8_MAP7, result.counter }); + result = writeTable(&trim8Table, trim8Table.type_key, { EEPROM_CONFIG8_MAP8, result.counter }); break; case canbusPage: @@ -256,7 +235,7 @@ void writeConfig(uint8_t pageNum) | Config page 10 (See storage.h for data layout) | 192 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage9, (byte *)&configPage9+sizeof(configPage9), result.changeWriteAddress(EEPROM_CONFIG9_START)); + result = write_range((byte *)&configPage9, (byte *)&configPage9+sizeof(configPage9), { EEPROM_CONFIG9_START, 0 }); break; case warmupPage: @@ -264,7 +243,7 @@ void writeConfig(uint8_t pageNum) | Config page 11 (See storage.h for data layout) | 192 byte long config table -----------------------------------------------------*/ - result = write_range((byte *)&configPage10, (byte *)&configPage10+sizeof(configPage10), result.changeWriteAddress(EEPROM_CONFIG10_START)); + result = write_range((byte *)&configPage10, (byte *)&configPage10+sizeof(configPage10), { EEPROM_CONFIG10_START, 0}); break; case fuelMap2Page: @@ -272,7 +251,7 @@ void writeConfig(uint8_t pageNum) | Fuel table 2 (See storage.h for data layout) | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&fuelTable2, decltype(fuelTable2)::type_key, result.changeWriteAddress(EEPROM_CONFIG11_MAP)); + result = writeTable(&fuelTable2, fuelTable2.type_key, { EEPROM_CONFIG11_MAP, 0 }); break; case wmiMapPage: @@ -282,16 +261,16 @@ void writeConfig(uint8_t pageNum) | 8x8 VVT2 table + the 8 values along each of the axis | 4x4 Dwell table itself + the 4 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&wmiTable, decltype(wmiTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG12_MAP)); - result = writeTable(&vvt2Table, decltype(vvt2Table)::type_key, result.changeWriteAddress(EEPROM_CONFIG12_MAP2)); - result = writeTable(&dwellTable, decltype(dwellTable)::type_key, result.changeWriteAddress(EEPROM_CONFIG12_MAP3)); + result = writeTable(&wmiTable, wmiTable.type_key, { EEPROM_CONFIG12_MAP, 0 }); + result = writeTable(&vvt2Table, vvt2Table.type_key, { EEPROM_CONFIG12_MAP2, result.counter }); + result = writeTable(&dwellTable, dwellTable.type_key, { EEPROM_CONFIG12_MAP3, result.counter }); break; case progOutsPage: /*--------------------------------------------------- | Config page 13 (See storage.h for data layout) -----------------------------------------------------*/ - result = write_range((byte *)&configPage13, (byte *)&configPage13+sizeof(configPage13), result.changeWriteAddress(EEPROM_CONFIG13_START)); + result = write_range((byte *)&configPage13, (byte *)&configPage13+sizeof(configPage13), { EEPROM_CONFIG13_START, 0}); break; case ignMap2Page: @@ -299,27 +278,16 @@ void writeConfig(uint8_t pageNum) | Ignition table (See storage.h for data layout) - Page 1 | 16x16 table itself + the 16 values along each of the axis -----------------------------------------------------*/ - result = writeTable(&ignitionTable2, decltype(ignitionTable2)::type_key, result.changeWriteAddress(EEPROM_CONFIG14_MAP)); - 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, decltype(boostTableLookupDuty)::type_key, result.changeWriteAddress(EEPROM_CONFIG15_MAP)); - - /*--------------------------------------------------- - | Config page 15 (See storage.h for data layout) - -----------------------------------------------------*/ - result = write_range((byte *)&configPage15, (byte *)&configPage15+sizeof(configPage15), result.changeWriteAddress(EEPROM_CONFIG15_START)); + result = writeTable(&ignitionTable2, ignitionTable2.type_key, { EEPROM_CONFIG14_MAP, 0 }); break; default: break; } - BIT_WRITE(currentStatus.status4, BIT_STATUS4_BURNPENDING, !result.can_write()); + eepromWritesPending = !result.can_write(); + if(eepromWritesPending == true) { BIT_SET(currentStatus.status4, BIT_STATUS4_BURNPENDING); } + else { BIT_CLEAR(currentStatus.status4, BIT_STATUS4_BURNPENDING); } } /** Reset all configPage* structs (2,4,6,9,10,13) and write them full of null-bytes. @@ -352,7 +320,7 @@ static inline eeprom_address_t load_range(eeprom_address_t address, byte *pFirst #if defined(CORE_AVR) // The generic code in the #else branch works but this provides a 45% speed up on AVR size_t size = pLast-pFirst; - eeprom_read_block(pFirst, (const void*)(size_t)address, size); + eeprom_read_block(pFirst, (void*)address, size); return address+size; #else for (; pFirst != pLast; ++address, (void)++pFirst) @@ -391,7 +359,7 @@ static inline eeprom_address_t load(table_axis_iterator it, eeprom_address_t add } -static inline eeprom_address_t loadTable(const void *pTable, table_type_t key, eeprom_address_t address) +static inline eeprom_address_t loadTable(void *pTable, table_type_t key, eeprom_address_t address) { return load(y_begin(pTable, key).reverse(), load(x_begin(pTable, key), @@ -405,37 +373,37 @@ static inline eeprom_address_t loadTable(const void *pTable, table_type_t key, e */ void loadConfig() { - loadTable(&fuelTable, decltype(fuelTable)::type_key, EEPROM_CONFIG1_MAP); + loadTable(&fuelTable, fuelTable.type_key, EEPROM_CONFIG1_MAP); load_range(EEPROM_CONFIG2_START, (byte *)&configPage2, (byte *)&configPage2+sizeof(configPage2)); //********************************************************************************************************************************************************************************* //IGNITION CONFIG PAGE (2) - loadTable(&ignitionTable, decltype(ignitionTable)::type_key, EEPROM_CONFIG3_MAP); + loadTable(&ignitionTable, ignitionTable.type_key, EEPROM_CONFIG3_MAP); load_range(EEPROM_CONFIG4_START, (byte *)&configPage4, (byte *)&configPage4+sizeof(configPage4)); //********************************************************************************************************************************************************************************* //AFR TARGET CONFIG PAGE (3) - loadTable(&afrTable, decltype(afrTable)::type_key, EEPROM_CONFIG5_MAP); + loadTable(&afrTable, afrTable.type_key, EEPROM_CONFIG5_MAP); load_range(EEPROM_CONFIG6_START, (byte *)&configPage6, (byte *)&configPage6+sizeof(configPage6)); //********************************************************************************************************************************************************************************* // Boost and vvt tables load - loadTable(&boostTable, decltype(boostTable)::type_key, EEPROM_CONFIG7_MAP1); - loadTable(&vvtTable, decltype(vvtTable)::type_key, EEPROM_CONFIG7_MAP2); - loadTable(&stagingTable, decltype(stagingTable)::type_key, EEPROM_CONFIG7_MAP3); + loadTable(&boostTable, boostTable.type_key, EEPROM_CONFIG7_MAP1); + loadTable(&vvtTable, vvtTable.type_key, EEPROM_CONFIG7_MAP2); + loadTable(&stagingTable, stagingTable.type_key, EEPROM_CONFIG7_MAP3); //********************************************************************************************************************************************************************************* // Fuel trim tables load - loadTable(&trim1Table, decltype(trim1Table)::type_key, EEPROM_CONFIG8_MAP1); - loadTable(&trim2Table, decltype(trim2Table)::type_key, EEPROM_CONFIG8_MAP2); - loadTable(&trim3Table, decltype(trim3Table)::type_key, EEPROM_CONFIG8_MAP3); - loadTable(&trim4Table, decltype(trim4Table)::type_key, EEPROM_CONFIG8_MAP4); - loadTable(&trim5Table, decltype(trim5Table)::type_key, EEPROM_CONFIG8_MAP5); - loadTable(&trim6Table, decltype(trim6Table)::type_key, EEPROM_CONFIG8_MAP6); - loadTable(&trim7Table, decltype(trim7Table)::type_key, EEPROM_CONFIG8_MAP7); - loadTable(&trim8Table, decltype(trim8Table)::type_key, EEPROM_CONFIG8_MAP8); + loadTable(&trim1Table, trim1Table.type_key, EEPROM_CONFIG8_MAP1); + loadTable(&trim2Table, trim2Table.type_key, EEPROM_CONFIG8_MAP2); + loadTable(&trim3Table, trim3Table.type_key, EEPROM_CONFIG8_MAP3); + loadTable(&trim4Table, trim4Table.type_key, EEPROM_CONFIG8_MAP4); + loadTable(&trim5Table, trim5Table.type_key, EEPROM_CONFIG8_MAP5); + loadTable(&trim6Table, trim6Table.type_key, EEPROM_CONFIG8_MAP6); + loadTable(&trim7Table, trim7Table.type_key, EEPROM_CONFIG8_MAP7); + loadTable(&trim8Table, trim8Table.type_key, EEPROM_CONFIG8_MAP8); //********************************************************************************************************************************************************************************* //canbus control page load @@ -448,13 +416,13 @@ void loadConfig() //********************************************************************************************************************************************************************************* //Fuel table 2 (See storage.h for data layout) - loadTable(&fuelTable2, decltype(fuelTable2)::type_key, EEPROM_CONFIG11_MAP); + loadTable(&fuelTable2, fuelTable2.type_key, EEPROM_CONFIG11_MAP); //********************************************************************************************************************************************************************************* // WMI, VVT2 and Dwell table load - loadTable(&wmiTable, decltype(wmiTable)::type_key, EEPROM_CONFIG12_MAP); - loadTable(&vvt2Table, decltype(vvt2Table)::type_key, EEPROM_CONFIG12_MAP2); - loadTable(&dwellTable, decltype(dwellTable)::type_key, EEPROM_CONFIG12_MAP3); + loadTable(&wmiTable, wmiTable.type_key, EEPROM_CONFIG12_MAP); + loadTable(&vvt2Table, vvt2Table.type_key, EEPROM_CONFIG12_MAP2); + loadTable(&dwellTable, dwellTable.type_key, EEPROM_CONFIG12_MAP3); //********************************************************************************************************************************************************************************* //CONFIG PAGE (13) @@ -463,12 +431,7 @@ void loadConfig() //********************************************************************************************************************************************************************************* //SECOND IGNITION CONFIG PAGE (14) - loadTable(&ignitionTable2, decltype(ignitionTable2)::type_key, EEPROM_CONFIG14_MAP); - - //********************************************************************************************************************************************************************************* - //CONFIG PAGE (15) + boost duty lookup table (LUT) - loadTable(&boostTableLookupDuty, decltype(boostTableLookupDuty)::type_key, EEPROM_CONFIG15_MAP); - load_range(EEPROM_CONFIG15_START, (byte *)&configPage15, (byte *)&configPage15+sizeof(configPage15)); + loadTable(&ignitionTable2, ignitionTable2.type_key, EEPROM_CONFIG14_MAP); //********************************************************************************************************************************************************************************* } diff --git a/speeduino/storage.h b/speeduino/storage.h index 5c7c558e..072b6a9d 100644 --- a/speeduino/storage.h +++ b/speeduino/storage.h @@ -95,12 +95,7 @@ * | 3151 |36 | Trim8 table (6x6) | @ref EEPROM_CONFIG8_MAP8 | * | 3187 |6 | Trim8 table (X axis) (RPM) | | * | 3193 |6 | Trim8 table (Y axis) (MAP) | | - * | 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 | | + * | 3199 |475 | EMPTY | | * | 3674 |4 | CLT Calibration CRC32 | | * | 3678 |4 | IAT Calibration CRC32 | | * | 3682 |4 | O2 Calibration CRC32 | | @@ -125,6 +120,8 @@ void loadCalibration(); void writeCalibration(); void writeCalibrationPage(uint8_t pageNum); void resetConfigPages(); +void enableForceBurn(); +void disableForceBurn(); //These are utility functions that prevent other files from having to use EEPROM.h directly byte readLastBaro(); @@ -177,12 +174,6 @@ 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/timers.h b/speeduino/timers.h index 380af06e..1cb87a71 100644 --- a/speeduino/timers.h +++ b/speeduino/timers.h @@ -24,7 +24,7 @@ Hence we will preload the timer with 131 cycles to leave 125 until overflow (1ms volatile bool tachoAlt = false; #define TACHO_PULSE_HIGH() *tach_pin_port |= (tach_pin_mask) #define TACHO_PULSE_LOW() *tach_pin_port &= ~(tach_pin_mask) -enum TachoOutputStatus {TACHO_INACTIVE, READY, ACTIVE}; //The 3 statuses that the tacho output pulse can have. NOTE: Cannot just use 'INACTIVE' as this is already defined within the Teensy Libs +enum TachoOutputStatus {DEACTIVE, READY, ACTIVE}; //The 3 statuses that the tacho output pulse can have volatile uint8_t tachoEndTime; //The time (in ms) that the tacho pulse needs to end at volatile TachoOutputStatus tachoOutputFlag; diff --git a/speeduino/timers.ino b/speeduino/timers.ino index 672e1d4b..0bba668b 100644 --- a/speeduino/timers.ino +++ b/speeduino/timers.ino @@ -32,7 +32,6 @@ void initialiseTimers() loop100ms = 0; loop250ms = 0; loopSec = 0; - tachoOutputFlag = TACHO_INACTIVE; } @@ -69,8 +68,8 @@ void oneMSInterval() //Most ARM chips can simply call a function if(ignitionSchedule7.Status == RUNNING) { if( (ignitionSchedule7.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign7EndFunction(); ignitionSchedule7.Status = OFF; } } if(ignitionSchedule8.Status == RUNNING) { if( (ignitionSchedule8.startTime < targetOverdwellTime) && (configPage4.useDwellLim) && (isCrankLocked != true) ) { ign8EndFunction(); ignitionSchedule8.Status = OFF; } } - //Tacho output check. This code will not do anything if tacho pulse duration is fixed to coil dwell. - //Tacho is flagged as being ready for a pulse by the ignition outputs. + //Tacho output check + //Tacho is flagged as being ready for a pulse by the ignition outputs. if(tachoOutputFlag == READY) { //Check for half speed tacho @@ -84,7 +83,7 @@ void oneMSInterval() //Most ARM chips can simply call a function else { //Don't run on this pulse (Half speed tacho) - tachoOutputFlag = TACHO_INACTIVE; + tachoOutputFlag = DEACTIVE; } tachoAlt = !tachoAlt; //Flip the alternating value in case half speed tacho is in use. } @@ -94,7 +93,7 @@ void oneMSInterval() //Most ARM chips can simply call a function if((uint8_t)ms_counter == tachoEndTime) { TACHO_PULSE_HIGH(); - tachoOutputFlag = TACHO_INACTIVE; + tachoOutputFlag = DEACTIVE; } } // Tacho sweep @@ -161,9 +160,9 @@ void oneMSInterval() //Most ARM chips can simply call a function //************************************************************************************************************************************************** //This updates the runSecs variable - //If the engine is running or cranking, we need to update the run time counter. + //If the engine is running or cranking, we need ot update the run time counter. if (BIT_CHECK(currentStatus.engine, BIT_ENGINE_RUN)) - { //NOTE - There is a potential for a ~1sec gap between engine crank starting and the runSec number being incremented. This may delay ASE! + { //NOTE - There is a potential for a ~1sec gap between engine crank starting and ths runSec number being incremented. This may delay ASE! if (currentStatus.runSecs <= 254) //Ensure we cap out at 255 and don't overflow. (which would reset ASE and cause problems with the closed loop fuelling (Which has to wait for the O2 to warmup)) { currentStatus.runSecs++; } //Increment our run counter by 1 second. } @@ -271,3 +270,4 @@ void oneMSInterval() //Most ARM chips can simply call a function TCNT2 = 131; //Preload timer2 with 100 cycles, leaving 156 till overflow. #endif } + diff --git a/speeduino/updates.ino b/speeduino/updates.ino index 08befd0d..5f859b9b 100644 --- a/speeduino/updates.ino +++ b/speeduino/updates.ino @@ -220,7 +220,7 @@ void doUpdates() configPage4.cltAdvValues[5] = 0; - //March 19 added a tacho pulse duration that could default to stupidly high values. Check if this is the case and fix it if found. 6ms is the maximum allowed value + //March 19 added a tacho pulse duration that could default to stupidly high values. Check if this is the case and fix it if found. 6ms is tha maximum allowed value if(configPage2.tachoDuration > 6) { configPage2.tachoDuration = 3; } //MAP based AE was introduced, force the AE mode to be TPS for all existing tunes @@ -491,7 +491,7 @@ void doUpdates() configPage10.TrigEdgeThrd = 0; //Old use as On/Off selection is removed, so change VVT mode to On/Off based on that - if(configPage6.tachoMode == 1) { configPage6.vvtMode = VVT_MODE_ONOFF; } + if(configPage6.unused_bit == 1) { configPage6.vvtMode = VVT_MODE_ONOFF; } //Closed loop VVT improvements. Set safety limits to max/min working values and filter to minimum. configPage10.vvtCLMinAng = 0; @@ -579,29 +579,6 @@ void doUpdates() configPage4.vvtDelay = 0; configPage4.vvtMinClt = 0; - - //Set SD logging related settings to zero. - configPage13.onboard_log_csv_separator = 0; - configPage13.onboard_log_file_style = 0; - configPage13.onboard_log_file_rate = 0; - configPage13.onboard_log_filenaming = 0; - configPage13.onboard_log_storage = 0; - configPage13.onboard_log_trigger_boot = 0; - configPage13.onboard_log_trigger_RPM = 0; - configPage13.onboard_log_trigger_prot = 0; - configPage13.onboard_log_trigger_Vbat = 0; - configPage13.onboard_log_trigger_Epin = 0; - configPage13.onboard_log_tr1_duration = 0; - configPage13.onboard_log_tr2_thr_on = 0; - configPage13.onboard_log_tr2_thr_off = 0; - configPage13.onboard_log_tr3_thr_RPM = 0; - configPage13.onboard_log_tr3_thr_MAP = 0; - configPage13.onboard_log_tr3_thr_Oil = 0; - configPage13.onboard_log_tr3_thr_AFR = 0; - configPage13.onboard_log_tr4_thr_on = 0; - configPage13.onboard_log_tr4_thr_off = 0; - configPage13.onboard_log_tr5_Epin_pin = 0; - writeAllConfig(); storeEEPROMVersion(19); } @@ -612,68 +589,18 @@ void doUpdates() //Option added to select injector pairing on 4 cylinder engines if( configPage4.inj4cylPairing > INJ_PAIR_14_23 ) { configPage4.inj4cylPairing = 0; } //Check valid value - if( configPage2.nCylinders == 4 ) - { - if ( configPage2.injLayout == INJ_SEQUENTIAL ) { configPage4.inj4cylPairing = INJ_PAIR_13_24; } //Since #478 engine will always start in semi, make the sequence right for the majority of inlie 4 engines - else { configPage4.inj4cylPairing = INJ_PAIR_14_23; } //Force setting to use the default mode from previous FW versions. This is to prevent issues on any setups that have been wired accordingly - } + if( configPage2.nCylinders == 4 ) { configPage4.inj4cylPairing = INJ_PAIR_14_23; } //Force setting to use the default mode from previous FW versions. This is to prevent issues on any setups that have been wired accordingly configPage9.hardRevMode = 1; //Set hard rev limiter to Fixed mode - configPage6.tachoMode = 0; //CAN broadcast introduced 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; - } - - //AFR Protection added, add default values - configPage9.afrProtectEnabled = 0; //Disable by default - configPage9.afrProtectMinMAP = 90; //Is divided by 2, vlue represents 180kPa - configPage9.afrProtectMinRPM = 40; //4000 RPM min - configPage9.afrProtectMinTPS = 160; //80% TPS min - configPage9.afrProtectDeviation = 14; //1.4 AFR deviation - writeAllConfig(); storeEEPROMVersion(20); } - + //Final check is always for 255 and 0 (Brand new arduino) if( (readEEPROMVersion() == 0) || (readEEPROMVersion() == 255) ) { diff --git a/test/test_decoders/test_decoders.cpp b/test/test_decoders/test_decoders.cpp index 1fd37fd2..109426c8 100644 --- a/test/test_decoders/test_decoders.cpp +++ b/test/test_decoders/test_decoders.cpp @@ -1,6 +1,5 @@ #include -#include #include #include "missing_tooth/missing_tooth.h" diff --git a/test/test_fuel/test_corrections.cpp b/test/test_fuel/test_corrections.cpp index 186fa84f..ade67a24 100644 --- a/test/test_fuel/test_corrections.cpp +++ b/test/test_fuel/test_corrections.cpp @@ -8,7 +8,6 @@ void testCorrections() { test_corrections_WUE(); test_corrections_dfco(); - test_corrections_TAE(); //TPS based accel enrichment corrections /* RUN_TEST(test_corrections_cranking); //Not written yet RUN_TEST(test_corrections_ASE); //Not written yet @@ -141,7 +140,7 @@ void setup_DFCO_on() correctionDFCO(); dfcoTaper = 20; } -//********************************************************************************************************************** + void test_corrections_dfco_on(void) { //Test under ideal conditions that DFCO goes active @@ -186,144 +185,3 @@ void test_corrections_dfco() RUN_TEST(test_corrections_dfco_off_TPS); RUN_TEST(test_corrections_dfco_off_delay); } -//********************************************************************************************************************** -//Setup a basic TAE enrichment curve, threshold etc that are common to all tests. Specifica values maybe updated in each individual test -void test_corrections_TAE_setup() -{ - configPage2.aeMode = AE_MODE_TPS; //Set AE to TPS - - configPage4.taeValues[0] = 70; - configPage4.taeValues[1] = 103; - configPage4.taeValues[2] = 124; - configPage4.taeValues[3] = 136; - - //Note: These values are divided by 10 - configPage4.taeBins[0] = 0; - configPage4.taeBins[1] = 8; - configPage4.taeBins[2] = 22; - configPage4.taeBins[3] = 97; - - configPage2.taeThresh = 0; - - //Divided by 100 - configPage2.aeTaperMin = 10; //1000 - configPage2.aeTaperMax = 50; //5000 - - //Set the coolant to be above the warmup AE taper - configPage2.aeColdTaperMax = 60; - configPage2.aeColdTaperMin = 0; - currentStatus.coolant = (int)(configPage2.aeColdTaperMax - CALIBRATION_TEMPERATURE_OFFSET) + 1; - - BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ACC); //Make sure AE is turned off -} - -void test_corrections_TAE_no_rpm_taper() -{ - //Disable the taper - currentStatus.RPM = 2000; - configPage2.aeTaperMin = 50; //5000 - configPage2.aeTaperMax = 60; //6000 - - currentStatus.TPSlast = 0; - currentStatus.TPS = 50; //25% actual value - - uint16_t accelValue = correctionAccel(); //Run the AE calcs - - TEST_ASSERT_EQUAL(75, currentStatus.tpsDOT); //DOT is 750%/s (25 * 30), value divided by 10; - TEST_ASSERT_EQUAL((100+132), accelValue); - TEST_ASSERT_TRUE(BIT_CHECK(currentStatus.engine, BIT_ENGINE_ACC)); //Confirm AE is flagged on -} - -void test_corrections_TAE_50pc_rpm_taper() -{ - //RPM is 50% of the way through the taper range - currentStatus.RPM = 3000; - configPage2.aeTaperMin = 10; //1000 - configPage2.aeTaperMax = 50; //5000 - - currentStatus.TPSlast = 0; - currentStatus.TPS = 50; //25% actual value - - uint16_t accelValue = correctionAccel(); //Run the AE calcs - - TEST_ASSERT_EQUAL(75, currentStatus.tpsDOT); //DOT is 750%/s (25 * 30), value divided by 10; - TEST_ASSERT_EQUAL((100+66), accelValue); - TEST_ASSERT_TRUE(BIT_CHECK(currentStatus.engine, BIT_ENGINE_ACC)); //Confirm AE is flagged on -} - -void test_corrections_TAE_110pc_rpm_taper() -{ - //RPM is 110% of the way through the taper range, which should result in no additional AE - currentStatus.RPM = 5400; - configPage2.aeTaperMin = 10; //1000 - configPage2.aeTaperMax = 50; //5000 - - currentStatus.TPSlast = 0; - currentStatus.TPS = 50; //25% actual value - - uint16_t accelValue = correctionAccel(); //Run the AE calcs - - TEST_ASSERT_EQUAL(75, currentStatus.tpsDOT); //DOT is 750%/s (25 * 30), value divided by 10; - TEST_ASSERT_EQUAL(100, accelValue); //Should be no AE as we're above the RPM taper end point - TEST_ASSERT_TRUE(BIT_CHECK(currentStatus.engine, BIT_ENGINE_ACC)); //Confirm AE is flagged on -} - -void test_corrections_TAE_under_threshold() -{ - //RPM is 50% of the way through the taper range, but TPS value will be below threshold - currentStatus.RPM = 3000; - configPage2.aeTaperMin = 10; //1000 - configPage2.aeTaperMax = 50; //5000 - - currentStatus.TPSlast = 0; - currentStatus.TPS = 6; //3% actual value. TPSDot should be 90%/s - configPage2.taeThresh = 100; //Above the reading of 90%/s - - uint16_t accelValue = correctionAccel(); //Run the AE calcs - - TEST_ASSERT_EQUAL(9, currentStatus.tpsDOT); //DOT is 90%/s (3% * 30), value divided by 10; - TEST_ASSERT_EQUAL(100, accelValue); //Should be no AE as we're above the RPM taper end point - TEST_ASSERT_FALSE(BIT_CHECK(currentStatus.engine, BIT_ENGINE_ACC)); //Confirm AE is flagged off -} - -void test_corrections_TAE_50pc_warmup_taper() -{ - //Disable the RPM taper - currentStatus.RPM = 2000; - configPage2.aeTaperMin = 50; //5000 - configPage2.aeTaperMax = 60; //6000 - - currentStatus.TPSlast = 0; - currentStatus.TPS = 50; //25% actual value - - //Set a cold % of 50% increase - configPage2.aeColdPct = 150; - configPage2.aeColdTaperMax = 60 + CALIBRATION_TEMPERATURE_OFFSET; - configPage2.aeColdTaperMin = 0 + CALIBRATION_TEMPERATURE_OFFSET; - //Set the coolant to be 50% of the way through the warmup range - currentStatus.coolant = 30; - - uint16_t accelValue = correctionAccel(); //Run the AE calcs - - TEST_ASSERT_EQUAL(75, currentStatus.tpsDOT); //DOT is 750%/s (25 * 30), value divided by 10; - TEST_ASSERT_EQUAL((100+165), accelValue); //Total AE should be 132 + (50% * 50%) = 132 * 1.25 = 165 - TEST_ASSERT_TRUE(BIT_CHECK(currentStatus.engine, BIT_ENGINE_ACC)); //Confirm AE is flagged on -} - -void test_corrections_TAE() -{ - test_corrections_TAE_setup(); - - - RUN_TEST(test_corrections_TAE_no_rpm_taper); - BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ACC); //Flag must be cleared between tests - RUN_TEST(test_corrections_TAE_50pc_rpm_taper); - BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ACC); //Flag must be cleared between tests - RUN_TEST(test_corrections_TAE_110pc_rpm_taper); - BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ACC); //Flag must be cleared between tests - RUN_TEST(test_corrections_TAE_under_threshold); - BIT_CLEAR(currentStatus.engine, BIT_ENGINE_ACC); //Flag must be cleared between tests - RUN_TEST(test_corrections_TAE_50pc_warmup_taper); - - -} \ No newline at end of file diff --git a/test/test_fuel/test_corrections.h b/test/test_fuel/test_corrections.h index d9ef1bb1..0f148915 100644 --- a/test/test_fuel/test_corrections.h +++ b/test/test_fuel/test_corrections.h @@ -9,5 +9,4 @@ void test_corrections_bat(void); void test_corrections_iatdensity(void); void test_corrections_baro(void); void test_corrections_launch(void); -void test_corrections_dfco(void); -void test_corrections_TAE(void); \ No newline at end of file +void test_corrections_dfco(void); \ No newline at end of file From f9c346e6dd73c7c3ede7ff9db2c92bbbb2157668 Mon Sep 17 00:00:00 2001 From: Mike501 Date: Sat, 3 Sep 2022 22:50:18 +0100 Subject: [PATCH 43/46] recover missing files --- reference/speeduino.ini | 2 +- speeduino/decoders.ino | 455 +++++++++++++++++++++++++++++++++++++++- speeduino/init.ino | 10 +- 3 files changed, 458 insertions(+), 9 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index e8829b20..5395663b 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -492,7 +492,7 @@ page = 4 fuelPumpPin= bits , U08, 6,[1:6], "Board Default", "INVALID", "INVALID", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "INVALID", "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", "INVALID" useResync = bits, U08, 6,[7:7], "No", "Yes" sparkDur = scalar, U08, 7, "ms", 0.1, 0, 0, 25.5, 1 ; Spark duration - trigPatternSec = bits,U08, 8,[0:6], "Single tooth cam", "4-1 cam", "Poll level", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" + trigPatternSec = bits,U08, 8,[0:6], "Single tooth cam", "4-1 cam", "Poll level", "Nissan 1-3-4-2", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" PollLevelPol = bits, U08, 8,[7:7], "Low", "High" ;Reset Control diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index 83c4c1f5..8fd960ee 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -695,19 +695,468 @@ Note: There can be no missing teeth on the primary wheel. /** Dual Wheel Setup. * * */ +byte doubleGapHalfTeeth=0; +byte doubleGap1=0, doubleGap2=0; + + void triggerSetup_DualWheel() { + // triggerToothAngle = 360 / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth triggerToothAngle = 360 / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth - if(configPage4.TrigSpeed == CAM_SPEED) { triggerToothAngle = 720 / configPage4.triggerTeeth; } //Account for cam speed + if(configPage4.TrigSpeed == CAM_SPEED) { triggerToothAngle = 720 / configPage4.triggerTeeth; } //Account for cam speed toothCurrentCount = 255; //Default value - triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //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 discarded as noise + secondaryToothCount = 0; + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //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 triggerSecFilterTime = (1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed) secondDerivEnabled = false; decoderIsSequential = true; triggerToothAngleIsCorrect = true; //This is always true for this pattern - MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) + + //MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) + + MAX_STALL_TIME = 166667 * triggerToothAngle; //1 rpm for testing + + targetGap = 100000L; // random value larger than 0 to ensure we start off being less than target + toothLastToothTime = 0; + toothLastMinusOneToothTime = 0; + +//------------ + + checkSyncToothCount = (configPage4.triggerTeeth) >> 2; //25% of the total teeth. + + doubleGapHalfTeeth = configPage4.triggerTeeth / 2; + + // this is the tooth after the gap + doubleGap1 = doubleGapHalfTeeth+1; + doubleGap2 = configPage4.triggerTeeth+1; + + +// Serial3.begin (38400); + } +#define toothAfterGap curGap3 +void triggerPri_DualWheel_v2() +{ + curTime = micros(); + curGap = curTime - toothLastToothTime; + if ( curGap >= triggerFilterTime || toothLastMinusOneToothTime == 0) // ensure we do this code until we've seen 2 teeth + { + toothCurrentCount++; //Increment the tooth counter + validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters) + +// Serial3.print(" "); Serial3.print(toothCurrentCount); + + if( (toothLastToothTime > 0) && (toothLastMinusOneToothTime > 0) ) + { + //Begin the missing tooth detection + //If the time between the current tooth and the last is greater than 2x the time between the last tooth and the tooth before that, we make the assertion that we must be at the first tooth after the gap + + targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2; //Multiply by 2 (Checks for a gap 2x greater than the last one) + + if ( curGap > targetGap ) + { + // Found a missing tooth, need to add additional missing teeth to toothCurrentCount & set missing tooth flag & triggerToothAngleIsCorrect to false + toothCurrentCount = toothCurrentCount + 2; +// Serial3.print(" GAP GAP"); + + + // fake the last gap to ensure when we get to tooth 2 after the gap we don't get a silly large gap due to the missing teeth being part of the maths + curGap = toothLastToothTime - toothLastMinusOneToothTime; + toothLastToothTime = curTime - curGap; + toothLastMinusOneToothTime = toothLastToothTime - curGap; + + triggerToothAngleIsCorrect = false; + + // does the tooth = tooth after gap Should do otherwise lost sync + + // all code could be simplifed to "if (toothCurrent == toothAfterGap) hassync else lost sync + + if( (configPage2.nCylinders == 4 && toothCurrentCount != 19 && toothCurrentCount != 37 ) + || (configPage2.nCylinders == 6 && toothCurrentCount != 13 && toothCurrentCount != 25 && toothCurrentCount != 37 ) + || (configPage2.nCylinders == 8 && toothCurrentCount != 10 && toothCurrentCount != 19 && toothCurrentCount != 28 && toothCurrentCount != 37 ) + ) + { + // lost Sync as gap should be at the tooth after gap1 or gap2 +// Serial3.print(" LostSYNC1 ");Serial3.print(toothCurrentCount); + currentStatus.hasSync = false; + currentStatus.syncLossCounter++; + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //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 + toothLastToothTime = 0; + toothLastMinusOneToothTime = 0; + toothCurrentCount = toothAfterGap; + } + else + { + // now we think we're at the right place on crank, check if the cam is correct as well before calling sync + if ( toothCurrentCount == toothAfterGap ) + { + currentStatus.hasSync = true; + } + else + { +// Serial3.print(" LostSYNC2 "); Serial3.print(toothAfterGap); Serial3.print(":"); Serial3.print(toothCurrentCount); Serial3.print("> "); + currentStatus.hasSync = false; + currentStatus.syncLossCounter++; + triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //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 + toothLastToothTime = 0; + toothLastMinusOneToothTime = 0; + toothCurrentCount = toothAfterGap; + } + } + } + else + { + // no gap in trigger wheel, normal tooth + setFilter(curGap); //Recalc the new filter value + triggerToothAngleIsCorrect = true; + } + + + if ( currentStatus.hasSync == true ) + { + if( toothCurrentCount > configPage4.triggerTeeth ) + { +// Serial3.println(" ROT "); + toothCurrentCount = toothCurrentCount - configPage4.triggerTeeth ; + if( toothCurrentCount != 1) + { +// Serial3.print(" LostSYNC3"); + currentStatus.hasSync = false; + currentStatus.syncLossCounter++; + triggerToothAngleIsCorrect = false; + toothCurrentCount = 1; + } + + revolutionOne = !revolutionOne; //Flip sequential revolution tracker + toothOneMinusOneTime = toothOneTime; + toothOneTime = curTime; + currentStatus.startRevolutions++; //Counter + } + } + else + { + // no sync or not seen enough teeth - can't let trigger wheel tooth counter get greater than teeth on wheel + if (toothCurrentCount > configPage4.triggerTeeth) + { + toothCurrentCount = 1; + } + } + + } + + toothLastMinusOneToothTime = toothLastToothTime; + toothLastToothTime = curTime; + //NEW IGNITION MODE + if( (configPage2.perToothIgn == true) && (!BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK)) ) + { + int16_t crankAngle = ( (toothCurrentCount-1) * triggerToothAngle ) + configPage4.triggerAngle; + // crankAngle = ignitionLimits(crankAngle); + if( (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) && (revolutionOne == true) && (configPage4.TrigSpeed == CRANK_SPEED) ) + { + crankAngle += 360; + checkPerToothTiming(crankAngle, (configPage4.triggerTeeth + toothCurrentCount)); + } + else{ checkPerToothTiming(crankAngle, toothCurrentCount); } + } + } //Trigger filter +} + +/** Dual Wheel Secondary. + * + * */ + + +void triggerSec_DualWheel_v2() +{ + curTime2 = micros(); + curGap2 = curTime2 - toothLastSecToothTime; + + if ( curGap2 >= triggerFilterTime) // filter at same rate as crank on assumption more teeth on crank than cam. Due to variable tooth gaps on cam this seems safer implementation of filtering + { + toothLastMinusOneSecToothTime = toothLastSecToothTime; + toothLastSecToothTime = curTime2; + + switch(configPage4.trigPatternSec) + { + case SEC_TRIGGER_SINGLE: + if( (currentStatus.hasSync == false) || (currentStatus.startRevolutions <= configPage4.StgCycles) ) + { + // no sync & only just started the engine and first time we've seen cam + toothLastToothTime = micros(); + toothLastMinusOneToothTime = micros() - (6000000 / configPage4.triggerTeeth); //Fixes RPM at 10rpm until a full revolution has taken place + toothCurrentCount = configPage4.triggerTeeth; + triggerFilterTime = 0; //Need to turn the filter off here otherwise the first primary tooth after achieving sync is ignored + + currentStatus.hasSync = true; + } + else + { + if ( (toothCurrentCount != configPage4.triggerTeeth) && (currentStatus.startRevolutions > 2)) { currentStatus.syncLossCounter++; } //Indicates likely sync loss. + if (configPage4.useResync == 1) { toothCurrentCount = configPage4.triggerTeeth; } + } + toothAfterGap = 1; + revolutionOne = 1; //Sequential revolution reset + break; + + + case SEC_TRIGGER_NISSAN_1_3_4_2: + targetGap2 = targetGap * 4; // target gap to identify large gap between teeth. Assumes 4 is a reasonable size. Works for Nissan engine with this trigger pattern + + if ( curGap2 >= targetGap2 ) + { + // had a large gap betwen teeth and then seen a tooth. Use the counter to work out which tooth we've seen after the gap then reset the gap counter + // remember this is the cam tooth AFTER the tooth counted. + switch( secondaryToothCount) + { + case 2: + // is detected at the first tooth of the 1 tooth cam + revolutionOne = 0; //Sequential revolution reset + switch (configPage2.nCylinders) + { + case 4: + case 6: + case 8: + toothAfterGap = 37; + break; + } +// Serial3.println(" CAM 2 "); + break; + + case 1: + // is detected at the first tooth of the 3 tooth cam pattern + revolutionOne = 0; //Sequential revolution reset + switch (configPage2.nCylinders) + { + case 4: + case 8: + toothAfterGap = 19; + break; + case 6: + toothAfterGap = 17; + break; + } +// Serial3.println(" CAM 1 "); + break; + + case 3: + // is detected at the first tooth of the 4 tooth cam + revolutionOne = 1; //Sequential revolution reset + switch (configPage2.nCylinders) + { + case 4: + case 8: + case 6: + toothAfterGap = 37; + break; + } +// Serial3.println(" CAM 3 "); + break; + + case 4: + // is detected at the first tooth of the 2 tooth cam + revolutionOne = 1; //Sequential revolution reset + switch (configPage2.nCylinders) + { + case 4: + case 8: + toothAfterGap = 19; + break; + case 6: + toothAfterGap = 17; + break; + } +// Serial3.println(" CAM 4 "); + break; + } + secondaryToothCount = 1; + } + else + { + secondaryToothCount++; + } + break; + + default: + // have a cam selected that we don't have a decoder for. + currentStatus.hasSync = false; + currentStatus.syncLossCounter++; + break; + } + } //Trigger filter +} + +void triggerSetEndTeeth_DualWheel_v2() +{ + //The toothAdder variable is used for when a setup is running sequentially, but the primary wheel is running at crank speed. This way the count of teeth will go up to 2* the number of primary teeth to allow for a sequential count. + byte toothAdder = 0; + if( (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) && (configPage4.TrigSpeed == CRANK_SPEED) ) { toothAdder = configPage4.triggerTeeth; } + + int16_t tempIgnition1EndTooth; + tempIgnition1EndTooth = ( (ignition1EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition1EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition1EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition1EndTooth <= 0) { tempIgnition1EndTooth += (configPage4.triggerTeeth + toothAdder); } + + int16_t tempIgnition2EndTooth; + tempIgnition2EndTooth = ( (ignition2EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition2EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition2EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition2EndTooth <= 0) { tempIgnition2EndTooth += (configPage4.triggerTeeth + toothAdder); } + + int16_t tempIgnition3EndTooth; + tempIgnition3EndTooth = ( (ignition3EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition3EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition3EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition3EndTooth <= 0) { tempIgnition3EndTooth += (configPage4.triggerTeeth + toothAdder); } + + int16_t tempIgnition4EndTooth; + tempIgnition4EndTooth = ( (ignition4EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition4EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition4EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition4EndTooth <= 0) { tempIgnition4EndTooth += (configPage4.triggerTeeth + toothAdder); } + +#if IGN_CHANNELS >= 5 + int16_t tempIgnition5EndTooth; + tempIgnition5EndTooth = ( (ignition5EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition5EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition5EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition5EndTooth <= 0) { tempIgnition5EndTooth += (configPage4.triggerTeeth + toothAdder); } +#endif +#if IGN_CHANNELS >= 6 + int16_t tempIgnition6EndTooth; + tempIgnition6EndTooth = ( (ignition6EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition6EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition6EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition6EndTooth <= 0) { tempIgnition6EndTooth += (configPage4.triggerTeeth + toothAdder); } +#endif +#if IGN_CHANNELS >= 7 + int16_t tempIgnition7EndTooth; + tempIgnition7EndTooth = ( (ignition7EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition7EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition7EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition7EndTooth <= 0) { tempIgnition7EndTooth += (configPage4.triggerTeeth + toothAdder); } +#endif +#if IGN_CHANNELS >= 8 + int16_t tempIgnition8EndTooth; + tempIgnition8EndTooth = ( (ignition8EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ); + if(tempIgnition8EndTooth > (configPage4.triggerTeeth + toothAdder)) { tempIgnition8EndTooth -= (configPage4.triggerTeeth + toothAdder); } + if(tempIgnition8EndTooth <= 0) { tempIgnition8EndTooth += (configPage4.triggerTeeth + toothAdder); } +#endif + +// take into account the missing teeth on the flywheels + + if( configPage4.triggerMissingTeeth == 0) + { + ignition1EndTooth = tempIgnition1EndTooth; + ignition2EndTooth = tempIgnition2EndTooth; + ignition3EndTooth = tempIgnition3EndTooth; + ignition4EndTooth = tempIgnition4EndTooth; + +#if IGN_CHANNELS >= 5 + ignition5EndTooth = tempIgnition5EndTooth; +#endif +#if IGN_CHANNELS >= 6 + ignition6EndTooth = tempIgnition6EndTooth; +#endif +#if IGN_CHANNELS >= 7 + ignition7EndTooth = tempIgnition7EndTooth; +#endif +#if IGN_CHANNELS >= 8 + ignition8EndTooth = tempIgnition8EndTooth; +#endif + } + else if (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) + { + // check the calculated trigger tooth exists, if it doesn't use the previous tooth + // nb the toothAngles[x] holds the tooth after the gap, hence the '-1' to see if it matches a gap + + if( tempIgnition1EndTooth < configPage4.triggerTeeth) { ignition1EndTooth = triggerToothCalc (tempIgnition1EndTooth,0); } // 0 to 360 degrees + else { ignition1EndTooth = triggerToothCalc (tempIgnition1EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + + if( tempIgnition2EndTooth < configPage4.triggerTeeth) { ignition2EndTooth = triggerToothCalc (tempIgnition2EndTooth,0); } // 0 to 360 degrees + else { ignition2EndTooth = triggerToothCalc (tempIgnition2EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + + if( tempIgnition3EndTooth < configPage4.triggerTeeth) { ignition3EndTooth = triggerToothCalc (tempIgnition3EndTooth,0); } // 0 to 360 degrees + else { ignition3EndTooth = triggerToothCalc (tempIgnition3EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + + if( tempIgnition4EndTooth < configPage4.triggerTeeth) { ignition4EndTooth = triggerToothCalc (tempIgnition4EndTooth,0); } // 0 to 360 degrees + else { ignition4EndTooth = triggerToothCalc (tempIgnition4EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + +#if IGN_CHANNELS >= 5 + if( tempIgnition5EndTooth < configPage4.triggerTeeth) { ignition5EndTooth = triggerToothCalc (tempIgnition5EndTooth,0); } // 0 to 360 degrees + else { ignition5EndTooth = triggerToothCalc (tempIgnition5EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees +#endif + +#if IGN_CHANNELS >= 6 + if( tempIgnition6EndTooth < configPage4.triggerTeeth) { ignition6EndTooth = triggerToothCalc (tempIgnition6EndTooth,0); } // 0 to 360 degrees + else { ignition6EndTooth = triggerToothCalc (tempIgnition6EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees +#endif + +#if IGN_CHANNELS >= 7 + if( tempIgnition7EndTooth < configPage4.triggerTeeth) { ignition7EndTooth = triggerToothCalc (tempIgnition7EndTooth,0); } // 0 to 360 degrees + else { ignition7EndTooth = triggerToothCalc (tempIgnition7EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees +#endif + +#if IGN_CHANNELS >= 8 + if( tempIgnition8EndTooth < configPage4.triggerTeeth) { ignition8EndTooth = triggerToothCalc (tempIgnition8EndTooth,0); } // 0 to 360 degrees + else { ignition8EndTooth = triggerToothCalc (tempIgnition8EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees +#endif + } + else + { + ignition1EndTooth = triggerToothCalc (tempIgnition1EndTooth,0); + ignition2EndTooth = triggerToothCalc (tempIgnition2EndTooth,0); + ignition3EndTooth = triggerToothCalc (tempIgnition3EndTooth,0); + ignition4EndTooth = triggerToothCalc (tempIgnition4EndTooth,0); +#if IGN_CHANNELS >= 5 + ignition5EndTooth = triggerToothCalc (tempIgnition5EndTooth,0); // 0 to 360 degrees +#endif + +#if IGN_CHANNELS >= 6 + ignition6EndTooth = triggerToothCalc (tempIgnition6EndTooth,0); // 0 to 360 degrees +#endif + +#if IGN_CHANNELS >= 7 + ignition7EndTooth = triggerToothCalc (tempIgnition7EndTooth,0); // 0 to 360 degrees +#endif + +#if IGN_CHANNELS >= 8 + ignition8EndTooth = triggerToothCalc (tempIgnition8EndTooth,0); // 0 to 360 degrees +#endif + } + + lastToothCalcAdvance = currentStatus.advance; +} + +char triggerToothCalc_v2(int16_t tempIgnitionEndTooth, byte tempSequentialTooth) +{ + switch(configPage2.nCylinders) + { + case 4: + if(tempIgnitionEndTooth == 17 || tempIgnitionEndTooth == 18) + { tempIgnitionEndTooth = 16;} + else if (tempIgnitionEndTooth == 35 || tempIgnitionEndTooth == 36) + { tempIgnitionEndTooth = 34;} + break; + + case 6: + if(tempIgnitionEndTooth == 11 || tempIgnitionEndTooth == 12) + { tempIgnitionEndTooth = 10;} + else if (tempIgnitionEndTooth == 23 || tempIgnitionEndTooth == 24) + { tempIgnitionEndTooth = 22;} + else if (tempIgnitionEndTooth == 35 || tempIgnitionEndTooth == 36) + { tempIgnitionEndTooth = 34;} + break; + + case 8: + if(tempIgnitionEndTooth == 8 || tempIgnitionEndTooth == 9) + { tempIgnitionEndTooth = 7;} + else if (tempIgnitionEndTooth == 17 || tempIgnitionEndTooth == 18) + { tempIgnitionEndTooth = 16;} + else if (tempIgnitionEndTooth == 26 || tempIgnitionEndTooth == 27) + { tempIgnitionEndTooth = 25;} + else if (tempIgnitionEndTooth == 35 || tempIgnitionEndTooth == 36) + { tempIgnitionEndTooth = 34;} + break; + } + return tempIgnitionEndTooth; +} + + /** Dual Wheel Primary. * * */ diff --git a/speeduino/init.ino b/speeduino/init.ino index 66ba80f6..3ccd040f 100644 --- a/speeduino/init.ino +++ b/speeduino/init.ino @@ -2929,14 +2929,14 @@ void initialiseTriggers() attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge); break; - case 2: + case DECODER_DUAL_WHEEL: triggerSetup_DualWheel(); - triggerHandler = triggerPri_DualWheel; - triggerSecondaryHandler = triggerSec_DualWheel; + triggerHandler = triggerPri_DualWheel_v2; + triggerSecondaryHandler = triggerSec_DualWheel_v2; + getCrankAngle = getCrankAngle_DualWheel; + triggerSetEndTeeth = triggerSetEndTeeth_DualWheel_v2; decoderHasSecondary = true; getRPM = getRPM_DualWheel; - getCrankAngle = getCrankAngle_DualWheel; - triggerSetEndTeeth = triggerSetEndTeeth_DualWheel; if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering) else { primaryTriggerEdge = FALLING; } From fb7a6130686239cd0dffaee96818073ca5652bae Mon Sep 17 00:00:00 2001 From: Mike501 Date: Sat, 3 Sep 2022 22:53:06 +0100 Subject: [PATCH 44/46] add vvt --- speeduino/decoders.ino | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index 8fd960ee..e3d28f53 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -897,6 +897,17 @@ void triggerSec_DualWheel_v2() } toothAfterGap = 1; revolutionOne = 1; //Sequential revolution reset + //Record the VVT Angle + if( (configPage6.vvtEnabled > 0) && (revolutionOne == 1) ) + { + int16_t curAngle; + curAngle = getCrankAngle(); + while(curAngle > 360) { curAngle -= 360; } + curAngle -= configPage4.triggerAngle; //Value at TDC + if( configPage6.vvtMode == VVT_MODE_CLOSED_LOOP ) { curAngle -= configPage10.vvtCL0DutyAng; } + + currentStatus.vvt1Angle = ANGLE_FILTER( (curAngle << 1), configPage4.ANGLEFILTER_VVT, currentStatus.vvt1Angle); + } break; @@ -909,7 +920,7 @@ void triggerSec_DualWheel_v2() // remember this is the cam tooth AFTER the tooth counted. switch( secondaryToothCount) { - case 2: + case 2: //315 degrees on 4 cylinder // is detected at the first tooth of the 1 tooth cam revolutionOne = 0; //Sequential revolution reset switch (configPage2.nCylinders) @@ -920,10 +931,10 @@ void triggerSec_DualWheel_v2() toothAfterGap = 37; break; } -// Serial3.println(" CAM 2 "); - break; + break; - case 1: + + case 1: //135 degrees on 4 cylinder // is detected at the first tooth of the 3 tooth cam pattern revolutionOne = 0; //Sequential revolution reset switch (configPage2.nCylinders) @@ -936,10 +947,9 @@ void triggerSec_DualWheel_v2() toothAfterGap = 17; break; } -// Serial3.println(" CAM 1 "); break; - case 3: + case 3: //334.5 degrees on 4 cylinder // is detected at the first tooth of the 4 tooth cam revolutionOne = 1; //Sequential revolution reset switch (configPage2.nCylinders) @@ -950,10 +960,10 @@ void triggerSec_DualWheel_v2() toothAfterGap = 37; break; } -// Serial3.println(" CAM 3 "); + break; - case 4: + case 4: //155 degrees on 4 cylinder // is detected at the first tooth of the 2 tooth cam revolutionOne = 1; //Sequential revolution reset switch (configPage2.nCylinders) @@ -966,7 +976,16 @@ void triggerSec_DualWheel_v2() toothAfterGap = 17; break; } -// Serial3.println(" CAM 4 "); + if( (configPage6.vvtEnabled > 0) ) + { + int16_t curAngle; + curAngle = getCrankAngle(); + while(curAngle > 360) { curAngle -= 360; } + curAngle -= configPage4.triggerAngle; //Value at TDC + if( configPage6.vvtMode == VVT_MODE_CLOSED_LOOP ) { curAngle -= configPage10.vvtCL0DutyAng; } + + currentStatus.vvt1Angle = ANGLE_FILTER( (curAngle << 1), configPage4.ANGLEFILTER_VVT, currentStatus.vvt1Angle); + } break; } secondaryToothCount = 1; @@ -983,6 +1002,9 @@ void triggerSec_DualWheel_v2() currentStatus.syncLossCounter++; break; } + + + } //Trigger filter } @@ -1157,6 +1179,7 @@ char triggerToothCalc_v2(int16_t tempIgnitionEndTooth, byte tempSequentialTooth) } + /** Dual Wheel Primary. * * */ From 711585b8c4731ea22ac965598de9f52f7c7e58cb Mon Sep 17 00:00:00 2001 From: Mike501 Date: Sun, 4 Sep 2022 00:01:21 +0100 Subject: [PATCH 45/46] missing files --- reference/speeduino.ini | 4 +-- speeduino/decoders.ino | 68 ++++++++++++++++++++++------------------- speeduino/globals.h | 1 + 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 5395663b..2e2a8f3e 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -2744,7 +2744,7 @@ menuDialog = main field = "Trigger Pattern", TrigPattern field = "Primary base teeth", numTeeth, { TrigPattern == 0 || TrigPattern == 2 || TrigPattern == 11 || TrigPattern == 18 || TrigPattern == 19 || TrigPattern == 21 } field = "Primary trigger speed", TrigSpeed, { TrigPattern == 0 || TrigPattern == 2 } - field = "Missing teeth", missingTeeth, { TrigPattern == 0 } + field = "Missing teeth", missingTeeth, { TrigPattern == 0 || TrigPattern == 2 } field = "Trigger angle multiplier", TrigAngMul, { TrigPattern == 11 } field = "Trigger Angle ", TrigAng field = "This number represents the angle ATDC when " @@ -2755,7 +2755,7 @@ menuDialog = main field = "cranking before the injectors and coils are fired" field = "Trigger edge", TrigEdge { TrigPattern != 4 && TrigPattern != 22 } ;4G63 uses both edges ;NGC uses both edges field = "Secondary trigger edge", TrigEdgeSec, { (TrigPattern == 0 && TrigSpeed == 0 && trigPatternSec != 2) || TrigPattern == 2 || TrigPattern == 9 || TrigPattern == 12 || TrigPattern == 18 || TrigPattern == 19 || TrigPattern == 20 || TrigPattern == 21 } ;Missing tooth, dual wheel and Miata 9905, weber-marelli, ST170, DRZ400 - field = "Missing Tooth Secondary type", trigPatternSec, { (TrigPattern == 0&& TrigSpeed == 0) } + field = "Missing Tooth Secondary type", trigPatternSec, { (TrigPattern == 0 && TrigSpeed == 0) || TrigPattern == 2 } field = "Level for 1st phase", PollLevelPol, { (TrigPattern == 0 && TrigSpeed == 0 && trigPatternSec == 2) } field = "Trigger Filter", TrigFilter, { TrigPattern != 13 } field = "Re-sync every cycle", useResync, { TrigPattern == 2 || TrigPattern == 4 || TrigPattern == 7 || TrigPattern == 12 || TrigPattern == 9 || TrigPattern == 13 || TrigPattern == 18 || TrigPattern == 19 || TrigPattern == 21 } ;Dual wheel, 4G63, Audi 135, Nissan 360, Miata 99-05, weber-marelli. DRZ400 diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index e3d28f53..fd454dc2 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -731,7 +731,7 @@ void triggerSetup_DualWheel() doubleGap2 = configPage4.triggerTeeth+1; -// Serial3.begin (38400); + // Serial3.begin (38400); } @@ -745,7 +745,8 @@ void triggerPri_DualWheel_v2() toothCurrentCount++; //Increment the tooth counter validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters) -// Serial3.print(" "); Serial3.print(toothCurrentCount); + // Serial3.print(" "); + // Serial3.print(toothCurrentCount); if( (toothLastToothTime > 0) && (toothLastMinusOneToothTime > 0) ) { @@ -758,7 +759,7 @@ void triggerPri_DualWheel_v2() { // Found a missing tooth, need to add additional missing teeth to toothCurrentCount & set missing tooth flag & triggerToothAngleIsCorrect to false toothCurrentCount = toothCurrentCount + 2; -// Serial3.print(" GAP GAP"); + // Serial3.print(" GAP GAP"); // fake the last gap to ensure when we get to tooth 2 after the gap we don't get a silly large gap due to the missing teeth being part of the maths @@ -778,7 +779,8 @@ void triggerPri_DualWheel_v2() ) { // lost Sync as gap should be at the tooth after gap1 or gap2 -// Serial3.print(" LostSYNC1 ");Serial3.print(toothCurrentCount); + // Serial3.print(" LostSYNC1 "); + // Serial3.print(toothCurrentCount); currentStatus.hasSync = false; currentStatus.syncLossCounter++; triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //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 @@ -795,7 +797,11 @@ void triggerPri_DualWheel_v2() } else { -// Serial3.print(" LostSYNC2 "); Serial3.print(toothAfterGap); Serial3.print(":"); Serial3.print(toothCurrentCount); Serial3.print("> "); + // Serial3.print(" LostSYNC2 "); + // Serial3.print(toothAfterGap); + // Serial3.print(":"); + // Serial3.print(toothCurrentCount); + // Serial3.print("> "); currentStatus.hasSync = false; currentStatus.syncLossCounter++; triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //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 @@ -817,11 +823,11 @@ void triggerPri_DualWheel_v2() { if( toothCurrentCount > configPage4.triggerTeeth ) { -// Serial3.println(" ROT "); + // Serial3.println(" ROT "); toothCurrentCount = toothCurrentCount - configPage4.triggerTeeth ; if( toothCurrentCount != 1) { -// Serial3.print(" LostSYNC3"); + // Serial3.print(" LostSYNC3"); currentStatus.hasSync = false; currentStatus.syncLossCounter++; triggerToothAngleIsCorrect = false; @@ -1086,58 +1092,58 @@ void triggerSetEndTeeth_DualWheel_v2() // check the calculated trigger tooth exists, if it doesn't use the previous tooth // nb the toothAngles[x] holds the tooth after the gap, hence the '-1' to see if it matches a gap - if( tempIgnition1EndTooth < configPage4.triggerTeeth) { ignition1EndTooth = triggerToothCalc (tempIgnition1EndTooth,0); } // 0 to 360 degrees - else { ignition1EndTooth = triggerToothCalc (tempIgnition1EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + if( tempIgnition1EndTooth < configPage4.triggerTeeth) { ignition1EndTooth = triggerToothCalc_v2 (tempIgnition1EndTooth,0); } // 0 to 360 degrees + else { ignition1EndTooth = triggerToothCalc_v2 (tempIgnition1EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees - if( tempIgnition2EndTooth < configPage4.triggerTeeth) { ignition2EndTooth = triggerToothCalc (tempIgnition2EndTooth,0); } // 0 to 360 degrees - else { ignition2EndTooth = triggerToothCalc (tempIgnition2EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + if( tempIgnition2EndTooth < configPage4.triggerTeeth) { ignition2EndTooth = triggerToothCalc_v2 (tempIgnition2EndTooth,0); } // 0 to 360 degrees + else { ignition2EndTooth = triggerToothCalc_v2 (tempIgnition2EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees - if( tempIgnition3EndTooth < configPage4.triggerTeeth) { ignition3EndTooth = triggerToothCalc (tempIgnition3EndTooth,0); } // 0 to 360 degrees - else { ignition3EndTooth = triggerToothCalc (tempIgnition3EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + if( tempIgnition3EndTooth < configPage4.triggerTeeth) { ignition3EndTooth = triggerToothCalc_v2 (tempIgnition3EndTooth,0); } // 0 to 360 degrees + else { ignition3EndTooth = triggerToothCalc_v2 (tempIgnition3EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees - if( tempIgnition4EndTooth < configPage4.triggerTeeth) { ignition4EndTooth = triggerToothCalc (tempIgnition4EndTooth,0); } // 0 to 360 degrees - else { ignition4EndTooth = triggerToothCalc (tempIgnition4EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + if( tempIgnition4EndTooth < configPage4.triggerTeeth) { ignition4EndTooth = triggerToothCalc_v2 (tempIgnition4EndTooth,0); } // 0 to 360 degrees + else { ignition4EndTooth = triggerToothCalc_v2 (tempIgnition4EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees #if IGN_CHANNELS >= 5 - if( tempIgnition5EndTooth < configPage4.triggerTeeth) { ignition5EndTooth = triggerToothCalc (tempIgnition5EndTooth,0); } // 0 to 360 degrees - else { ignition5EndTooth = triggerToothCalc (tempIgnition5EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + if( tempIgnition5EndTooth < configPage4.triggerTeeth) { ignition5EndTooth = triggerToothCalc_v2 (tempIgnition5EndTooth,0); } // 0 to 360 degrees + else { ignition5EndTooth = triggerToothCalc_v2 (tempIgnition5EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees #endif #if IGN_CHANNELS >= 6 - if( tempIgnition6EndTooth < configPage4.triggerTeeth) { ignition6EndTooth = triggerToothCalc (tempIgnition6EndTooth,0); } // 0 to 360 degrees - else { ignition6EndTooth = triggerToothCalc (tempIgnition6EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + if( tempIgnition6EndTooth < configPage4.triggerTeeth) { ignition6EndTooth = triggerToothCalc_v2 (tempIgnition6EndTooth,0); } // 0 to 360 degrees + else { ignition6EndTooth = triggerToothCalc_v2 (tempIgnition6EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees #endif #if IGN_CHANNELS >= 7 - if( tempIgnition7EndTooth < configPage4.triggerTeeth) { ignition7EndTooth = triggerToothCalc (tempIgnition7EndTooth,0); } // 0 to 360 degrees - else { ignition7EndTooth = triggerToothCalc (tempIgnition7EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + if( tempIgnition7EndTooth < configPage4.triggerTeeth) { ignition7EndTooth = triggerToothCalc_v2 (tempIgnition7EndTooth,0); } // 0 to 360 degrees + else { ignition7EndTooth = triggerToothCalc_v2 (tempIgnition7EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees #endif #if IGN_CHANNELS >= 8 - if( tempIgnition8EndTooth < configPage4.triggerTeeth) { ignition8EndTooth = triggerToothCalc (tempIgnition8EndTooth,0); } // 0 to 360 degrees - else { ignition8EndTooth = triggerToothCalc (tempIgnition8EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees + if( tempIgnition8EndTooth < configPage4.triggerTeeth) { ignition8EndTooth = triggerToothCalc_v2 (tempIgnition8EndTooth,0); } // 0 to 360 degrees + else { ignition8EndTooth = triggerToothCalc_v2 (tempIgnition8EndTooth,configPage4.triggerTeeth); } // tooth is on the 360 to 720 degrees #endif } else { - ignition1EndTooth = triggerToothCalc (tempIgnition1EndTooth,0); - ignition2EndTooth = triggerToothCalc (tempIgnition2EndTooth,0); - ignition3EndTooth = triggerToothCalc (tempIgnition3EndTooth,0); - ignition4EndTooth = triggerToothCalc (tempIgnition4EndTooth,0); + ignition1EndTooth = triggerToothCalc_v2 (tempIgnition1EndTooth,0); + ignition2EndTooth = triggerToothCalc_v2 (tempIgnition2EndTooth,0); + ignition3EndTooth = triggerToothCalc_v2 (tempIgnition3EndTooth,0); + ignition4EndTooth = triggerToothCalc_v2 (tempIgnition4EndTooth,0); #if IGN_CHANNELS >= 5 - ignition5EndTooth = triggerToothCalc (tempIgnition5EndTooth,0); // 0 to 360 degrees + ignition5EndTooth = triggerToothCalc_v2 (tempIgnition5EndTooth,0); // 0 to 360 degrees #endif #if IGN_CHANNELS >= 6 - ignition6EndTooth = triggerToothCalc (tempIgnition6EndTooth,0); // 0 to 360 degrees + ignition6EndTooth = triggerToothCalc_v2 (tempIgnition6EndTooth,0); // 0 to 360 degrees #endif #if IGN_CHANNELS >= 7 - ignition7EndTooth = triggerToothCalc (tempIgnition7EndTooth,0); // 0 to 360 degrees + ignition7EndTooth = triggerToothCalc_v2 (tempIgnition7EndTooth,0); // 0 to 360 degrees #endif #if IGN_CHANNELS >= 8 - ignition8EndTooth = triggerToothCalc (tempIgnition8EndTooth,0); // 0 to 360 degrees + ignition8EndTooth = triggerToothCalc_v2 (tempIgnition8EndTooth,0); // 0 to 360 degrees #endif } diff --git a/speeduino/globals.h b/speeduino/globals.h index 917332ee..892ffd5d 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -275,6 +275,7 @@ #define SEC_TRIGGER_SINGLE 0 #define SEC_TRIGGER_4_1 1 #define SEC_TRIGGER_POLL 2 +#define SEC_TRIGGER_NISSAN_1_3_4_2 3 #define ROTARY_IGN_FC 0 #define ROTARY_IGN_FD 1 From 24a0cf991d37cc1f44e3e69b3757d39e86ebdc8c Mon Sep 17 00:00:00 2001 From: Mike501 Date: Sat, 22 Oct 2022 10:37:08 +0100 Subject: [PATCH 46/46] fix stall time from debug version --- speeduino/decoders.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index 093e8f68..62ab327c 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -712,9 +712,9 @@ void triggerSetup_DualWheel() decoderIsSequential = true; triggerToothAngleIsCorrect = true; //This is always true for this pattern - //MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) + MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) - MAX_STALL_TIME = 166667 * triggerToothAngle; //1 rpm for testing + // MAX_STALL_TIME = 166667 * triggerToothAngle; //1 rpm for testing targetGap = 100000L; // random value larger than 0 to ensure we start off being less than target toothLastToothTime = 0;