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:
parent
f67817b4ad
commit
809bd3a54c
|
@ -130,6 +130,8 @@
|
|||
#define trigger_ThirtySixMinus222 = 16
|
||||
#define trigger_ThirtySixMinus21 = 17
|
||||
#define trigger_420a = 18
|
||||
#define trigger_Webber = 19
|
||||
#define trigger_FordST170 = 20
|
||||
|
||||
[Constants]
|
||||
|
||||
|
@ -433,7 +435,7 @@ page = 4
|
|||
TrigEdge = bits, U08, 5,[0:0], "RISING", "FALLING"
|
||||
TrigSpeed = bits, U08, 5,[1:1], "Crank Speed", "Cam Speed"
|
||||
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"
|
||||
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"
|
||||
|
@ -2495,7 +2497,7 @@ menuDialog = main
|
|||
field = "Note: This is the number of revolutions that will be skipped during"
|
||||
field = "cranking before the injectors and coils are fired"
|
||||
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 = "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
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define DECODER_36_2_1 17
|
||||
#define DECODER_420A 18
|
||||
#define DECODER_WEBER 19
|
||||
#define DECODER_ST170 20
|
||||
|
||||
static inline void addToothLogEntry(unsigned long, bool);
|
||||
void loggerPrimaryISR();
|
||||
|
@ -178,6 +179,13 @@ void triggerSetEndTeeth_420a();
|
|||
void triggerPri_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 (*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)
|
||||
|
|
|
@ -3864,3 +3864,164 @@ void triggerSec_Webber()
|
|||
checkSyncToothCount = 1; //Reset tooth counter
|
||||
} //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;
|
||||
}
|
||||
|
|
|
@ -3029,6 +3029,25 @@ void initialiseTriggers()
|
|||
attachInterrupt(triggerInterrupt2, triggerSecondaryHandler, secondaryTriggerEdge);
|
||||
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:
|
||||
triggerHandler = triggerPri_missingTooth;
|
||||
|
|
Loading…
Reference in New Issue