13.2.11 Quadrature In [T-Series Datasheet]
Overview
T4 Capable DIO: DIO4, DIO5, DIO6, DIO7, DIO8, DIO9 (aka FIO4, FIO5, FIO6, FIO7, EIO0, EIO1)
T7 Capable DIO: DIO0, DIO1, DIO2, DIO3, DIO6, DIO7 (aka FIO0, FIO1, FIO2, FIO3, FIO6, FIO7)
T8 Capable DIO: DIO0, DIO1, DIO2, DIO3, DIO4, DIO5, DIO6, DIO7, DIO8, DIO9, DIO10, DIO11, DIO12, DIO13, DIO14, DIO15 (aka FIO0, FIO1, FIO2, FIO3, FIO4, FIO5, FIO6, FIO7, EIO0, EIO1, EIO2, EIO3, EIO4, EIO5, EIO6, EIO7)
Requires Clock Source: No
Index: 10
Streamable: Yes—integer READ registers only.
Quadrature input uses two DIOs to track a quadrature signal. Quadrature is a directional count often used in various types of rotary encoders when you need to keep track of absolute position with forward & reverse movement. If you have movement in only one direction, or another way to know direction, you can simply use a normal counter with one phase of the encoder output.
T-series devices uses 4x quadrature decoding, meaning that every edge observed (rising & falling on both phases) will increment or decrement the count.
This interrupt-based digital I/O extended feature (DIO-EF) is not purely implemented in hardware, but rather firmware must service each edge. See the discussion of edge rate limits at the bottom of this page.
Quadrature is prone to error if the edge rate is exceeded. This is particularly likely during direction change where the time between edges can be very small. Errors can occur when two edges come in too quickly for the device to process, which can result in missed counts or missed change in direction. These errors will be recorded and the quantity encountered can be read. If three edges come in too quickly an undetectable error can occur.
Some quadrature encoders also include a third output channel, called a zero (Z-phase) or index or reference signal, which supplies a single pulse per revolution. This single pulse is used for absolute determination of position. T-series devices support resets according to this reference signal. Z-phase will reset the count when a high state is detected on the specified DIO line at the same time any edge occurs on A or B phases. If the reference pulse is wider than A/B pulses, consider using the Conditional Reset feature instead of this Z-phase support. If the reference pulse is only high in between A/B edges, consider some sort of RC circuit to elongate it or consider using the Conditional Reset feature. If set to one-shot mode, Z-phase will clear the count only once and must be "re-armed" by disabling/re-enabling the feature or a read from DIO#_EF_READ_A_AND_RESET.
Configure
Two DIO must be configured for Quadrature In. The two lines must be an adjacent even/odd pair:
T4: DIO4/5, DIO6/7, and DIO8/9 are valid pairs.
T7: DIO0/1, DIO2/3, and DIO6/7 are valid pairs.
The even IO line will be phase A and the odd will be phase B.
DIO#_EF_ENABLE: 0 = Disable, 1 = Enable
DIO#_EF_INDEX: 10
DIO#_EF_CLOCK_SOURCE: Not used.
DIO#_EF_CONFIG_A: Z-phase control: 0 = Z-phase off, 1 = Z-phase on, 3 = Z-phase on in one shot mode.
DIO#_EF_CONFIG_B: Z-phase DIO number.
DIO#_EF_CONFIG_C: Not used.
DIO#_EF_CONFIG_D: Not used.
Update
No update operations can be performed with Quadrature In.
Read
The quadrature count and error count are available from the even channel. The odd channel will return zeros.
Results are read from the following registers.
DIO#_EF_READ_A - Returns the current count as a signed 2's complement value.
DIO#_EF_READ_B – Returns the number of detected errors.
DIO#_EF_READ_A_F - Returns the count in a single precision float (float32).
Only reading DIO#_EF_READ_A or DIO#_EF_READ_A_F triggers a new measurement.
Stream Read
All operations discussed in this section are supported in command-response mode. In stream mode, you can read from the integer READ registers (A, B, A_AND_RESET), but as mentioned in the Stream Section those reads only return the lower 16 bits so you need to also use STREAM_DATA_CAPTURE_16 in the scan list to get the upper 16 bits.
Reset
DIO#_EF_READ_A_AND_RESET – Performs the same operation as DIO#_EF_READ_A, then sets the count to zero.
DIO#_EF_READ_A_F_AND_RESET – Performs the same operation as DIO#_EF_READ_A_F, then sets the count to zero.
Example
See our Kipling quadrature input guide.
Configure DIO6 and DIO7 as quadrature inputs:
DIO6_EF_ENABLE = 0 //Make sure DIO-EF is disabled on DIO6
DIO7_EF_ENABLE = 0 //Make sure DIO-EF is disabled on DIO7
DIO6_EF_INDEX = 10 //Set feature index for DIO6 to quadrature.
DIO7_EF_INDEX = 10 //Set feature index for DIO7 to quadrature.
DIO6_EF_ENABLE = 1 //Enable quadrature DIO-EF on DIO6, for A phase.
DIO7_EF_ENABLE = 1 //Enable quadrature DIO-EF on DIO7, for B phase.
Edges on the two lines will now be decoded and the count will be incremented or decremented according to the edge sequence.
The current count can be read from DIO6_EF_READ_A or DIO6_EF_READ_A_AND_RESET.
To enable z-phase connected to DIO5 you would do:
DIO6_EF_CONFIG_A=1
DIO6_EF_CONFIG_B=5
DIO7_EF_CONFIG_A=1
DIO7_EF_CONFIG_B=5
Testing
On some LabJack devices you can physically tap a GND wire into the two DIO channels to cause some counts, but that does not work on T-series devices. Testing needs to be done with a proper quadrature signal.
If testing with an actual encoder, start with DIO-EF enabled and simply watch (e.g. in Kipling) the digital inputs as you slowly turn the encoder to see if the inputs change between high and low. That confirms a valid electrical connection.
You can test using 2 digital outputs to create a quadrature sequence. For example, configure quadrature on DIO6/7 as shown above, and connect DIO0 to DIO6 and DIO1 to DIO7. This can be done with the Register Matrix in Kipling.
DIO0 = 1 //Initialize DIO0 to output-high.
DIO1 = 1 //Initialize DIO1 to output-high.
DIO6_EF_ENABLE = 0 //Make sure DIO-EF is disabled on DIO6
DIO7_EF_ENABLE = 0 //Make sure DIO-EF is disabled on DIO7
DIO6_EF_INDEX = 10 //Set feature index for DIO6 to quadrature.
DIO7_EF_INDEX = 10 //Set feature index for DIO7 to quadrature.
DIO6_EF_ENABLE = 1 //Enable quadrature DIO-EF on DIO6, for A phase.
DIO7_EF_ENABLE = 1 //Enable quadrature DIO-EF on DIO7, for B phase.
Now we can simulate a quadrature signal by toggling DIO0 and DIO1—aka FIO0 and FIO1—in the proper sequence. We will use the FIO_STATE register (address=2500) which operates on all 8 FIO bits at once, but we will set the inhibit bits for FIO2-FIO7 (bits 10-15) so they are not affected. To set bits 10-15 we can simply add 64512 to the desired FIO0/1 state value:
Write FIO_STATE = 3 + 64512, then should read DIO6_EF_READ_A = 0
Write FIO_STATE = 1 + 64512, then should read DIO6_EF_READ_A = 1
Write FIO_STATE = 0 + 64512, then should read DIO6_EF_READ_A = 0
Write FIO_STATE = 2 + 64512, then should read DIO6_EF_READ_A = -1
Write FIO_STATE = 3 + 64512, then should read DIO6_EF_READ_A = -2
Write FIO_STATE = 2 + 64512, then should read DIO6_EF_READ_A = -1
Write FIO_STATE = 0 + 64512, then should read DIO6_EF_READ_A = 0
Write FIO_STATE = 1 + 64512, then should read DIO6_EF_READ_A = 1
Write FIO_STATE = 3 + 64512, then should read DIO6_EF_READ_A = 2
Write FIO_STATE = 2 + 64512, then should read DIO6_EF_READ_A = 3
Write FIO_STATE = 0 + 64512, then should read DIO6_EF_READ_A = 4
Write FIO_STATE = 1 + 64512, then should read DIO6_EF_READ_A = 5
Write FIO_STATE = 3 + 64512, then should read DIO6_EF_READ_A = 6
Write FIO_STATE = 2 + 64512, then should read DIO6_EF_READ_A = 7
Quadrature Decoding or Simple Counting?
Quadrature decoding is only needed when you need to keep track of absolute position with changes in direction included.
If you want to track absolute position but the direction does not change, or for whatever reason you always know the direction of movement, then you can just count the pulses from one phase (A or B) using a simple counter. The interrupt counters available on 6 of the FIO0 lines have the same 70k edge rate limit discussed below, but they only do 1x counting and only use 1 timer. The high-speed counters on the 4 CIO lines can handle up to 5 MHz per counter.
If you are just trying to measure frequency, you can use a counter as described above and note the change in count over some time interval, or you can use a DIO-EF that measures the time of individual pulses. Either way, just one phase (A or B) is needed.
Edge Rate Limits
Keep in mind that T-series devices do 4x quadrature counting. For example, a 100 pulses/revolution encoder connected to a pair of DIO will generate 400 edges/revolution.
This interrupt-based digital I/O extended feature (DIO-EF) is not purely implemented in hardware, but rather firmware must service each edge. This makes it substantially slower than other DIO-EF that are purely hardware-based. To avoid missed edges, the aggregate limit for edges seen by all interrupt-based DIO-EF is 70k edges/second. If stream mode is active, the limit is reduced to 20k edges/second. Excessive processor loading (e.g. a busy Lua script) can also reduce these limits. Note that interrupt features must process all edges, rising & falling, even if a given feature is configured to only look at one or the other. Additionally, note that intensive interrupt based features may limit the maximum streaming rates due to processor loading.
The more proper way to think of the edge limit, and understand error that could be introduced when using multiple interrupt-based DIO-EF, is to consider that the interrupt that processes an edge can take up to 14 μs to complete. When a particular channel sees an applicable edge, an IF (interrupt flag) is set for that channel that tells the processor it needs to run an ISR (interrupt service routine) for that channel. Once an ISR is started, it runs to completion and no other ISR can run until it is done (except that stream interrupts are higher priority and will preempt other interrupts). When an ISR completes, it clears the IF for that channel. So it is okay to have edges on multiple channels at the same time, as long as there is not another edge on any of those channels before enough time to process all the initial edges.
Say that channel A & B have an edge occur at the same time and an ISR starts to process the edge on channel A. If channel A has another edge during the first 14 μs, that edge will be lost. If channel B has another edge during the first 14 μs, the initial edge will be lost. If channel B has another edge during the second 14 μs (during the ISR for channel B), the new edge will be lost.
For faster quadrature tracking, one option is to use a chip such as the LS7366R-S from US Digital and then use the SPI ability of the T-series device to talk to that chip. In fact, a Lua script can be used to handle the SPI communication with the chip and periodically put the current count in a user-ram register than can be easily read by any host application or Modbus client.
Examples:
See the Rotary Encoder app-note for examples and more.