Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

how to read quadrature encoder using analog input

How can I use an analog input input port to efficiently read the angle of a quadrature encoder?

 

Background

Hardware: USB 6361 DAQ (manual), 2345 Signal Carrier/Conditioner (manual), X4 optical encoder with 1250 pulses/revolution (manual)

I would like to provide position feedback for a PID VI. Previously, I provided this feedback with an increment encoder connected to a counter port on my USB 6361. However, I'm running out of counter I/O ports, so I would like to use analog input channels to provide feedback for my PID. To do that, I understand that I need to:

  1. use 3 AI channels to capture the pulse train generated by the A, B, and Z channels of my encoder (pulse train = non-uniform square wave, correct??)
  2. Process those pulses into an angle (to be discussed below)
  3. Give angle to PID (trivial)

However, I'm having trouble with the timing of part 1 and the logic of part 2.

 

Problem 1: timing signal acquisition

know I want to continuously acquire each signal. My DAQ can digitize multiple signals at 1 MHz, so 1 MHz / 9 signals (worst case) ~= 100 kHz sample rate. According to part 2 of this paper, I should set the number of samples per channel to 1/10th the sample rate (10 kHz)--is this correct? Or am I mixing topics?

 

Furthermore, the sampling rate shouldn't affect the final angle since the samples will be processed at a different rate (frequency of while/PID-loop)--correct?

 

Problem 2: processing analog signal

Assuming my timing is right, then every while-loop iteration I will have an array of voltage values for A, B, and Z that I will need to process into pulses and then to angle. Going from a pulse to an angle should be easy ((edge_count * 360) / (4 * 1250)), but I don't understand how to go from voltages to pulses--namely, I don't understand how to account for which pulse has the "lead". 

 

But first, let me explain my thought process for processing a single signal's pulses. I'm basing the following pseudocode on this example VI

 

rise = 0;

for (int n = 0; n < voltage_array_A; n++)

/val = nth element of voltage array

if(val >= high_limit && rise == 0)

rise = true;

if(val <= low_limit && rise == 1)

rise = 0;

pulses++

 

 

I'd process signal B similarly, but how would I account for which signal has the lead? Should I create a state variable (high/low) for A and B, and use shift registers to compare current and previous values of each signal? And how should I process the Z signal?

 

Finally, is there a better way to process quadrature encoders without counter I/O? I found this example using DIO, but I chose not to pursue it since my DAQ only has 8 DIO ports and I may need to process up to 9 signals. Thanks!

0 Kudos
Message 1 of 5
(4,991 Views)

Are you sitting comfortably? This is going to get ugly. Here is the old-school way of doing it.

 

I presume that you have access to a pile of 74 series TTL (or 74LS or 74HC or 74HCT) and a prototyping board and that you are unafraid to use them, and know about discrete logic (e.g. ALWAYS tie unused inputs to VCC or GND as appropriate).An oscilloscope will be essential for debugging. A presettable pulse generator will be helpful.

You will need need:

Schmitt Trigger inverters/buffers

A D-type flip flop

A 16 bit presettable parallel counter (or 2 8 bit counters in series) (4 off 4 bit counters, e.g. 74HC191)

LTC1597 16-Bit Parallel Multiplying DAC with 4-Quadrant Resistor (+other parts in LTC1597 datasheet)

Make sure your encoder is using a 5 volt PSU. Use the more voltage tolerent 4000 series CMOS if not.

Connect encoder A, B & Z to separate Schmitt trigger buffers to generate As, Bs & Zs.

Connect As to the D input of the D type FF.

Connect Bs to the clock input of the FF and the clock input of the counter.

Connect the output of the FF to the up/down input of the counter.

Connect Zs to the parallel load (PL) input of the counters

Connect the parallel input of each counter (d0-d3...) so that the DAC will give 0 output when preloaded with this value. Dig into the datasheet for the LTC1597 to see what binary representation it requires to go from full scale negative to fullscale positive on the output.

 

Connect the 16 counter outputs to the 16 DAC inputs.

Wire the DAC as per the LTC datasheet page 1.

Adjust V ref so that +1249 pulses gives 5 volts. Check that it zeros with the Z pulse, and that going backwards causes it to go negative to -5 v at -1249 pulses after the z pulse.

 

 

 

 

6-Bit
Message 2 of 5
(4,974 Views)

Steve, that's a bit outside my comfort zone. Any way I can do that via software in LV?

0 Kudos
Message 3 of 5
(4,946 Views)

You can probably do it in LV, but a D type Flip-flop will massively simplify your problem, because it will decode the pulse stream to seperate [pulse] and [up/down] signals. These parts are normally less than $1, so it does not matter if you blow a few up.:mansad: The rest of the complexity is because I thought you wanted the information in a single analogue input, and could be discarded if you really want to do it in LV but consume 3 analogue inputs.

 

Actually, I'd test the performace of your USB 6361 with the encoder hooked up to the analogue inputs quite carefully before writing lots of code. I.E. write a short VI that ONLY reads the 3 analogue inputs at your required speed and writes to disk with TDMS. Run the shaft encoder at the expected range of speeds and directions, and see if there are any artifacts in the data.

0 Kudos
Message 4 of 5
(4,939 Views)

Steve,

 

I apologize for the response delay. I actually just got assigned a new project, so I won't be able to test your suggestion. Thanks for informing me about flip flops though. I think they're going to come in handy for future projects!

0 Kudos
Message 5 of 5
(4,875 Views)