Page 1 of 1

zx-128a1 Dev Board QDEC Implementation

Posted: 01 December 2010, 1:03 AM
by dajacobs
Hello,
I am looking for some support on implementing the QDEC on the ZX-128a1 Dev Board. I have an optical encoder connected to A.0 and A.1. After following the instructions in the Atmel XMEGA manual, I have an interesting repeatable error.

I am able to get counts in both directions when I rotate the wheel but there are times when the count increases rapidly without any motion. Using the scope, the signals going in are nice and square. However, I found that if the wheel stops spinning on a count where both A and B are high I get this repeatable rapid incrementing when the wheel is stopped.

Any advice you have would be most appreciated

Thanks,
Daniel

Code: Select all

sub InitEventModule()
   
'~ For a full QDEC setup the following is required:
'~ •I/O port pins - quadrature signal input
'~ •The Event System - quadrature decoding
'~ •A Timer/Counter - up, down and optional index count
'~ The following procedure should be used for QDEC setup:

'~ •Choose two successive pins on a port as QDEC phase inputs.
'~ •Set pin direction for QDPH0 and QDPH90 as input.
'Pin A.0 and A.1 are input by default

'~ •Set pin configuration for QDPH0 and QDPH90 to low level sense.
SetBits Register.PORTA_PIN0CTRL, &B0000_0111, &B0000_0011
SetBits Register.PORTA_PIN1CTRL, &B0000_0111, &B0000_0011

'~ •Select QDPH0 pin as multiplexer input for an event channel, 0.
SetBits Register.EVSYS_CH0MUX, &B1111_1111, &B0101_0000

'~ •Enable quadrature decoding and digital filtering in the Event Channel.
SetBits Register.EVSYS_CH0CTRL, &B0000_1111, &B0000_1001

	
'~ •Optional:
'~ a.Setup QDEC index (QINDX).
'~ b.Select a third pin for QINDX input.
'~ c.Set pin direction for QINDX as input.
'~ d.Set pin configuration for QINDX to sense both edges.
'~ e.Select QINDX as multiplexer input for Event Channel n+1
'~ f.Set the Quadrature Index Enable bit in Event Channel n+1.
'~ g.Select the Index Recognition mode for Event Channel n+1.
' Don't have an index

'~ •Set quadrature decoding as event action for a Timer/Counter.
SetBits Register.TCC0_CTRLD, &B1110_0000, &B0110_0000

'~ •Select Event Channel 0 as event source the Timer/Counter.
SetBits Register.TCC0_CTRLD, &B0000_1111, &B0000_1000

'~ •Set the period register of the Timer/Counter to ('line count' * 4 - 1). (The line count of the 
'~ quadrature encoder).
Register.TCC0_PER = LineCount*4-1

'~ •Enable the Timer/Counter by setting CLKSEL to a CLKSEL_DIV1.
SetBits Register.TCC0_CTRLA, &B0000_1111, &B0000_0001

'~ The angle of a quadrature encoder attached to QDPH0, QDPH90 (and QINDX) can now be read
'~ directly from the Timer/Counter Count register. If the Count register is different from BOTTOM
'~ when the index is recognized, the Timer/Counter error flag is set. Similarly the error flag is set if
'~ the position counter passes BOTTOM without the recognition of the index.

end Sub

Re: zx-128a1 Dev Board QDEC Implementation

Posted: 01 December 2010, 7:24 AM
by spamiam
dajacobs wrote:Using the scope, the signals going in are nice and square. However, I found that if the wheel stops spinning on a count where both A and B are high I get this repeatable rapid incrementing when the wheel is stopped.
Well, clearly that should not be happening that way. How many MHz is your scope rated for? One of the signals may be right on the edge and transitioning so fast that the scope can't see it.

Can you try replacing the encoder with just a couple of wires. Simulate the both high condition by connecting A0 and A1 to VCC. Do you see transitions then?

I'd guess that your signals are not as clean as you think, and there is some noise coming in there somewhere to make the CPU think it is seeing transitions.

-Tony

Posted: 01 December 2010, 8:10 AM
by dkinzer
I assume you've seen AVR1600: Using the XMEGA Quadrature Decoder and the accompanying example code.

Re: zx-128a1 Dev Board QDEC Implementation

Posted: 01 December 2010, 9:26 AM
by dkinzer
dajacobs wrote:However, I found that if the wheel stops spinning on a count where both A and B are high I get this repeatable rapid incrementing when the wheel is stopped.
Your code sets the input sensing for the quadrature inputs to "low level". About this, the xmega documentation says:
A low pin value will not generate events, and a high pin value will continuously generate events.
This seems to explain what you're seeing. Interestingly, the example code for AVR1600 does the same. I'm not sure how this is supposed to work. I should think that using edge sensing would be more appropriate but, then again, I'm not a quadrature decoding expert.

As an aside, since you are using a timer you should eventually add code to set the TimerBusy flag for that timer so that other I/O functions won't use it.

Code: Select all

If Semaphore(Register.TimerC0Busy) Then
...
End If

Re: zx-128a1 Dev Board QDEC Implementation

Posted: 01 December 2010, 14:22 PM
by dlh
dkinzer wrote:I'm not a quadrature decoding expert.
Tom Becker has some expertise in this area. Perhaps a PM will alert him - the subject probably did not pique his interest.

Posted: 02 December 2010, 8:43 AM
by GTBecker
2. Configure PD0 and PD1 input sense control register to level sensing (transparent
for events).
3. Select PD0 as multiplexer input for event channel 0.
4. Optional for index:
a. Configure PD2 as input.
b. Configure PD2 input sense control register to sense both edges.
I haven't used the QDEC resource so I can't comment very specifically, but line 2 above is is puzzling considering line 4b. A quadrature phase _is_ an edge-triggered signal, i.e. it is a change that drives the result, not a current fixed level. An index is no different in that regard from the two quadrature phases, so setting PD0 and PD1 to level sensing and PD2 to edge sensing seems contradictory - but I don't yet grok the mechanism so that might be incorrect.

To date, my quadrature detection on these machines has been done with some external hardware that detects change and drives an interrupt whose code determines what changed and ncrements appropriate variables.

Tom

Posted: 08 December 2010, 14:46 PM
by dajacobs
Thank you all. I ended up redoing all the wiring and that appears to have cleaned up my issue. The final code is as I originally posted.