diff --git a/decoders.h b/decoders.h index 797077a8..10798924 100644 --- a/decoders.h +++ b/decoders.h @@ -49,6 +49,7 @@ int triggerToothAngle; //The number of crank degrees that elapse per tooth unsigned long revolutionTime; //The time in uS that one revolution would take at current speed (The time tooth 1 was last seen, minus the time it was seen prior to that) bool secondDerivEnabled; //The use of the 2nd derivative calculation is limited to certain decoders. This is set to either true or false in each decoders setup routine bool decoderIsSequential; //Whether or not the decoder supports sequential operation +byte checkSyncToothCount; //How many teeth must've been seen on this revolution before we try to confirm sync (Useful for missing tooth type decoders) int toothAngles[24]; //An array for storing fixed tooth angles. Currently sized at 24 for the GM 24X decoder, but may grow later if there are other decoders that use this style diff --git a/decoders.ino b/decoders.ino index 47b4600c..a7155dee 100644 --- a/decoders.ino +++ b/decoders.ino @@ -91,6 +91,7 @@ void triggerSetup_missingTooth() 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 secondDerivEnabled = false; decoderIsSequential = false; + checkSyncToothCount = (configPage2.triggerTeeth * 3) >> 1; //50% of the total teeth. MAX_STALL_TIME = (3333UL * triggerToothAngle * (configPage2.triggerMissingTeeth + 1)); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) } @@ -105,27 +106,30 @@ void triggerPri_missingTooth() toothCurrentCount++; //Increment the tooth counter addToothLogEntry(curGap); - - //Begin the missing tooth detection - //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 - if(configPage2.triggerMissingTeeth == 1) { targetGap = (3 * (toothLastToothTime - toothLastMinusOneToothTime)) >> 1; } //Multiply by 1.5 (Checks for a gap 1.5x greater than the last one) (Uses bitshift to multiply by 3 then divide by 2. Much faster than multiplying by 1.5) - else { targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2; } //Multiply by 2 (Checks for a gap 2x greater than the last one) - - if ( curGap > targetGap || toothCurrentCount > triggerActualTeeth) - { - if(toothCurrentCount < (triggerActualTeeth) && currentStatus.hasSync) { currentStatus.hasSync = false; return; } //This occurs when we're at tooth #1, but haven't seen all the other teeth. This indicates a signal issue so we flag lost sync so this will attempt to resync on the next revolution. - toothCurrentCount = 1; - revolutionOne = !revolutionOne; //Flip sequential revolution tracker - toothOneMinusOneTime = toothOneTime; - toothOneTime = curTime; - currentStatus.hasSync = true; - startRevolutions++; //Counter - triggerFilterTime = 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 + + if(toothCurrentCount > checkSyncToothCount || !currentStatus.hasSync) { - //Filter can only be recalc'd for the regular teeth, not the missing one. - setFilter(curGap); + //Begin the missing tooth detection + //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 + if(configPage2.triggerMissingTeeth == 1) { targetGap = (3 * (toothLastToothTime - toothLastMinusOneToothTime)) >> 1; } //Multiply by 1.5 (Checks for a gap 1.5x greater than the last one) (Uses bitshift to multiply by 3 then divide by 2. Much faster than multiplying by 1.5) + else { targetGap = ((toothLastToothTime - toothLastMinusOneToothTime)) * 2; } //Multiply by 2 (Checks for a gap 2x greater than the last one) + + if ( curGap > targetGap || toothCurrentCount > triggerActualTeeth) + { + if(toothCurrentCount < (triggerActualTeeth) && currentStatus.hasSync) { currentStatus.hasSync = false; return; } //This occurs when we're at tooth #1, but haven't seen all the other teeth. This indicates a signal issue so we flag lost sync so this will attempt to resync on the next revolution. + toothCurrentCount = 1; + revolutionOne = !revolutionOne; //Flip sequential revolution tracker + toothOneMinusOneTime = toothOneTime; + toothOneTime = curTime; + currentStatus.hasSync = true; + startRevolutions++; //Counter + triggerFilterTime = 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 + { + //Filter can only be recalc'd for the regular teeth, not the missing one. + setFilter(curGap); + } } toothLastMinusOneToothTime = toothLastToothTime; diff --git a/speeduino.ino b/speeduino.ino index 1500467b..e88641e6 100644 --- a/speeduino.ino +++ b/speeduino.ino @@ -1238,7 +1238,7 @@ void loop() /*----------------------------------------------------------------------------------------- | A Note on tempCrankAngle and tempStartAngle: | The use of tempCrankAngle/tempStartAngle is described below. It is then used in the same way for channels 2, 3 and 4 on both injectors and ignition - | Essentially, these 2 variables are used to realign the current crank and and the desired start angle around 0 degrees for the given cylinder/output + | Essentially, these 2 variables are used to realign the current crank angle and the desired start angle around 0 degrees for the given cylinder/output | Eg: If cylinder 2 TDC is 180 degrees after cylinder 1 (Eg a standard 4 cylidner engine), then tempCrankAngle is 180* less than the current crank angle and | tempStartAngle is the desired open time less 180*. Thus the cylinder is being treated relative to its own TDC, regardless of its offset | diff --git a/table.ino b/table.ino index f277032a..383b6755 100644 --- a/table.ino +++ b/table.ino @@ -315,6 +315,7 @@ int get3DTableValue(struct table3D *fromTable, int Y, int X) else //If it's not caught by one of the above scenarios, give up and just run the loop { + for (byte y = fromTable->ySize-1; y >= 0; y--) { //Checks the case where the Y value is exactly what was requested @@ -355,6 +356,9 @@ int get3DTableValue(struct table3D *fromTable, int Y, int X) int B = fromTable->values[yMin][xMax]; int C = fromTable->values[yMax][xMin]; int D = fromTable->values[yMax][xMax]; + + //Check that all values aren't just the same (This regularly happens with things like the fuel trim maps) + if(A == B && A == C && A == D) { return A; } //Create some normalised position values //These are essentially percentages (between 0 and 1) of where the desired value falls between the nearest bins on each axis