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?
已解决! 转到解答。
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
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
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.
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.
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:
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
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