QEI inputs, and index capture

cancel
Showing results for 
Search instead for 
Did you mean: 

QEI inputs, and index capture

Jump to solution
2,640 Views
Senior Contributor III

I am studying the quadrature mode of the Kinetis K family, more specifically the K10, and specs for these have the general statement:

Quadrature decoder with input filters, relative position counting, and interrupt on

position count or capture of position count on external event.

My problem is the 'capture of position count on external event', or more particularly the connection of an encoder Index pulse.  These quadrature functions are available on 2-channel FTM instantiations, and the A/B inputs 'take over' the two associated channel I/O connections for that module, and later in the FTM description of Quadrature Decoder Mode is the statement "no channel logic is used in Quadrature Decoder mode."  So I don't know where this 'capture of position count on external event' functionality IS.  One 'grand hope' I have is that the FTM Hardware Trigger(s) discussed in the FTM instantiaion information can be forwarded to the channel capture logic and re-enable use of one channel's capture function.  Has anybody made a full A/B/X encoder interface work with these quadrature capabilities?

Labels (1)
Tags (4)
0 Kudos
1 Solution
65 Views
Senior Contributor III

By experimentation, that control bit does indeed seem to work!  Not my 'favorite' way to prove chip functions, but in a pinch it will do...


This is CONTRARY to the AN4381 statement:

"The processing of the index signal together with the phase signals can only be  done in an FTM with three or more channels."

That is, with the SOPT4 register contents set to use the CMP1 ‘output’ as the channel-0 input capture control (for the 2-channel FMT2 in this example):

    //Hook FTM2 CH0 capture to run from this CMP1 comparator output!

    SIM_SOPT4 |= SIM_SOPT4_FTM2CH0SRC(2);

I do INDEED get a capture value at the index edge!  Now of course that still leaves one fundamental issue with this process – knowing ‘which direction’ we were going at the time!  That is, for any ‘width’ of Index pulse more than ¼ of the quadrature-period, then the ‘rising’ (or falling) edge we encounter will be the ‘leading’ (or trailing) edge of the pulse, so the encoder counts will inherently differ by the number of PHA/B edges that occur during the width of the index pulse.  There is a status bit that tells me the ‘last direction’ the counter was going when I read it, but any value of that assumes that the direction at the time I can get to read it is the same as the direction at the time of the Index-driven capture, which is ‘less than ideal’ in cases of shaft jitter, but I think this is going to work out ‘pretty well’.  My next test is to try the 'dual edge capture' capabilities to give me both edges to work with, and that should help the counter-consistency decisions!

As an example, here is some output from my test:

Overflow UP       -- output when overall counter goes from 0xFFFF back up thru 0

0031F                 -- output from comparator-interrupt routine

    0031F UP          -- output from FTM channel-zero input capture, also printing that ‘last direction’ as UP

00321                 -- output from comparator-interrupt routine, going the other direction

    00321 DN          -- output from FTM channel-zero capture, going ‘down’ this time so the ‘leading edge’ comes 2 counts earlier!

0031F

    0031F UP          -- Back in the ‘up’ direction

0063F

    0063F UP          -- One ‘whole turn’ later!

Incidentally, this is a 200-slot encoder disk, so 800 (0x320) quad-edge counts per revolution.  The above test was started right at the index pulse.  At this ‘speed’ (a CRAWL) the comparator and capture interrupts agree on the encoder count.  Certainly at higher speeds, and with some interrupt latency, this will NOT remain true.

Message was edited by: Earl Goodrich II

View solution in original post

0 Kudos
7 Replies
66 Views
Senior Contributor III

By experimentation, that control bit does indeed seem to work!  Not my 'favorite' way to prove chip functions, but in a pinch it will do...


This is CONTRARY to the AN4381 statement:

"The processing of the index signal together with the phase signals can only be  done in an FTM with three or more channels."

That is, with the SOPT4 register contents set to use the CMP1 ‘output’ as the channel-0 input capture control (for the 2-channel FMT2 in this example):

    //Hook FTM2 CH0 capture to run from this CMP1 comparator output!

    SIM_SOPT4 |= SIM_SOPT4_FTM2CH0SRC(2);

I do INDEED get a capture value at the index edge!  Now of course that still leaves one fundamental issue with this process – knowing ‘which direction’ we were going at the time!  That is, for any ‘width’ of Index pulse more than ¼ of the quadrature-period, then the ‘rising’ (or falling) edge we encounter will be the ‘leading’ (or trailing) edge of the pulse, so the encoder counts will inherently differ by the number of PHA/B edges that occur during the width of the index pulse.  There is a status bit that tells me the ‘last direction’ the counter was going when I read it, but any value of that assumes that the direction at the time I can get to read it is the same as the direction at the time of the Index-driven capture, which is ‘less than ideal’ in cases of shaft jitter, but I think this is going to work out ‘pretty well’.  My next test is to try the 'dual edge capture' capabilities to give me both edges to work with, and that should help the counter-consistency decisions!

As an example, here is some output from my test:

Overflow UP       -- output when overall counter goes from 0xFFFF back up thru 0

0031F                 -- output from comparator-interrupt routine

    0031F UP          -- output from FTM channel-zero input capture, also printing that ‘last direction’ as UP

00321                 -- output from comparator-interrupt routine, going the other direction

    00321 DN          -- output from FTM channel-zero capture, going ‘down’ this time so the ‘leading edge’ comes 2 counts earlier!

0031F

    0031F UP          -- Back in the ‘up’ direction

0063F

    0063F UP          -- One ‘whole turn’ later!

Incidentally, this is a 200-slot encoder disk, so 800 (0x320) quad-edge counts per revolution.  The above test was started right at the index pulse.  At this ‘speed’ (a CRAWL) the comparator and capture interrupts agree on the encoder count.  Certainly at higher speeds, and with some interrupt latency, this will NOT remain true.

Message was edited by: Earl Goodrich II

View solution in original post

0 Kudos
65 Views
Senior Contributor III

Indeed, dual-edge DOES work, although I had some 'difficult' troubles with the consistency-control logic.  I put rising (leading) edge on C0, falling (trailing) on C1 (still both fed thru the SOPT4 option from CMP1)

So now I wait for the 'falling edge' detect on FTM2 channel 1, and at that time evaluate both channel 0 and 1 values for the 'least' to indicate a consistent 'edge point' for the index relative to PHA/B count values!  This is my 'test' output:

08034 rise                   -- Compare interrupt on rising (leading) edge

08036 fall                    -- Compare interrupt 'fall' (trailing)

       8034 8036  UP     -- FTM2 C1 'capture' interrupt with both edges (C0V and C1V). and QD direction

08354 rise                  --  One turn later, so same as above plus 0x320

08356 fall                                                                   

       8354 8356  UP                                                         

08356 rise                  -- Compare interrupt on leading edge, in reverse direction

08354 fall                   -- Compare trailing edge, still in reverse

       8356 8354  DN    --  FTM2 C1 capture interrupt from reverse direction, so the 'higher' count matches the

                                     index rising edge, and the falling edge comes 'later' as the count continues to decrease.

Attached is a version of the code that runs this test.  Please, no points off for style(!), especially printf() in isr!...this is just test-case code.

0 Kudos
65 Views
Senior Contributor III

Just a footnote on the impressive performance of the Kinetis QD FTM functions.

With 'maximum filtering' set in FTMx_FILTER, a 36MHz bus clock allows just about 1.2 Million edges per second.

With filtering 'off', it looks like the edge rate can run right at the 1.5 bus-clocks per edge per the datasheet GPIO spec!  Each input frequency is only 1/4 the edge rate, of course.

And running 'near the limits' of clocks and filters of course requires 'perfect quadrature', with each input truly 50/50 and offset exactly 90 degrees.  Deviations will decrease the overall edge rate until the 'shortest' segment satisfies.

0 Kudos
65 Views
Senior Contributor II

Hi Earl, thanks for sharing your QEI file with us.  I'm glad I found it, as I am having a lot of trouble getting QD working on my FRDM-K64F using FTM2 configured to read a QE on PTB18 and PTB19.  I am comparing your code to mine, and was hoping that you could answer some questions I have come up with:

  • You set the DECAPEN0 flag just before enabling the FTM.  The docs say that this field is write-protected, so MODE[WPDIS] has to be 1 for it to take effect.  Is there a reason why you didn't put FTM2_MODE = FTM_MODE_FTMEN_MASK | FTM_MODE_WPDIS_MASK before FTM2_COMBINE = FTM_COMBINE_DECAPEN0_MASK?
  • Is it necessary to set FTMx_CnV?  Your comment says "clear these while we can", which sounds important, but the docs say that in input capture or dual edge capture modes, these registers are ignored.
  • For "quick and dirty" testing, I just have a task that performs all of my register initializations, and then sits in a while loop and monitors FTM2_CNT and should hit a breakpoint any time the count changes.  However, it never changes.  At some point I will add the ISR to deal with counter rollover, but is it necessary to implement this now when I just want to see the FTM2_CNT register change as I spin the encoder?
  • I think the main problem I'm having is that I can't set FTM2_MOD.  It's always zero.  I've also tried to follow FSL's flowchart for modifying that value, but even when I set up the other registers as indicated, when I write FTM2_MOD it's still 0.  Would you agree that anytime FTM2_MOD is 0, FTM2_CNT will be stuck at 0 as well?
0 Kudos
65 Views
Senior Contributor II

I think I've finally figured it out.  I will update my own post with my findings.

0 Kudos
65 Views
Contributor III

  Hello Earl,

I just working with A and B inputs of quadrature encoder with "my" Kinetis K60 board (we have a project board with K60 where I connect the inputs to check the functionality of inputs).

You can refer to the Application Note 4381:

http://cache.freescale.com/files/32bit/doc/app_note/AN4381.pdf?fpsp=1&WT_TYPE=Application Notes&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation

and, if you use the Processor Expert in your exampe project, you can use only the Init_FTM component to initialize it and after you can work directly with  Registers:

-) FTM1_CNT is the counter register;

-) FTM1_QDCTRL to set some charateristcs of encoder (in my example I use the command

FTM1_QDCTRL ^= FTM_QDCTRL_PHAPOL_MASK;

to change "rotation" of encoder, it reverse the channel A logic)

Let me know if you need example project to test it.

Best Regards,

Paolo

0 Kudos
65 Views
Senior Contributor III

Thank you for this input. I see where you work with A/B, and I also see the same in AN4381 -- that AN specifically says that the index-pulse will be handled as an edge interrupt.  But this fails to resolve the Kinetis-documentation statement 'capture of position count on external event', and invites inherent index-count-resolution error due to various interrupt delays.

So I'm still looking for somebody, presumably at Freescale, to explain the claimed FTM quadrature capability 'capture of position count on external event'.

--ERGII

0 Kudos