diff --git a/reference/speeduino.ini b/reference/speeduino.ini index e60d56f1..7f74b951 100644 --- a/reference/speeduino.ini +++ b/reference/speeduino.ini @@ -517,7 +517,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", "Rover 5-3-2 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" + trigPatternSec = bits,U08, 8,[0:6], "Single tooth cam", "4-1 cam", "Poll level", "Rover 5-3-2 cam", "Toyota 3 Tooth", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "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.cpp b/speeduino/decoders.cpp index 2413ca95..908f2f24 100644 --- a/speeduino/decoders.cpp +++ b/speeduino/decoders.cpp @@ -1,3 +1,5 @@ +#define MJR 1 + /* Speeduino - Simple engine management for the Arduino Mega 2560 platform Copyright (C) Josh Stewart @@ -53,6 +55,7 @@ int (*getCrankAngle)(void) = nullGetCrankAngle; ///Pointer to the getCrank Angle void (*triggerSetEndTeeth)(void) = triggerSetEndTeeth_missingTooth; ///Pointer to the triggerSetEndTeeth function of each decoder static void triggerRoverMEMSCommon(void); +static inline void triggerRecordVVT1Angle (void); volatile unsigned long curTime; volatile unsigned long curGap; @@ -552,12 +555,15 @@ void triggerPri_missingTooth(void) if( (secondaryToothCount > 0) || (configPage4.TrigSpeed == CAM_SPEED) || (configPage4.trigPatternSec == SEC_TRIGGER_POLL) || (configPage2.strokes == TWO_STROKE) ) { currentStatus.hasSync = true; - BIT_CLEAR(currentStatus.status3, BIT_STATUS3_HALFSYNC); //the engine is fully synced so clear the Half Sync bit - if(configPage4.trigPatternSec == SEC_TRIGGER_SINGLE) { secondaryToothCount = 0; } //Reset the secondary tooth counter to prevent it overflowing + BIT_CLEAR(currentStatus.status3, BIT_STATUS3_HALFSYNC); //the engine is fully synced so clear the Half Sync bit } else if(currentStatus.hasSync != true) { BIT_SET(currentStatus.status3, BIT_STATUS3_HALFSYNC); } //If there is primary trigger but no secondary we only have half sync. } else { currentStatus.hasSync = true; BIT_CLEAR(currentStatus.status3, BIT_STATUS3_HALFSYNC); } //If nothing is using sequential, we have sync and also clear half sync bit + if(configPage4.trigPatternSec == SEC_TRIGGER_SINGLE || configPage4.trigPatternSec == SEC_TRIGGER_TOYOTA_3) //Reset the secondary tooth counter to prevent it overflowing, done outside of sequental as v6 & v8 engines could be batch firing with VVT that needs the cam resetting + { + secondaryToothCount = 0; + } triggerFilterTime = 0; //This is used to prevent a condition where serious intermittent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state toothLastMinusOneToothTime = toothLastToothTime; @@ -613,32 +619,52 @@ void triggerSec_missingTooth(void) if ( curGap2 >= triggerSecFilterTime ) { - if ( configPage4.trigPatternSec == SEC_TRIGGER_4_1 ) + switch (configPage4.trigPatternSec) { - 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; + case SEC_TRIGGER_4_1: + 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 + triggerRecordVVT1Angle (); + } + 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++; + } + break; + + case SEC_TRIGGER_SINGLE: + //Standard single tooth cam trigger revolutionOne = 1; //Sequential revolution reset - triggerSecFilterTime = 0; //This is used to prevent a condition where serious intermittent 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 recalculated for the regular teeth, not the missing one. + triggerSecFilterTime = curGap2 >> 1; //Next secondary filter is half the current gap secondaryToothCount++; - } - } - else if ( configPage4.trigPatternSec == SEC_TRIGGER_SINGLE ) - { - //Standard single tooth cam trigger - revolutionOne = 1; //Sequential revolution reset - triggerSecFilterTime = curGap2 >> 1; //Next secondary filter is half the current gap - secondaryToothCount++; + triggerRecordVVT1Angle (); + break; + + case SEC_TRIGGER_TOYOTA_3: + // designed for Toyota VVTI (2JZ) engine - 3 triggers on the cam. + // the 2 teeth for this are within 1 rotation (1 tooth first 360, 2 teeth second 360) + secondaryToothCount++; + if(secondaryToothCount == 2) + { + revolutionOne = 1; // sequential revolution reset + triggerRecordVVT1Angle (); + } + //Next secondary filter is 25% the current gap, done here so we don't get a great big gap for the 1st tooth + triggerSecFilterTime = curGap2 >> 2; + break; } toothLastSecToothTime = curTime2; } //Trigger filter +} +static inline void triggerRecordVVT1Angle (void) +{ //Record the VVT Angle if( (configPage6.vvtEnabled > 0) && (revolutionOne == 1) ) { @@ -650,13 +676,14 @@ void triggerSec_missingTooth(void) currentStatus.vvt1Angle = ANGLE_FILTER( (curAngle << 1), configPage4.ANGLEFILTER_VVT, currentStatus.vvt1Angle); } - - } + void triggerThird_missingTooth(void) { - //Record the VVT2 Angle (the only purpose of the third trigger) +//Record the VVT2 Angle (the only purpose of the third trigger) +//NB no filtering of this signal with current implementation unlike Cam (VVT1) + int16_t curAngle; curTime3 = micros(); curGap3 = curTime3 - toothLastThirdToothTime; @@ -671,16 +698,17 @@ void triggerThird_missingTooth(void) if ( curGap3 >= triggerThirdFilterTime ) { thirdToothCount++; - triggerThirdFilterTime = curGap3 >> 1; //Next third filter is 50% the current gap + triggerThirdFilterTime = curGap3 >> 2; //Next third filter is 25% the current gap curAngle = getCrankAngle(); while(curAngle > 360) { curAngle -= 360; } curAngle -= configPage4.triggerAngle; //Value at TDC if( configPage6.vvtMode == VVT_MODE_CLOSED_LOOP ) { curAngle -= configPage4.vvt2CL0DutyAng; } //currentStatus.vvt2Angle = int8_t (curAngle); //vvt1Angle is only int8, but +/-127 degrees is enough for VVT control - currentStatus.vvt2Angle = ANGLE_FILTER( (curAngle << 1), configPage4.ANGLEFILTER_VVT, currentStatus.vvt2Angle); + currentStatus.vvt2Angle = ANGLE_FILTER( (curAngle << 1), configPage4.ANGLEFILTER_VVT, currentStatus.vvt2Angle); + toothLastThirdToothTime = curTime3; - } // Trigger filter + } //Trigger filter } uint16_t getRPM_missingTooth(void) diff --git a/speeduino/decoders.h b/speeduino/decoders.h index 16265ec4..26c6bed5 100644 --- a/speeduino/decoders.h +++ b/speeduino/decoders.h @@ -76,6 +76,7 @@ uint16_t getRPM_missingTooth(void); int getCrankAngle_missingTooth(void); extern void triggerSetEndTeeth_missingTooth(void); + void triggerSetup_DualWheel(void); void triggerPri_DualWheel(void); void triggerSec_DualWheel(void); diff --git a/speeduino/globals.h b/speeduino/globals.h index cdd6ae89..cf043243 100644 --- a/speeduino/globals.h +++ b/speeduino/globals.h @@ -255,6 +255,7 @@ #define SEC_TRIGGER_4_1 1 #define SEC_TRIGGER_POLL 2 #define SEC_TRIGGER_5_3_2 3 +#define SEC_TRIGGER_TOYOTA_3 4 #define ROTARY_IGN_FC 0 #define ROTARY_IGN_FD 1 @@ -1469,8 +1470,8 @@ extern byte pinCoil7; //Pin for coil 7 extern byte pinCoil8; //Pin for coil 8 extern byte ignitionOutputControl; //Specifies whether the coils are controlled directly (Via an IO pin) or using something like the MC33810 extern byte pinTrigger; //The CAS pin -extern byte pinTrigger2; //The Cam Sensor pin -extern byte pinTrigger3; //the 2nd cam sensor pin +extern byte pinTrigger2; //The Cam Sensor pin known as secondary input +extern byte pinTrigger3; //the 2nd cam sensor pin known as tertiary input extern byte pinTPS;//TPS input pin extern byte pinMAP; //MAP sensor pin extern byte pinEMAP; //EMAP sensor pin