Teensy 3 Encoder Lib

Status
Not open for further replies.
Hi Chaps,
Does anyone know if the encoder.h will work on Teensy 3 using Ardunio 1.0.2?
I have this working fine on Teensy 2 and collects pulses from my Linier Encoders has not missed a single pulse and want upgrade to the faster T3.
I have downloaded Arduino version 1.0.2 but this does not have the encoder library included.
Regards,
LP :)
 
Try replacing the util/direct_pin_read.h with this:

Code:
#ifndef direct_pin_read_h_
#define direct_pin_read_h_

#if defined(__AVR__) || defined(__MK20DX128__)

#define IO_REG_TYPE                     uint8_t
#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask)     (((*(base)) & (mask)) ? 1 : 0)

#elif defined(__SAM3X8E__)

#define IO_REG_TYPE                     uint32_t
#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask)     (((*(base)) & (mask)) ? 1 : 0)

#elif defined(__PIC32MX__)

#define IO_REG_TYPE                     uint32_t
#define PIN_TO_BASEREG(pin)             (portModeRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask)     (((*(base+4)) & (mask)) ? 1 : 0)

#endif

#endif

This doesn't provide any of the intense optimization that I did for AVR, but it should at least work. I'll look at optimizing Encoder for ARM sometime next year.
 
Fully understanding the lack of optimization, I'd like to ask a clarifying question regarding performance of the code you posted, Paul: When I run the basic example from the Encoder library (on a T3 on a breadboard with hardware set up for a much larger sketch), it works really well. However, when I add a simple Serial.println(myEncoder.read()); to the loop in the much larger sketch I have, it responds but with no correlation to the left/right differentiation of the encoder...I think it's missing single signals in the quadrature wave and getting confused.

My sketch is 40k right now, so it's pretty large, and I'm using 2 interrupts for button presses, the SD library, and an I2C display. My assumption is that the raw reads are just too slow and some percentage are getting lost, which leads to inaccuracy in the reported encoder position. Might there be anything else I can do in my sketch to make position reading more accurate before the ARM optimizations are done next year?
 
Given that the K20 family has a hardware quadrature decoder (available with 2 alternate locations/pin pairs, both seem to be usable), it would be nice if that was supported...
 
First notes toward hardware-based encoder decoding for the T3

I took a first look at hardware-based encoder decoding on the T3. For what they're worth, here are my notes from scoping out hardware decoding.


Don't look for encoder in the monstrous data "sheet;" instead search for quadrature. The chip can also decode step/direction style encoders, but searching for quadrature will get you to the right places.

This chip has one channel of hardware quadrature decoder. Hardware encoder decoding *must use* both channels on the second timer module, FTM1 -- can't switch it to other timer channels.

Paul, do you know of any T3 code in your distribution that must use FTM1? If so, please let me know what.
My hope is that other timer-based functionality does not use FTM1 (except for PWM/capture/compare on pins 3&4.) If nothing else needs to use FTM1, that would lower the odds that encoder decoding will break something else.

From the T3 schematic and sect 10.3.1 (datasheet pinout table, p. 194, fifth and sixth row up from bottom),
quadrature decoding is available on chip pins 28/29, which correspond to T3 pins 3/4
or alternatively, chip pins 35/36, which correspond to pins A3/A4 on the T3. Since decoding needs FTM1 anyhow, I'd start using T3 pins 3 and 4. Since decoding is an alternate function for those pin pairs, their default functions would need to be switched to encoder mode.

The timer/counter blocks in the K20 chip are amazingly capable, but also amazingly complex. Take a look at figure 35-1, the block diagram for the timer modules. Thus getting quad decode working -- without breaking other things -- doesn't look that all easy. The chapter on timers is 100+ pages!! Sect 35.4.25 (p. 807) was a good starting point for me for encoder decoding. Although it's complex, I *love* some of the features of the K20's quad decode. (I wouldn't have killed for those in grad school, but I'd probably have considered maiming.) <Just kidding!>

I don't have any encoders handy, so I'm not going to start on encoder/decoding software until I do. But next time I order from either Sparkfun or Adafruit, I'll put a couple low-rez ones in my order.

I'm not promising to deliver working encoder code, but one of my projects would go better with an encoder as a user input (vs. a limited-angle pot.) So when I get to that, I anticipate taking a shot at T3 encoder code.

Please post here if I've gotten something wrong in my notes or if you have comments or other relevant info. -- Larry
 
Last edited:
This chip has one channel of hardware quadrature decoder. Hardware encoder decoding *must use* both channels on the second timer module, FTM1 -- can't switch it to other timer channels.

Paul, do you know of any T3 code in your distribution that must use FTM1? If so, please let me know what.
My hope is that other timer-based functionality does not use FTM1 (except for PWM/capture/compare on pins 3&4.) If nothing else needs to use FTM1, that would lower the odds that encoder decoding will break something else.

I think that analogWrite on pins 3 & 4 uses FTM1 -- see pins_teensy.c
 
I'm planning to work on Encoder again in about 1-2 weeks. My main focus will be on making sure the interrupts are properly used.

I'll take a shot at special code to use FTM1 if pins 3 and 4 are selected. But if I can't get it in a day or two, it'll probably go onto my low-priority list to do later. There are lots of other really important things to do..... and Encoder using interrupts is very capable.
 
I'm planning to work on Encoder again in about 1-2 weeks. My main focus will be on making sure the interrupts are properly used.

I'll take a shot at special code to use FTM1 if pins 3 and 4 are selected. But if I can't get it in a day or two, it'll probably go onto my low-priority list to do later. There are lots of other really important things to do..... and Encoder using interrupts is very capable.

Paul -- what I think is valuable would be to have some documentation about which MCU features the Arduino features use -- e.g. AnalogWrite() on channels 3&4 'take over' the FTM1; tone() uses PIT3 etc.
 
Don't think analogWrite() precludes encoder reading. Just can't do both at once.

I think that analogWrite on pins 3 & 4 uses FTM1 -- see pins_teensy.c

@Jp3141,

Thanks for your response; glad to see others interested.

As I understand it, the existence of analogWrite (a flavor of PWM) for pins 3 or 4 shouldn't be a problem for encoder reading via those pins. Yes, both AnalogWrite() on pins 3,4 and hardware supported encoder reads must use the same counter module, FTM1. But since any I/O pin can only be in one mode at a time, I think the issue for those pins is that they can't be used for anything else while configured for encoder decoding. I think that's the same for any pin with alternate functions.

However, using T3 pins A2 and A3 for encoder inputs means that you can't do analogWrite (or any other timer-based function) on T3 pins 3 and 4, because FTM1 (needed for both) is busy counting encoder steps. Whenever possible, I'd avoid using A2 and A3 for anything digital, including analogWrite (really PWM, a digital output with lots of sharp edges.) IMHO, better to keep those sharp edges as far from analog signals as possible.

Configuring only one pin of either possible pair for encoder reading would limit what you could do with it's mate. But configuring only one pin of a pair for encoder reading doesn't make much sense. IMHO, for a one channel encoder (AKA digital tach) it'd be better to use input capture mode on a non-encoder pin.
 
I'm also very interested in the Encoder library, and if it could be optimized with hardware quadrature decoder it would be awesome ! I'm not good enough to help you developping this kind of stuff, but I fully support you guys ! :)
 
SPI Quadrature Encoder Counter

I agree, that it's important to have a functional encoder library working on the Teensy 3.0.
However, this discussion reminded me of this high performance SPI Quadrature decoder chip that I used very successfully in the past.
One advantage, is that it completely relieves the Micro-controller from monitoring the encoders. When ever you poll it, the current value is there.

There are several variants, but here is a link to the data sheet for the one I used: http://www.lsicsi.com/pdfs/Data_Sheets/LS7366R.pdf

The biggest problem, is that they only seem to be available direct from the manufacturer, with a minimum order of 10.
 
I read part of the manual again, in preparation to work on this in a couple weeks. Probably the trickiest part is going to be extending the 16 bit hardware counter to 32 bits while handling race conditions where the counter overflows or underflows during the read operation.

The one design decision where I could really use some input is the default the Encoder library should use for the input filters? The filter is described in section 35.4.4.1 starting on page 750.

I know some people are excited about the capability to accumulate very fast quadrature waveforms... perhaps up to 6 or 12 MHz? The maximum isn't perfectly clear to me, but I suspect it'll be some division of 48 MHz (the bus clock runs FTM1, not the cpu clock). However, I'm reluctant to make unfiltered the default for the Encoder library. It will be an option if you edit the code, but I know a lot of the encoders people commonly use have high frequency noise, so I really don't want to make unfiltered the default. This isn't like computer speed, where faster is always better. Faster without filtering means more susceptible to noise, contact chatter and signal problems.

The filter clocks at 12 MHz and can require up to 32 of its cycles for the signal to be considered high or low. I believe that means the slowest filter setting would limit the speed to 187.5 kHz (or 750k counts/sec). A fast default might be only 3 or 4 filter clocks, corresponding to 2 MHz or 1.5 MHz signals (8M or 6M counts/sec).

Anyway, a big question I have is what is the benefit you perceive or expect from the hardware quadrature encoder? Is it extremely low CPU overhead? Is it the possibility to measure much faster signals? If the speed is the reason you want to use it, can you give me some description of the source of the fast signals you expect to use?
 
Some data on encoder frequencies from rotary encoders

Paul,

Regarding overflow/underflow/race-condition issues in encoder software:

From my reading of the data (I have trouble calling a 1200+ page document a) sheet section, the chip designers included some hardware to make handling overflow/underflow/race-conditions easier. Search for TOFDIR. Unlike many hardware encoder interfaces, this one not only has a flag for counter rollover, TOF, it also has one for the **direction** of the rollover, TOFDIR. Those flags would have made my grad-school experimental software much, much easier. Without any such flags, the only way I know to maintain an accurate encoder count is to (a) bound the maximum counting rate and then (b) make sure you sample the counter faster than it could possibly count halfway. With those constraints, extending the counter width is doable. With those two flags, one doesn't need to check the counter nearly so often (I think it'd now be the time to count one less than twice the counter's max count -- almost 4 times as long permitted between reads.)

Regarding the filter. I was quite pleased to see they have a filter; not all encoder interfaces have that. Much better with.

Can anybody reading this give an example of anything other than in the guts of a software-defined (really software-morphable) radio that produces digital signals in quadrature at frequencies above 2 MHz.?

I suspect I've used higher resolution encoders than most reading this -- 81,000 lines on the encoder disk, giving 324,000 quadrature counts per revolution. (Has anybody here used an encoder with more lines/disk? If so, please speak up!) That number, by itself, might make you think we'd need a counter that could handle tens or hundreds of MHz. Not so. If you take a look at the specsheet for that 81,000 line encoder, http://usa.canon.com/CUSA/assets/app/pdf/encoder/LaserRotaryEncoder.pdf
you'll see that there's now an even higher resolution version, the R1P20!?! However, if you take a look at the "Max Response" row in those specs, you'll see that the fastest that the raw quadrature signals can go is 2 MHz (and it isn't even for the highest resolution encoder.) Typical encoders used in motion control have no more than 4096 lines/disk (often significantly less.) even spinning at 10,000 RPM (which is cooking along!) that gives 4096*10,000 / 60 = approx 683 KHz. Most shaft encoders have a spec for maximum count rate -- which may well be significantly less than the max. speed constraints from the bearings, etc. involved.

Another data point re filtering: H-P, back before they split up, made an encoder interface chip (originally for their printer division.) That chip used a best-3-out-of-4 filter, fixed thus not programmable. So I suspect that a default of 4 should work well on the high-frequency range. There might be an issue on the other end of frequencies. Mechanical encoders with (inevitably) bouncy contacts will probably bounce too slowly to be caught by the hardware filter. Hopefully mechanical encoders are made such that one phase's bouncing ends before the other phase transitions (and probably starts bouncing.) I haven't used those, though I expect to soon. Optical or magnetic encoders should be fine with the encoder interface hardware on this chip.

What I see as the main benefit of the hardware quad decoder is that, once some poor bastard [1] publishes a timer-interrupt driven ISR to read the encoder periodically and extend the count to 32 or 64 bits (ISR shouldn't take more than a small fraction of the CPU), all we'll have to do (after a few calls to set up the decoder as desired) is call readEncoder()

[1] My intent in this post is to provide some data to assist that poor bastard.
 
Last edited:
Thanks. That's a lot of good perspective on actual encoder needs. :)

once some poor bastard [1] publishes a timer-interrupt driven ISR to read the encoder periodically and extend the count to 32 or 64 bits (ISR shouldn't take more than a small fraction of the CPU), all we'll have to do (after a few calls to set up the decoder as desired) is call readEncoder()

That's pretty much exactly what I intend to try with the Encoder library in a couple weeks. It already implements a 32 bit count based on pin change interrupts and/or polling. When/if I support the hardware encoder, it'll be extended to 32 bits.
 
Quadrature decoding: Clock source(s) and suggested default value for the filters

The maximum isn't perfectly clear to me, but I suspect it'll be some division of 48 MHz (the bus clock runs FTM1, not the cpu clock).

Paul,

Datasheet sect. 35.1.2 states:
Fixed frequency clock is an additional clock input to allow the selection of an on
chip clock source other than the system clock.
The FTM block diagram shows this as well. So it appears we have some flexibility re clock sources for encoder decoding.

Regarding filtering for encoder signals:
I haven't yet found any description of exactly how the filter works. However, my understanding is that when set to N, it requires *something* about N successive samples of the raw encoder signal before changing state. When in quadrature mode, each full cycle of an encoder phase has both a low and a high half cycle. (I'm focusing on quadrature mode for now, rather than step/direction) To ensure that the signal makes it through the filter (so no counts are lost), I'm pretty sure we must ensure at least N samples in each half cycle, thus 2*N samples per full cycle. So, if the maximum frequency of the raw encoder phases is w, then we must clock the filters at 2*N*w or faster. If we can select 48 MHz to clock FTM1, then a filter value of N=4 means the encoder signals must be 48/(2*4) = 6 Mhz or lower. If we can only clock FTM1 at 12 MHz, then the encoder signals cannot exceed 1.5 MHz. I believe a default setting of either 3 or 4 for the encoder filtering is a reasonable starting point.
 
Hi all,

Sorry for deviating from the discussion a bit. I tried to use the Encoder.h library with Teensy3, making modifications to util/direct_pin_read.h as suggested by Paul. The program compiles without errors and sort of works but not very reliably. I am using a standard mechanical rotary encoder and connecting the output of the encoder directly to pins 7 and 8 (no capacitors or damping circuit).

My code monitors the encoder in a loop and does a serial print on whether it is turned clockwise or anticlockwise. So, when I turn the encoder in 1 direction, it reports the wrong direction about 20% of the time. Anyone got the same problem?
 
Try moving from pin 8 to any pin less than 7.

Currently Encoder only supports up to 8 interrupts, on pins 0 to 7. I'm working on an update with will expand it to support interrupts on all pins.
 
Is the hardware quadrature decoder implementation still topical ? Is it scheduled for teensyduino 1.15 ?
 
I'm using 12 mechanical rotary encoders - works fine with the current lib (including the bottom pins, which sure come in handy).

Even though the lib doesn't seem to do filtering/deglitching, I haven't seen any glitches so far (not doing hardware deglitching either, the encoders are wired directly to the Teensy).

(I originally asked about the hardware encoder because I wanted to use it with a motor and high resolution optical encoder, but I ended up with a motor controller that has a quadrature decoder built in.)
 
I'm using 12 mechanical rotary encoders - works fine with the current lib (including the bottom pins, which sure come in handy).

Any chance you could share a photo? I believe 12 is the most I've heard anyone actually used so far.
 
Any chance you could share a photo? I believe 12 is the most I've heard anyone actually used so far.
It's just an ugly prototype right now that needs to move to a real enclosure. Note the obese Teensy that's using some floppy connectors for the bottom pins and power / ground distribution.

The encoders are Alps EC11 with integrated push button (only two buttons connected). There are enough pins left to add a display...

View attachment 741 img2.jpg
 
I'm using 12 mechanical rotary encoders - works fine with the current lib (including the bottom pins, which sure come in handy).

Even though the lib doesn't seem to do filtering/deglitching, I haven't seen any glitches so far (not doing hardware deglitching either, the encoders are wired directly to the Teensy). mlm leads
thank.
 
Hi Paul and other Arduino-Aliens,

is there any news on support for the Teensy 3.0 and the hardware encoder? I'm in the process of doing a FFB Steering Wheel (HID) project based on the Teensy 3.0 using a servo motor with 2.5k lines at max 1.5k rpm. I really need to read the encoder pulses a) very accurately and b) very light on the CPU as there are many other calculations going on which are critical.

Unfortunately I don't really have the skills to dig into the ARM datasheet (yet) but I kind of rely on some functional libraries to finish my (to be OpenSource) project. The market is really missing an OS solution for this particular type of game controller and I'd like to help out as good as I can to get something going here :)
 
Last edited:
Status
Not open for further replies.
Back
Top