Add Ford ST170 Decoder (#530)

This adds a decoder for the Ford ST170 engine.
This setup uses a 36-1 primary and a unique 8-3 secondary trigger.
The existing missing tooth deooder with fixed parameters is used as the primary to reduce duplication.
This commit is contained in:
DIY-EFI 2021-02-13 22:15:53 +00:00 committed by GitHub
parent f67817b4ad
commit 809bd3a54c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 192 additions and 2 deletions

View File

@ -130,6 +130,8 @@
#define trigger_ThirtySixMinus222 = 16 #define trigger_ThirtySixMinus222 = 16
#define trigger_ThirtySixMinus21 = 17 #define trigger_ThirtySixMinus21 = 17
#define trigger_420a = 18 #define trigger_420a = 18
#define trigger_Webber = 19
#define trigger_FordST170 = 20
[Constants] [Constants]
@ -433,7 +435,7 @@ page = 4
TrigEdge = bits, U08, 5,[0:0], "RISING", "FALLING" TrigEdge = bits, U08, 5,[0:0], "RISING", "FALLING"
TrigSpeed = bits, U08, 5,[1:1], "Crank Speed", "Cam Speed" TrigSpeed = bits, U08, 5,[1:1], "Crank Speed", "Cam Speed"
IgInv = bits, U08, 5,[2:2], "Going Low", "Going High" IgInv = bits, U08, 5,[2:2], "Going Low", "Going High"
TrigPattern= bits, U08, 5,[3:7], "Missing Tooth", "Basic Distributor", "Dual Wheel", "GM 7X", "4G63 / Miata / 3000GT", "GM 24X", "Jeep 2000", "Audi 135", "Honda D17", "Miata 99-05", "Mazda AU", "Non-360 Dual", "Nissan 360", "Subaru 6/7", "Daihatsu +1", "Harley EVO", "36-2-2-2", "36-2-1", "DSM 420a", "Weber-Marelli", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID" TrigPattern= bits, U08, 5,[3:7], "Missing Tooth", "Basic Distributor", "Dual Wheel", "GM 7X", "4G63 / Miata / 3000GT", "GM 24X", "Jeep 2000", "Audi 135", "Honda D17", "Miata 99-05", "Mazda AU", "Non-360 Dual", "Nissan 360", "Subaru 6/7", "Daihatsu +1", "Harley EVO", "36-2-2-2", "36-2-1", "DSM 420a", "Weber-Marelli", "Ford ST170", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID"
TrigEdgeSec= bits, U08, 6,[0:0], "RISING", "FALLING" TrigEdgeSec= bits, U08, 6,[0:0], "RISING", "FALLING"
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" 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" useResync = bits, U08, 6,[7:7], "No", "Yes"
@ -2495,7 +2497,7 @@ menuDialog = main
field = "Note: This is the number of revolutions that will be skipped during" field = "Note: This is the number of revolutions that will be skipped during"
field = "cranking before the injectors and coils are fired" field = "cranking before the injectors and coils are fired"
field = "Trigger edge", TrigEdge { TrigPattern != 4 } ;4G63 uses both edges field = "Trigger edge", TrigEdge { TrigPattern != 4 } ;4G63 uses both edges
field = "Secondary trigger edge", TrigEdgeSec, { (TrigPattern == 0 && TrigSpeed == 0) || TrigPattern == 2 || TrigPattern == 9 || TrigPattern == 12 || TrigPattern == 18 || TrigPattern == 19 } ;Missing tooth, dual wheel and Miata 9905, weber-marelli field = "Secondary trigger edge", TrigEdgeSec, { (TrigPattern == 0 && TrigSpeed == 0) || TrigPattern == 2 || TrigPattern == 9 || TrigPattern == 12 || TrigPattern == 18 || TrigPattern == 19 || TrigPattern == 20 } ;Missing tooth, dual wheel and Miata 9905, weber-marelli, ST170
field = "Missing Tooth Secondary type" trigPatternSec, { (TrigPattern == 0&& TrigSpeed == 0) } field = "Missing Tooth Secondary type" trigPatternSec, { (TrigPattern == 0&& TrigSpeed == 0) }
field = "Trigger Filter", TrigFilter, { TrigPattern != 13 } 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 } ;Dual wheel, 4G63, Audi 135, Nissan 360, Miata 99-05, weber-marelli field = "Re-sync every cycle", useResync, { TrigPattern == 2 || TrigPattern == 4 || TrigPattern == 7 || TrigPattern == 12 || TrigPattern == 9 || TrigPattern == 13 || TrigPattern == 18 || TrigPattern == 19 } ;Dual wheel, 4G63, Audi 135, Nissan 360, Miata 99-05, weber-marelli

View File

@ -31,6 +31,7 @@
#define DECODER_36_2_1 17 #define DECODER_36_2_1 17
#define DECODER_420A 18 #define DECODER_420A 18
#define DECODER_WEBER 19 #define DECODER_WEBER 19
#define DECODER_ST170 20
static inline void addToothLogEntry(unsigned long, bool); static inline void addToothLogEntry(unsigned long, bool);
void loggerPrimaryISR(); void loggerPrimaryISR();
@ -178,6 +179,13 @@ void triggerSetEndTeeth_420a();
void triggerPri_Webber(); void triggerPri_Webber();
void triggerSec_Webber(); void triggerSec_Webber();
void triggerSetup_FordST170();
void triggerSec_FordST170();
uint16_t getRPM_FordST170();
int getCrankAngle_FordST170();
void triggerSetEndTeeth_FordST170();
extern void (*triggerHandler)(); //Pointer for the trigger function (Gets pointed to the relevant decoder) extern void (*triggerHandler)(); //Pointer for the trigger function (Gets pointed to the relevant decoder)
extern void (*triggerSecondaryHandler)(); //Pointer for the secondary trigger function (Gets pointed to the relevant decoder) extern void (*triggerSecondaryHandler)(); //Pointer for the secondary trigger function (Gets pointed to the relevant decoder)
extern uint16_t (*getRPM)(); //Pointer to the getRPM function (Gets pointed to the relevant decoder) extern uint16_t (*getRPM)(); //Pointer to the getRPM function (Gets pointed to the relevant decoder)

View File

@ -3864,3 +3864,164 @@ void triggerSec_Webber()
checkSyncToothCount = 1; //Reset tooth counter checkSyncToothCount = 1; //Reset tooth counter
} //Trigger filter } //Trigger filter
} }
/*
Name: Ford ST170
Desc: A dedicated decoder for 01-04 Ford Focus ST170/SVT engine.
Note: Standard 36-1 trigger wheel running at crank speed and 8-3 trigger wheel running at cam speed
*/
void triggerSetup_FordST170()
{
//Set these as we are using the existing missing tooth primary decoder and these will never change.
configPage4.triggerTeeth = 36;
configPage4.triggerMissingTeeth = 1;
configPage4.TrigSpeed = CRANK_SPEED;
triggerToothAngle = 360 / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth
triggerActualTeeth = configPage4.triggerTeeth - configPage4.triggerMissingTeeth; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt
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 * 60 / MAX_RPM / 8 / 2; //Cam pattern is 8-3, so 2 nearest teeth are 90 deg crank angle apart. Cam can be advanced by 60 deg, so going from fully retarded to fully advanced closes the gap to 30 deg. Zetec cam pulleys aren't keyed from factory, so I substracted additional 10 deg to avoid filter to be too agressive. And there you have it 720/20=36.
secondDerivEnabled = false;
decoderIsSequential = true;
checkSyncToothCount = (36) >> 1; //50% of the total teeth.
toothLastMinusOneToothTime = 0;
toothCurrentCount = 0;
secondaryToothCount = 0;
toothOneTime = 0;
toothOneMinusOneTime = 0;
MAX_STALL_TIME = (3333UL * triggerToothAngle * (1 + 1)); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
}
void triggerSec_FordST170()
{
curTime2 = micros();
curGap2 = curTime2 - toothLastSecToothTime;
//Safety check for initial startup
if( (toothLastSecToothTime == 0) )
{
curGap2 = 0;
toothLastSecToothTime = curTime2;
}
if ( curGap2 >= triggerSecFilterTime )
{
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 == 5) )
{
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++;
}
toothLastSecToothTime = curTime2;
//Record the VVT Angle
//We use the first tooth after the long gap as our reference, this remains in the same engine
//cycle even when the VVT is at either end of its full swing.
if( (configPage6.vvtEnabled > 0) && (revolutionOne == 1) && (secondaryToothCount == 1) )
{
int16_t curAngle;
curAngle = getCrankAngle();
while(curAngle > 360) { curAngle -= 360; }
if( configPage6.vvtMode == VVT_MODE_CLOSED_LOOP )
{
currentStatus.vvt1Angle = 360 - curAngle - configPage10.vvtCLMinAng;
}
}
} //Trigger filter
}
uint16_t getRPM_FordST170()
{
uint16_t tempRPM = 0;
if( currentStatus.RPM < currentStatus.crankRPM )
{
if(toothCurrentCount != 1)
{
tempRPM = crankingGetRPM(36);
}
else { tempRPM = currentStatus.RPM; } //Can't do per tooth RPM if we're at tooth #1 as the missing tooth messes the calculation
}
else
{
tempRPM = stdGetRPM(360);
}
return tempRPM;
}
int getCrankAngle_FordST170()
{
//This is the current angle ATDC the engine is at. This is the last known position based on what tooth was last 'seen'. It is only accurate to the resolution of the trigger wheel (Eg 36-1 is 10 degrees)
unsigned long tempToothLastToothTime;
int tempToothCurrentCount;
bool tempRevolutionOne;
//Grab some variables that are used in the trigger code and assign them to temp variables.
noInterrupts();
tempToothCurrentCount = toothCurrentCount;
tempRevolutionOne = revolutionOne;
tempToothLastToothTime = toothLastToothTime;
interrupts();
int crankAngle = ((tempToothCurrentCount - 1) * triggerToothAngle) + configPage4.triggerAngle; //Number of teeth that have passed since tooth 1, multiplied by the angle each tooth represents, plus the angle that tooth 1 is ATDC. This gives accuracy only to the nearest tooth.
//Sequential check (simply sets whether we're on the first or 2nd revoltuion of the cycle)
if ( (tempRevolutionOne == true) && (configPage4.TrigSpeed == CRANK_SPEED) ) { crankAngle += 360; }
lastCrankAngleCalc = micros();
elapsedTime = (lastCrankAngleCalc - tempToothLastToothTime);
crankAngle += timeToAngle(elapsedTime, CRANKMATH_METHOD_INTERVAL_REV);
if (crankAngle >= 720) { crankAngle -= 720; }
else if (crankAngle > CRANK_ANGLE_MAX) { crankAngle -= CRANK_ANGLE_MAX; }
if (crankAngle < 0) { crankAngle += CRANK_ANGLE_MAX; }
return crankAngle;
}
void triggerSetEndTeeth_FordST170()
{
byte toothAdder = 0;
if( (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) && (configPage4.TrigSpeed == CRANK_SPEED) ) { toothAdder = 36; }
//Temp variables are used here to avoid potential issues if a trigger interrupt occurs part way through this function
int16_t tempIgnition1EndTooth;
tempIgnition1EndTooth = ( (ignition1EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ) - 1;
if(tempIgnition1EndTooth > (36 + toothAdder)) { tempIgnition1EndTooth -= (36 + toothAdder); }
if(tempIgnition1EndTooth <= 0) { tempIgnition1EndTooth += (36 + toothAdder); }
if((uint16_t)tempIgnition1EndTooth > (triggerActualTeeth + toothAdder)) { tempIgnition1EndTooth = (triggerActualTeeth + toothAdder); }
ignition1EndTooth = tempIgnition1EndTooth;
int16_t tempIgnition2EndTooth;
tempIgnition2EndTooth = ( (ignition2EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ) - 1;
if(tempIgnition2EndTooth > (36 + toothAdder)) { tempIgnition2EndTooth -= (36 + toothAdder); }
if(tempIgnition2EndTooth <= 0) { tempIgnition2EndTooth += (36 + toothAdder); }
if((uint16_t)tempIgnition2EndTooth > (triggerActualTeeth + toothAdder)) { tempIgnition2EndTooth = (triggerActualTeeth + toothAdder); }
ignition2EndTooth = tempIgnition2EndTooth;
int16_t tempIgnition3EndTooth;
tempIgnition3EndTooth = ( (ignition3EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ) - 1;
if(tempIgnition3EndTooth > (36 + toothAdder)) { tempIgnition3EndTooth -= (36 + toothAdder); }
if(tempIgnition3EndTooth <= 0) { tempIgnition3EndTooth += (36 + toothAdder); }
if((uint16_t)tempIgnition3EndTooth > (triggerActualTeeth + toothAdder)) { tempIgnition3EndTooth = (triggerActualTeeth + toothAdder); }
ignition3EndTooth = tempIgnition3EndTooth;
int16_t tempIgnition4EndTooth;
tempIgnition4EndTooth = ( (ignition4EndAngle - configPage4.triggerAngle) / (int16_t)(triggerToothAngle) ) - 1;
if(tempIgnition4EndTooth > (36 + toothAdder)) { tempIgnition4EndTooth -= (36 + toothAdder); }
if(tempIgnition4EndTooth <= 0) { tempIgnition4EndTooth += (36 + toothAdder); }
if((uint16_t)tempIgnition4EndTooth > (triggerActualTeeth + toothAdder)) { tempIgnition4EndTooth = (triggerActualTeeth + toothAdder); }
ignition4EndTooth = tempIgnition4EndTooth;
// Removed ign channels >4 as an ST170 engine is a 4 cylinder
lastToothCalcAdvance = currentStatus.advance;
}

View File

@ -3029,6 +3029,25 @@ void initialiseTriggers()
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge); attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break; break;
case DECODER_ST170:
//Ford ST170
triggerSetup_FordST170();
triggerHandler = triggerPri_missingTooth;
triggerSecondaryHandler = triggerSec_FordST170;
decoderHasSecondary = true;
getRPM = getRPM_FordST170;
getCrankAngle = getCrankAngle_FordST170;
triggerSetEndTeeth = triggerSetEndTeeth_FordST170;
if(configPage4.TrigEdge == 0) { primaryTriggerEdge = RISING; } // Attach the crank trigger wheel interrupt (Hall sensor drags to ground when triggering)
else { primaryTriggerEdge = FALLING; }
if(configPage4.TrigEdgeSec == 0) { secondaryTriggerEdge = RISING; }
else { secondaryTriggerEdge = FALLING; }
attachInterrupt(triggerInterrupt, triggerHandler, primaryTriggerEdge);
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
break;
default: default:
triggerHandler = triggerPri_missingTooth; triggerHandler = triggerPri_missingTooth;