diff --git a/reference/speeduino.ini b/reference/speeduino.ini index 04ad75ea..72902c7b 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -280,7 +280,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", "54", "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 - unused4-8 = scalar, U08, 8, "ms", 0.1, 0.0, 0.0, 25.5, 1 + trigPatternSec = bits, U08, 8,[0:7], "Single tooth cam", "4-1 cam", "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", "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", "INVALID", "INVALID", "INVALID", "INVALID" unused4-9 = scalar, U08, 9, "ms", 0.1, 0.0, 0.0, 25.5, 1 unused4-10 = scalar, U08, 10, "ms", 0.1, 0.0, 0.0, 25.5, 1 SkipCycles = scalar, U08, 11, "cycles", 1, 0, 0, 255, 0 @@ -728,6 +728,7 @@ page = 10 requiresPowerCycle = reqFuel requiresPowerCycle = numTeeth requiresPowerCycle = missingTeeth + requiresPowerCycle = trigPatternSec requiresPowerCycle = injOpen requiresPowerCycle = IgInv requiresPowerCycle = fanInv @@ -757,6 +758,7 @@ page = 10 defaultValue = pinLayout, 1 defaultValue = TrigPattern, 0 defaultValue = useResync, 1 + defaultValue = trigPatternSec, 0 defaultValue = sparkMode, 0 defaultValue = indInjAng, 0 defaultValue = inj1Ang, 355 @@ -940,6 +942,7 @@ menuDialog = main TrigPattern = "The type of input trigger decoder to be used." useResync = "If enabled, sync will be rechecked once every full cycle from the cam input. This is good for accuracy, however if your cam input is noisy then this can cause issues." + trigPatternSec = "Cam mode/type also known as Secondary Trigger Pattern." numTeeth = "Number of teeth on Primary Wheel." TrigSpeed = "Primary trigger speed." missingTeeth= "Number of Missing teeth on Primary Wheel." @@ -1325,6 +1328,7 @@ menuDialog = main field = "cranking before the injectors and coils are fired" field = "Trigger edge", TrigEdge field = "Secondary trigger edge", TrigEdgeSec, { TrigPattern == 0 || TrigPattern == 2 || TrigPattern == 9 || TrigPattern == 12 } ;Missing tooth, dual wheel and Miata 9905 + field = "Missing Tooth Secondary type" trigPatternSec, { TrigPattern == 0 } field = "Trigger Filter", TrigFilter field = "Re-sync every cycle", useResync, { TrigPattern == 2 || TrigPattern == 4 || TrigPattern == 7 || TrigPattern == 12 || TrigPattern == 9 } ;Dual wheel, 4G63, Audi 135, Nissan 360, Miata 99-05 field = "" diff --git a/speeduino/decoders.h b/speeduino/decoders.h index 5ece0970..9e571645 100644 --- a/speeduino/decoders.h +++ b/speeduino/decoders.h @@ -43,6 +43,10 @@ volatile unsigned long toothSystemLastToothTime = 0; //As below, but used for de volatile unsigned long toothLastToothTime = 0; //The time (micros()) that the last tooth was registered volatile unsigned long toothLastSecToothTime = 0; //The time (micros()) that the last tooth was registered on the secondary input volatile unsigned long toothLastMinusOneToothTime = 0; //The time (micros()) that the tooth before the last tooth was registered +#ifndef SMALL_FLASH_MODE +volatile unsigned long toothLastMinusOneSecToothTime = 0; //The time (micros()) that the tooth before the last tooth was registered on secondary input +volatile unsigned long targetGap2; +#endif volatile unsigned long toothOneTime = 0; //The time (micros()) that tooth 1 last triggered volatile unsigned long toothOneMinusOneTime = 0; //The 2nd to last time (micros()) that tooth 1 last triggered volatile bool revolutionOne = 0; // For sequential operation, this tracks whether the current revolution is 1 or 2 (not 1) diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index abe970d1..b5ef7637 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -128,6 +128,7 @@ void triggerSetup_missingTooth() if(configPage2.TrigSpeed == 1) { triggerToothAngle = 720 / configPage2.triggerTeeth; } //Account for cam speed missing tooth triggerActualTeeth = configPage2.triggerTeeth - configPage2.triggerMissingTeeth; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt triggerFilterTime = (int)(1000000 / (MAX_RPM / 60 * configPage2.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 = (int)((trigPatternSec == true) ? 1000000 * 60 / MAX_RPM / 4 / 2 : 1000000 * 60 / MAX_RPM / 2 / 2); //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed) secondDerivEnabled = false; decoderIsSequential = false; checkSyncToothCount = (configPage2.triggerTeeth) >> 1; //50% of the total teeth. @@ -197,8 +198,39 @@ void triggerPri_missingTooth() void triggerSec_missingTooth() { - //TODO: This should really have filtering enabled on the secondary input. - revolutionOne = 1; + curTime2 = micros(); + curGap2 = curTime2 - toothLastSecToothTime; + if( (toothLastSecToothTime == 0) +#ifndef SMALL_FLASH_MODE + || (toothLastMinusOneSecToothTime == 0 ) +#endif + ) { curGap2 = 0; } + if ( curGap2 >= triggerSecFilterTime ) + { +#ifndef SMALL_FLASH_MODE + if ( trigPatternSec == true ) + { + targetGap2 = (3 * (toothLastSecToothTime - toothLastMinusOneSecToothTime)) >> 1; //If the time between the current tooth and the last is greater than 1.5x 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 + toothLastMinusOneSecToothTime = toothLastSecToothTime; + if ( ( curGap2 >= targetGap2 ) || ( secondaryToothCount > 3 ) ) + { + secondaryToothCount = 1; + revolutionOne = 1; //Sequential revolution reset + triggerSecFilterTime = 0; //This is used to prevent a condition where serious intermitent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state + } + else + { + triggerSecFilterTime = curGap2 >> 2; //Set filter at 25% of the current speed. Filter can only be recalc'd for the regular teeth, not the missing one. + secondaryToothCount++; + } + } + else +#endif + { + revolutionOne = 1; //Sequential revolution reset + } + toothLastSecToothTime = curTime2; + } //Trigger filter } uint16_t getRPM_missingTooth() diff --git a/speeduino/globals.h b/speeduino/globals.h index 4a0c1b4f..c6eb04a7 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -428,7 +428,7 @@ struct config2 { byte useResync : 1; byte sparkDur; //Spark duration in ms * 10 - byte unused4_8; + bool trigPatternSec; //Mode for Missing tooth secondary trigger. Either single tooth cam wheel or 4-1 byte unused4_9; byte unused4_10; byte StgCycles; //The number of initial cycles before the ignition should fire when first cranking @@ -727,5 +727,7 @@ extern byte cltCalibrationTable[CALIBRATION_TABLE_SIZE]; extern byte iatCalibrationTable[CALIBRATION_TABLE_SIZE]; extern byte o2CalibrationTable[CALIBRATION_TABLE_SIZE]; +// alias(es) for ease of code reading!! +bool& trigPatternSec = configPage2.trigPatternSec; #endif // GLOBALS_H