Potential fix for erratic spark behaviour

This commit is contained in:
Josh Stewart 2015-11-25 15:38:22 +11:00
parent 2d4ce39605
commit c779f42d9e
3 changed files with 32 additions and 22 deletions

View File

@ -121,7 +121,9 @@ int getCrankAngle_missingTooth(int timePerDegree)
int crankAngle = (tempToothCurrentCount - 1) * triggerToothAngle + configPage2.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.
crankAngle += ( (micros() - tempToothLastToothTime) / timePerDegree); //Estimate the number of degrees travelled since the last tooth
if (crankAngle > 360) { crankAngle -= 360; }
if (crankAngle >= 720) { crankAngle -= 720; }
else if (crankAngle > 360) { crankAngle -= 360; }
if (crankAngle < 0) { crankAngle += 360; }
return crankAngle;
}

View File

@ -122,13 +122,9 @@ void setIgnitionSchedule1(void (*startCallback)(), unsigned long timeout, unsign
if(ignitionSchedule1.Status == RUNNING) { return; } //Check that we're not already part way through a schedule
//We need to calculate the value to reset the timer to (preload) in order to achieve the desired overflow time
//As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
//unsigned int absoluteTimeout = TCNT5 + (timeout / 16); //Each tick occurs every 16uS with the 256 prescaler, so divide the timeout by 16 to get ther required number of ticks. Add this to the current tick count to get the target time. This will automatically overflow as required
//unsigned char sreg;
//sreg = SREG;
//noInterrupts();
//unsigned int absoluteTimeout = TCNT5 + (timeout >> 4); //As above, but with bit shift instead of / 16
OCR5A = TCNT5 + (timeout >> 2); //Divid timeout by 4 (Each tick represent 4uS)
//As the timer is ticking every 4uS (Time per Tick = (Prescale)*(1/Frequency))
if (timeout > 262140) { return; } // If the timeout is >4x (Each tick represents 4uS) the maximum allowed value of unsigned int (65525), the timer compare value will overflow when appliedcausing erratic behaviour such as erroneous sparking.
OCR5A = TCNT5 + (timeout >> 2); //Divide timeout by 4 (Each tick represent 4uS)
//SREG = sreg;
ignitionSchedule1.duration = duration;
@ -262,11 +258,10 @@ ISR(TIMER5_COMPA_vect, ISR_NOBLOCK) //ignitionSchedule1
{
if (ignitionSchedule1.Status == PENDING) //Check to see if this schedule is turn on
{
if ( ign1LastRev == startRevolutions ) { return; }
//if ( ign1LastRev == startRevolutions ) { return; }
ignitionSchedule1.Status = RUNNING; //Set the status to be in progress (ie The start callback has been called, but not the end callback)
ignitionSchedule1.startTime = currentLoopTime;
ignitionSchedule1.startTime = micros();
ignitionSchedule1.StartCallback();
//unsigned int absoluteTimeout = TCNT5 + (ignitionSchedule1.duration >> 4);
ign1LastRev = startRevolutions;
unsigned int absoluteTimeout = TCNT5 + (ignitionSchedule1.duration >> 2); //Divide by 4
OCR5A = absoluteTimeout;

View File

@ -727,16 +727,17 @@ void loop()
int tempCrankAngle;
int tempStartAngle;
//********************************************************
//How fast are we going? Need to know how long (uS) it will take to get from one tooth to the next. We then use that to estimate how far we are between the last tooth and the next one
//We use a 1st Deriv accleration prediction, but only when there is an even spacing between primary sensor teeth
//Any decoder that has uneven spacing has its triggerToothAngle set to 0
if(triggerToothAngle > 0 && toothHistoryIndex >= 3 && currentStatus.RPM < 3000 ) //toothHistoryIndex must be greater than or equal to 3 as we need the last 3 entries. Currently this mode only runs below 3000 rpm
if(triggerToothAngle > 0 && toothHistoryIndex >= 3 && currentStatus.RPM < 1 ) //toothHistoryIndex must be greater than or equal to 3 as we need the last 3 entries. Currently this mode only runs below 3000 rpm
{
//Only recalculate deltaV if the tooth has changed since last time
//Only recalculate deltaV if the tooth has changed since last time (DeltaV stays the same until the next tooth)
if (deltaToothCount != toothCurrentCount)
{
deltaToothCount = toothCurrentCount;
int angle1, angle2; //These represent that crank angles that are travelled for the last 2 pulses
int angle1, angle2; //These represent the crank angles that are travelled for the last 2 pulses
if(configPage2.TrigPattern == 4)
{
//Special case for 70/110 pattern on 4g63
@ -744,14 +745,22 @@ void loop()
if (angle2 == 70) { angle1 = 110; }
else { angle1 = 70; }
}
else if(configPage2.TrigPattern == 0)
{
//Special case for missing tooth decoder where the missing tooth was one of the last 2 seen
if(toothCurrentCount == 1) { angle2 = 2*triggerToothAngle; angle1 = triggerToothAngle; }
else if(toothCurrentCount == 2) { angle1 = 2*triggerToothAngle; angle2 = triggerToothAngle; }
else { angle1 = angle2 = triggerToothAngle; }
}
else { angle1 = angle2 = triggerToothAngle; }
long toothDeltaV = (1000000L * angle2 / toothHistory[toothHistoryIndex]) - (1000000L * angle1 / toothHistory[toothHistoryIndex-1]);
long toothDeltaT = toothHistory[toothHistoryIndex];
long timeToLastTooth = micros() - toothLastToothTime; //Cannot be unsigned
rpmDelta = (toothDeltaV * timeToLastTooth) / (6 * toothDeltaT);
}
rpmDelta = (toothDeltaV << 10) / (6 * toothDeltaT);
}
timePerDegree = ldiv( 166666L, (currentStatus.RPM + rpmDelta)).quot; //There is a small amount of rounding in this calculation, however it is less than 0.001 of a uS (Faster as ldiv than / )
}
@ -977,18 +986,22 @@ void loop()
crankAngle = getCrankAngle(timePerDegree); //Refresh with the latest crank angle
if(ignitionOn && (currentStatus.RPM < ((unsigned int)(configPage2.HardRevLim) * 100) ))
{
if ( (ignition1StartAngle > crankAngle) && ign1LastRev != startRevolutions)
//if (ign1LastRev != startRevolutions)
//if ( (ignition1StartAngle > crankAngle))// && ign1LastRev != startRevolutions)
//if ((ignition1StartAngle > crankAngle) == 0)
//if ((ignition1StartAngle < crankAngle))
{
unsigned long ignition1StartTime;
long ignition1StartTime;
if(ignition1StartAngle > crankAngle) { ignition1StartTime = ((unsigned long)(ignition1StartAngle - crankAngle) * (unsigned long)timePerDegree); }
else { ignition1StartTime = ((unsigned long)(360 - crankAngle + ignition1StartAngle) * (unsigned long)timePerDegree); }
else if (ignition1StartAngle < crankAngle) { ignition1StartTime = ((long)(360 - crankAngle + ignition1StartAngle) * (long)timePerDegree); }
else { ignition1StartTime = 0; }
if(ignition1StartTime > 0) {
setIgnitionSchedule1(ign1StartFunction,
((unsigned long)(ignition1StartAngle - crankAngle) * (unsigned long)timePerDegree),
ignition1StartTime,
currentStatus.dwell,
ign1EndFunction
);
}
}
tempCrankAngle = crankAngle - channel2IgnDegrees;