Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,etc)

For discussing and developing different RPM/Position decoders using our superior modular architecture! One thread per pattern, please.
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,etc)

Post by Fred »

It's about time work got started on this. We've had a fixed implementation in the code by Phil for a long time, but i couldn't make a lot of sense of it and he's not been around for forever. Marcos modified it to use on his Fiat, however I wanted something 100% robust and generic, so it's time for that code to say goodbye and for some new better code to come into the fold.

The issue is on the tracker here: http://issues.freeems.org/view.php?id=135

Missing teeth decoders are all about time differencing. The only logic is with respect to timing and ratios. You watch input pulses come in and record stamps and then periods and then compare periods (as soon as you have two).

Given M minus N terminology, there are three cases for gaining sync:

Common Case

Probability = ((M-N)-2)/M

First tooth is any tooth that isn't the one of the two before or the one after after the missing teeth. We must wait for up to (M-N)-3 teeth to come past before finding that our next one is large relative to our last two.

Rare case 1

Probability = (N + 1)/M

First tooth is the one after the missing teeth. (M-N)-1 evenly spaced pulses come past and we know the next one must be a long pulse because we are on the tooth before it.

Rare case 2

Probability = 1/M

First tooth is the one before the missing teeth. The first period is large and the two following periods are small.

Rare case 3

Probability = 1/M

First tooth is the one before the one before the missing teeth. The first period is small, the middle period is large and the last period is small.

More Certain Sync

Because it's a bit risky to take a scheduling gospel from just two periods (3 teeth), we double check this to ensure that any pair that matches one of our three sync opportunities is followed by the appropriate pair. We will check for the following before declaring sync:
  • If (M-N)-1 even periods were observed when we found a preliminary sync, then the next period MUST be the gap.
  • If we had a small period and then a large period, we will check to make sure that we get a small period on the next cycle.
  • If we had a large period and then a small period, we will check to make sure that the next one is small and comparable also.
Behaviour Of Different N Values

If the sensor wiring is reversed you get the situation where there are two wider teeth in a row.

Where N = 1 the wide period is approximately 2x the narrow ones before and after it. If reversed you get two, both approximately 1.5x the narrow ones before and after them.

Where N = 2 the wide period is approximately 3x the narrow ones before and after it. If reversed you get two, both approximately 2x the narrow ones before and after them.

For N = 3 it's 4x or a pair of 2.5x.

Thus it is always long period = (N+1) * normalPeriod
Reversed, the two long periods = ((N+2)/2) * normalPeriod

Thus I think that I can write this to output a specific error for the case when the wiring is backwards telling you to swap it.

Reading RPM

A rough RPM reading can be obtained as soon as we see two periods and decide if we are on a sync point, or waiting to find one. This can be used for preliminary scheduling to speed starting slightly. Accurate and stable RPM reading must wait until

(2*M)/cylinderCount periods have been measured (for a four stroke crank mounted application).

With just cylinder count we can set up the RPM to work smoothly on this type, so it might ignore configuration for RPM calcs and be smart always. We will see.

Noise Filtering

As part of our sync mechanism we're already filtering noise, however there is one more opportunity to catch out bad wiring and save the engine and that is tooth width. Tooth width varies with RPM due to sensor clearances etc, however at any given RPM it should be pretty stable and noise pulses are usually much narrower. We can difference these, one from the next, and lose sync if there are any out of the allowed range.

Different Applications

There are a number of use cases for the missing tooth style decoder. Some are outlined below:
  • Cam mounted, 720 degrees, 4 stroke
  • Crank mounted, 360 degrees, 4 stroke
  • Crank mounted, 360 degrees, 4 stroke, with short cam sync pulse
  • Crank mounted, 360 degrees, 4 stroke, with 50/50 cam sync
  • Crank mounted, 360 degrees, 2 stroke
Initial development will be limited to the following cases:
  • 12 minus 1 on the crank, four stroke
  • 36 minus 1 on the crank, four stroke
  • 60 minus 2 on the crank, four stroke
  • 24 minus 1 on the cam, four stroke
However any other combination is also possible. There is some info about possible second inputs here: http://issues.freeems.org/view.php?id=131

Right, to eclipse to knock this one out! :-)

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,e

Post by Fred »

For a couple of log images of a 60 minus 2 wheel wired correctly and backwards, check this out:

viewtopic.php?f=11&t=1341
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,e

Post by Fred »

MissingTeethValidCombos.ods

Check out the notes on the right before selecting a wheel for your appliction.

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,e

Post by Fred »

Time Settings And Sync Thresholds For Different N Values

If we recall that we have the following situation for inter-tooth gaps:
  • N=1: Narrow=1, Wide=2, Backwards=1.5, twice
  • N=2: Narrow=1, Wide=3, Backwards=2, twice
  • N=3: Narrow=1, Wide=4, Backwards=2.5, twice
  • N=N: Narrow=1, Wide=N+1, Backwards=(N+2)/2
Then, upon analysis, possibilities for a pair of periods are:
  • MP ~1:1
  • NW ~1:(N+1)
  • WN ~(N+1):1
  • NB ~1:(N+2)/2
  • BN ~(N+2)/2:1
  • NT 1:>(N+1)
  • TN >(N+1):1
  • FT FellThrough (the cracks, ie, no match)
Partitioning Data Into Pair Types

We need to turn the relationship between thisPeriod and lastPeriod into an enum value as above.

The region centres are:
  • 1
  • ((N+2/)2)
  • (N+1)
Which leaves us with two borders per centre:
  • (< 1), (> 1)
  • (< ((N+2/)2)), (> ((N+2/)2))
  • (< (N+1)), (> (N+1))
Which leaves the astute reader noticing that there are two regions of overlap that have to be handled, either by priority or setting limitations. I don't like artificial limits on settings, however maybe we'll need it here, or maybe we won't. Pre-post-edit, we don't!

If we check which is bigger and swap the order (and remember that for later) then we can treat the smaller one as "1" and only check upwards.

For N=1, with a 50% tolerance we would count from 1.0 up to 1.5x as the same, and if not matched, from 1.0x (effectively 1.5x) up to 3.0x as wide, and after 3 as too wide. This rules out the detection of reversed teeth, however. The test for reversed teeth should come after the test for wide teeth such that there is a priority level for matching.

Code: Select all

if(thisPeriod > lastPeriod){
    larger = thisPeriod;
    smaller = lastPeriod;
    thisLargerThanLast = true;
}else{
    smaller = lastPeriod;
    larger = thisPeriod;
    thisLargerThanLast = false;
}

if(larger < (1.5 * smaller)){ // has to be first to be most efficient
    pair = MP; // same period, roughly
}else if((larger < (3.0 * smaller)) && (larger > (1.0 * smaller))){ // has to be second to be most efficient
    if(thisLargerThanLast){
        pair = NW
    else{
        pair = WN
    }
}else if((larger <  (2.25 * smaller)) && (larger > (0.75 * smaller))){ // this leads to further code running later, so should come next
    if(thisLargerThanLast){
        pair = NB
    else{
        pair = BN
    }
}else if(larger > (3.0 * smaller)){
    if(thisLargerThanLast){
        loseSync(yourVRSensorHasALoosePlugFixIt);
    }else{
        loseSync(noiseAppearedWayTooEarlyAsIfItWasAVRToothButWasnt);
    }
}else{ // fell between the cracks, not matched, settings very tight, therefore was in two possible places on either side of (N+2)/2.
    loseSync(yourSyncToleranceIsTighterThanAWellYouGetTheIdea);
}
Simply substituting the correct variables into this will yield working code.

Then we have to use that info, see the next post for more info.

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,e

Post by Fred »

Matching Patterns Using Pairs

For gaining sync if we keep in mind the possibility of a reversed wheel, we wind up with this situation for N=1:
  • 2,1,1 - probably
  • 1,2,1 - certain
  • 1,1,2 - probably
  • 1.5,1,1 - inconclusive
  • 1,1.5,1 - probably
  • 1,1,1.5 - inconclusive
  • 1.5,1.5,1 - reversed wheel error
  • 1,1.5,1.5 - reversed wheel error
  • 2,2,1 - probably reversed wheel error
  • 1,2,2 - probably reversed wheel error
Unfortunately the above listed pair possibilities are not all, ignoring the instant fails from TC,NT, and TN there are actually 25 permutations (5^2), where two numbers = one pair. We reduced it from 64 possible combos by recognising the valid and reversed ones, and rejecting all of the rest as noise. All possible permutations and outcomes:
  • MP,MP - No sync, no error, just wait. This is the normal case of being anywhere other than the sync point on the wheel.
  • MP,NW - Sync!
  • NW,WN - Sync! Perfect case.
  • WN,MP - Sync!
  • NW,BN - Reset state, nearly synced error!
  • NB,WN - Reset state, nearly synced error!
  • NB,BN - Reset state, nearly synced error!
  • MP,NB - Reset state, nearly synced error!
  • BN,MP - Reset state, nearly synced error!
  • WN,NW - Reset state, extra tooth error.
  • WN,NB - Reset state, extra tooth error.
  • BN,NW - Reset state, extra tooth error.
  • BN,NB - Reset state, extra tooth error.
  • MP,BN - Reset state, reversed VR wiring error!
  • MP,WN - Reset state, reversed VR wiring error!
  • NW,MP - Reset state, reversed VR wiring error!
  • NB,MP - Reset state, reversed VR wiring error!
  • NW,NB - Reset state, excess deceleration error.
  • NB,NW - Reset state, excess deceleration error.
  • NW,NW - Reset state, excess deceleration error.
  • NB,NB - Reset state, excess deceleration error.
  • BN,BN - Reset state, excess acceleration error.
  • BN,WN - Reset state, excess acceleration error.
  • WN,BN - Reset state, excess acceleration error.
  • WN,WN - Reset state, excess acceleration error.
Which translates into the following rules, in order, for efficiency:

If synced, directly check for what we are expecting, lose sync with "wrong state found" or similar.

If not synced, search for sync as follows:
  • Three matching periods, or two matched pairs of periods (MP, MP) means we're just on a normal tooth, record what we need to and exit to wait for the next one. 1 gone
  • Check for three possible sync points and declare sync if we find one. 3 gone.
  • Nearly synced error! Cases that were the same basic pattern as the 3 sync opportunities, but slightly out of tolerance. 5 gone.
  • Extra tooth error. Getting long short long = extra tooth inserted between two others, definitely noise. 4 gone.
  • Reversed VR wiring error! Stepping up to a wide or backwards and then getting another wide or backwards, respectively (MP), OR, Getting two matching periods, and then stepping down to a narrow from a wide or backwards. 4 gone.
  • Excess deceleration or acceleration error. Any remaining matching or nearly matching comparison pairs are rejected and state is reset with accel or decel noise error. 8 gone.
This can be performed with the following code, a very nice, elegant and efficient solution to this issue:

Code: Select all

typedef struct {
    unsigned thisPair: 4;
    unsigned lastPair: 4;
} twoPairs;

typedef union {
    twoPairs pairs;
    unsigned char pattern;
} match;

match matches;

<other code that populates matches>

// This all needs a little more complexity for cam only/crank only/crank + cam sync use, hard coded to crank only for now

if(matches.pattern == MatchedPairMatchedPair){ // small small small - All periods match 
    NumberOfTwinMatchedPairs++;
    if(NumberOfTwinMatchedPairs == NUMBER_OF_WHEEL_EVENTS){
        // This will match repeatedly then un-sync on next cycle if tolerance is set too high
        currentEvent = NUMBER_OF_WHEEL_EVENTS - 1;
        decoderFlags |= CRANK_SYNC;
    } // else fall through to wait.
}else if(matches.pattern == MatchedPairNarrowWide){ // small small big - First tooth after missing 
    currentEvent = 0;
    decoderFlags |= CRANK_SYNC;
}else if(matches.pattern == NarrowWideWideNarrow){ // small big small - Second tooth after missing, the strongest and most certain sync 
    currentEvent = 1;
    decoderFlags |= CRANK_SYNC;
}else if(matches.pattern == WideNarrowMatchedPair){ // big small small - Third tooth after missing 
    currentEvent = 2;
    decoderFlags |= CRANK_SYNC;
}else{
    resetToNonRunningState(matches.pattern); // Where they are defined individually in the error file! Beautiful!!
}
The header can contain the following defines and checks:

Code: Select all

#define MatchedPairMatchedPair 0x44 // small small small - All periods match
#define MatchedPairNarrowWide  0x46 // small small BIG - First tooth after missing
#define NarrowWideWideNarrow   0x67 // small BIG small - Second tooth after missing, the strongest and most certain sync
#define WideNarrowMatchedPair  0x74 // BIG small small - Third tooth after missing
// Fails:
#define NearlySyncedNarrowWideBackwardNarrow           0x65
#define NearlySyncedNarrowBackwardWideNarrow           0x87
#define NearlySyncedNarrowBackwardBackwardNarrow       0x85
#define NearlySyncedMatchedPairNarrowBackward          0x48
#define NearlySyncedBackwardNarrowMatchedPair          0x54
#define ExtraToothWideNarrowNarrowWide                 0x76
#define ExtraToothWideNarrowNarrowBackward             0x78
#define ExtraToothBackwardNarrowNarrowWide             0x56
#define ExtraToothBackwardNarrowNarrowBackward         0x58
#define VRWiringBackwardMatchedPairBackwardNarrow      69 // Engineered to be 69 (0x45) for humour value!
#define VRWiringBackwardMatchedPairWideNarrow          0x47
#define VRWiringBackwardNarrowWideMatchedPair          0x64
#define VRWiringBackwardNarrowBackwardMatchedPair      0x84
#define ExcessDecelerationNarrowBackwardNarrowBackward 0x88
#define ExcessDecelerationNarrowBackwardNarrowWide     0x86
#define ExcessDecelerationNarrowWideNarrowBackward     0x68
#define ExcessDecelerationNarrowWideNarrowWide         0x66
#define ExcessAccelerationBackwardNarrowBackwardNarrow 0x55
#define ExcessAccelerationBackwardNarrowWideNarrow     0x57
#define ExcessAccelerationWideNarrowBackwardNarrow     0x75
#define ExcessAccelerationWideNarrowWideNarrow         0x77
All defined and/or checked with ((firstMatch << 4) + secondMatch), would be nice if they were human readable, though.

And that pretty much completes the magic decoder. My next step is to put the sync tolerance into the MissingTooth spreadsheet so that people can use it to intelligently set that up, including me, with the default values.

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,e

Post by Fred »

Losing Sync Once Running

This needs to be efficient, which is OK, because luckily it can and will be.

Checking to see if we should lose sync, as opposed to gaining sync is simply a matter of the following snippet:

Code: Select all

// Wrapped in a check for sync, if not synced, don't run any of this:

// Some code to roll the variable up by one, and reset it to zero if required.

if((currentEvent == 0) && (matches.pattern != MatchedPairNarrowWide)){ // First event after gap
    resetToNonRunningState(matches.pattern);
}else if((currentEvent == 1) && (matches.pattern != NarrowWideWideNarrow)){ // Second event after gap
    resetToNonRunningState(matches.pattern);
}else if((currentEvent == 2) && (matches.pattern != WideNarrowMatchedPair)){ // Third event after gap
    resetToNonRunningState(matches.pattern);
}else if(matches.pattern != MatchedPairMatchedPair){ // All other events should be preceeded by two matched pairs
    resetToNonRunningState(matches.pattern);
} // else carry on happily as always
That's about it. It's that "simple" :-)

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,e

Post by Fred »

Spread sheet updated and sync stuff is now on Sheet2 along with notes about that on Sheet3 and the original big table on Sheet1.

https://github.com/fredcooke/freeems-va ... s?raw=true

Off to bed!

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,e

Post by Fred »

I entered all of this into real files tonight, written in firefox/phpBB3 and copy paste and, more or less, go. I've got max of a few hours left to get it to the point where it should work, then the debug starts, or not, it could just work. 700 lines of header and 100 lines of code. Should be under 150 when done. probably much less. Pretty happy with it so far :-) We'll see how it works when I hit it with a signal one of these days soon :-)
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,e

Post by Fred »

Just minor timing of operations stuff to do now, should have it tested by the end of tonight if things go well, but I have some other code to take care of too. We'll see :-)
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Generic M-N Missing Teeth Decoder (12-1,24-1,36-1,60-2,e

Post by Fred »

It's pushed, but not tested yet. I need to add some better logging and then do some thorough testing and see if there are any issues. We're close now :-)
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
Post Reply