EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Re: ARM7 and quadrature encoders

Started by rtstofer December 4, 2007
--- In l..., "roboticsbcn" wrote:
>
> Hello,
>
> I need control 2 quadrature encoders. Some ARM7 of Phillips support
> quadrature encoders to count Up/Down?
>
> If not, someone knows one specific component to count automaticaly the
> position?
>
> The encoder can supply up to 90000 pluses/second in each channel.
>
> Thanks!
>

The LPC2148, among others, has 4 external interrupt inputs which can
be set for rising or falling edge triggering.

Each encoder would use 2 external interrupts and the mode would always
be set for edge trigger and the polarity alternating so as to detect
the next edge. For example, if the last interrupt was on a rising
edge, the next one MUST be a falling edge.

A little state table with +1 and -1 constants selected by which input
changes is about all it takes.

This code is for an Atmel ATmega128 (8 bit uC):

volatile int8_t RightWheelState = 0;
volatile int32_t RightWheelCount = 0;
volatile int8_t LeftWheelState = 0;
volatile int32_t LeftWheelCount = 0;

/* Quadrature Encoder Scheme
*
* There are two pairs of quadrature signals, one for each wheel.
* The right wheel is on EXINT4 (PE4) and EXINT5 (PE5)
* The left wheel is on EXINT6 (PE6) and EXINT7 (PE7)
* Each encoder has two outputs A & B. For convenience, A is
considered the MSB
* while B is considered the LSB.
*/

const int32_t EncoderB[] = {+1,-1,-1,+1};
const int32_t EncoderA[] = {-1,+1,+1,-1};

SIGNAL(SIG_INTERRUPT4) // encoder B for right wheel
{
EICRB ^= 0x01; // toggle the edge bit
RightWheelState ^= 0x01;
RightWheelCount += EncoderB[RightWheelState];
}

SIGNAL(SIG_INTERRUPT5) // encoder A for right wheel
{
EICRB ^= 0x04;
RightWheelState ^= 0x02;
RightWheelCount += EncoderA[RightWheelState];
}

SIGNAL(SIG_INTERRUPT6) // encoder B for left wheel
{
EICRB ^= 0x10;
LeftWheelState ^= 0x01;
LeftWheelCount += EncoderB[LeftWheelState];
}

SIGNAL(SIG_INTERRUPT7) // encoder A for left wheel
{
EICRB ^= 0x40;
LeftWheelState ^= 0x02;
LeftWheelCount += EncoderA[LeftWheelState];
}

Each of the 4 interrupt routines toggles the edge selection bit as
described above. It then keeps track of the current state of the
encoder and adds/subtracts 1 from the wheel count. Initialization
code is not shown but it sets the wheel state to the current levels on
the pins at startup. Even if this didn't work out, only a single edge
would be missed.

I haven't gotten around to doing this with the LPC2148 but there would
be a little more code involved with the VIC.

Richard

An Engineer's Guide to the LPC2100 Series

Thanks Richard, but I prefer one specific device because I have 4
channels at 90.000 pluses/second (180.000 edges/second).

I think that NXP need incorporate specific hardware to count the
pulses from one encoder like dsPIC, or other devices.

Regards!

--- In l..., "rtstofer" wrote:
>
> --- In l..., "roboticsbcn" wrote:
> >
> > Hello,
> >
> > I need control 2 quadrature encoders. Some ARM7 of Phillips
support
> > quadrature encoders to count Up/Down?
> >
> > If not, someone knows one specific component to count
automaticaly the
> > position?
> >
> > The encoder can supply up to 90000 pluses/second in each channel.
> >
> > Thanks!
> > The LPC2148, among others, has 4 external interrupt inputs which
can
> be set for rising or falling edge triggering.
>
> Each encoder would use 2 external interrupts and the mode would
always
> be set for edge trigger and the polarity alternating so as to
detect
> the next edge. For example, if the last interrupt was on a rising
> edge, the next one MUST be a falling edge.
>
> A little state table with +1 and -1 constants selected by which
input
> changes is about all it takes.
>
> This code is for an Atmel ATmega128 (8 bit uC):
>
> volatile int8_t RightWheelState = 0;
> volatile int32_t RightWheelCount = 0;
> volatile int8_t LeftWheelState = 0;
> volatile int32_t LeftWheelCount = 0;
>
> /* Quadrature Encoder Scheme
> *
> * There are two pairs of quadrature signals, one for each
wheel.
> * The right wheel is on EXINT4 (PE4) and EXINT5 (PE5)
> * The left wheel is on EXINT6 (PE6) and EXINT7 (PE7)
> * Each encoder has two outputs A & B. For convenience, A is
> considered the MSB
> * while B is considered the LSB.
> */
>
> const int32_t EncoderB[] = {+1,-1,-1,+1};
> const int32_t EncoderA[] = {-1,+1,+1,-1};
>
> SIGNAL(SIG_INTERRUPT4) // encoder B for right wheel
> {
> EICRB ^= 0x01; // toggle the edge bit
> RightWheelState ^= 0x01;
> RightWheelCount += EncoderB[RightWheelState];
> }
>
> SIGNAL(SIG_INTERRUPT5) // encoder A for right wheel
> {
> EICRB ^= 0x04;
> RightWheelState ^= 0x02;
> RightWheelCount += EncoderA[RightWheelState];
> }
>
> SIGNAL(SIG_INTERRUPT6) // encoder B for left wheel
> {
> EICRB ^= 0x10;
> LeftWheelState ^= 0x01;
> LeftWheelCount += EncoderB[LeftWheelState];
> }
>
> SIGNAL(SIG_INTERRUPT7) // encoder A for left wheel
> {
> EICRB ^= 0x40;
> LeftWheelState ^= 0x02;
> LeftWheelCount += EncoderA[LeftWheelState];
> }
>
> Each of the 4 interrupt routines toggles the edge selection bit as
> described above. It then keeps track of the current state of the
> encoder and adds/subtracts 1 from the wheel count. Initialization
> code is not shown but it sets the wheel state to the current
levels on
> the pins at startup. Even if this didn't work out, only a single
edge
> would be missed.
>
> I haven't gotten around to doing this with the LPC2148 but there
would
> be a little more code involved with the VIC.
>
> Richard
>
> Thanks Richard, but I prefer one specific device because I
> have 4 channels at 90.000 pluses/second (180.000
edges/second).
>
> I think that NXP need incorporate specific hardware to count
> the pulses from one encoder like dsPIC, or other devices.

Different processor family, but the DSP56F805 (and follow on
series) have 32-bit quadrature decoders built in. Also their
timers can be set up to read quadrature. So I've set up and read
6 channels of quadrature on a single micro. Since these are in
hardware, there's no software overhead. They work up to the
internal IP clock speeds, ie 40 MHz. Differencing for velocity
from a previous read is as easy as reading a different register.
The timers had to be differenced in software. (Just as a further
note on the subject, beyond periodic differencing, I had enough
spare timers to also measure the width of the quadrature pulses,
so I was able to read accurate velocity even when the counts per
time were very low.)

The ones in the DSP are the best I've every used. I've used the
LSI chips before. See also the LS7266.

I've often wondered if I could come up with a design in a cpld
or small fpga if there'd be a market for a selling that or the
IP (Intellectual Property) as a quadrature chip.

Randy
www.newmicros.com

The 2024 Embedded Online Conference