Quadrature RPM algorithm

polarmystery

Diamond Member
Aug 21, 2005
3,888
8
81
Hey guys,

I'm having trouble coming up with an algorithm for my micro-controller to measure pulses on a timer in a quadrature decoder. What it is supposed to do is count the number of times BitRdPortI(PFDR, 0) == TRUE and record is as a rotational rate but the way I have it is incorrect. What it does now is simply count up forever while the port is TRUE.

The Quad decoder if you are unfamiliar with it counts from 0 to 3 in binary (IE: 00-> 11 and it rolls over after that) and there are two port pins that contain the changing bits. If I poll a port (let's say I use the right-most bit to count 1's), it will simply count up until it's at 0 while staying in that loop, but I need it to count all the pulses when they change (IE: if it's counting the right-most bit, it should read 2 if I cycle through all positions) until count reaches 100. Any ideas? It should be simple, but I can't put my finger on what it should be. Thanks in advance! Here is my crappy code snippet thus far:

Code:
void velocity()
{
   int count;
   count = 0;

       while(count < 100)
      {
         if (BitRdPortI(PFDR, 0) == TRUE)
          rate++;
      }
   }
   printf(" Ticks per second %d \n",rate);
   printf("\x1Bt");
}
 

esun

Platinum Member
Nov 12, 2001
2,214
0
0
You want an edge detector, which requires state. The condition you want is not that X == TRUE (let X be the signal in question). Rather, you want to count up when the CURRENT value of X == TRUE and the PREVIOUS value of X == FALSE, meaning you got a rising edge. I'll let you figure out how the code for that looks.
 

polarmystery

Diamond Member
Aug 21, 2005
3,888
8
81
You want an edge detector, which requires state. The condition you want is not that X == TRUE (let X be the signal in question). Rather, you want to count up when the CURRENT value of X == TRUE and the PREVIOUS value of X == FALSE, meaning you got a rising edge. I'll let you figure out how the code for that looks.

If I did that, because the code polls continuously, I'd get the same results no?
 

Leros

Lifer
Jul 11, 2004
21,867
7
81
You should be doing this via interrupts, not polling. What chip are using?
 

Colt45

Lifer
Apr 18, 2001
19,720
1
0
If you want to poll it, you'll need something like this

Code:
	while(count < 100)
	{
		oldstate = state;
		state = (BitRdPortI(PFDR, 0);
		if(state != oldstate) //state has changed
			rate++;
	}

This doesn't account for rising/falling, it will trigger on either, so you need to modify it a bit if you only want it on one edge.

But unless you are using some archaic thing, or badly planned your board and got stuck with a signal on a pin with no interrupts... interrupts are really the way to go here.

(ps - your loop never increases 'count', so it will never exit ... unless it's incremented in an interrupt routine.)

Or am I misunderstanding your question..? Are you trying to count pulses, or measure their length?
 
May 11, 2008
23,331
1,575
126
If you are using a quadrature encoder, then what you have is that on the rising edge of one pin, the other pin will be low or high depending on the direction.
The easiest way in software is to indeed use an interrupt for this. The interrupt triggers on the rising edge. And in the interrupt service routine you count the amount of interrupts you had (just +1); and you check the level of the other pin to find out the direction. For example clockwise can be a high level and counter clockwise can be a low level. Then you can use averaging filters (in software) to filter out glitches if needed. This last sentence sounds difficult but it is just using variables as counters and checking these counters on a fixed repetition period for a certain threshold value.


encoder-phase.gif



If you insist on not using an interrupt, you are best of to use a little bit of hardware. A so called D-flipflop will store the direction for you. An averaging algorithm polling the clk input pin (which is also connected to the quadrature encoder)of the d flipflop will determine an averaged but rough count. The output of the flipflop will hold directional information in the same way as described as above. Because the output will follow the d input pin when the clk pin is experiencing a rising edge.

quadrature_decoder_0.gif



This is a most simple explanation where i omitted a lot of secondary information. But it will do. And give you a rough idea. :)


I used the hardware version once for rotary buttons with quadrature encoders in them. But i also used the interrupt version. For motor encoders, you really need interrupts or you are going to have problems determining the angle of the motor shaft...


P.S.

If you only need rpm, you need only one pin but i will let you figure it out yourself. ^_^


EDIT:

One more picture for clarity :

01384x02.png
 
Last edited:

polarmystery

Diamond Member
Aug 21, 2005
3,888
8
81
You should be doing this via interrupts, not polling. What chip are using?

A Rabbit 3000A. I know I should be using interrupts, but I suck coding them.

Edit: Nevermind. I got it to work. I tied an interrupt pin to one of the legs of the Quad Decoder and it worked great.

Sometimes...I need to step back and take a deep breath. I tend to freak out too much *sigh* :(
 
Last edited:

polarmystery

Diamond Member
Aug 21, 2005
3,888
8
81
If you want to poll it, you'll need something like this

Code:
    while(count < 100)
    {
        oldstate = state;
        state = (BitRdPortI(PFDR, 0);
        if(state != oldstate) //state has changed
            rate++;
    }
This doesn't account for rising/falling, it will trigger on either, so you need to modify it a bit if you only want it on one edge.

But unless you are using some archaic thing, or badly planned your board and got stuck with a signal on a pin with no interrupts... interrupts are really the way to go here.

(ps - your loop never increases 'count', so it will never exit ... unless it's incremented in an interrupt routine.)

Or am I misunderstanding your question..? Are you trying to count pulses, or measure their length?

I was trying to count pulses, so I ended up using an external interrupt pin as mentioned above. It's not intuitive for me to use interrupts for some reason, but it worked great.
 

Leros

Lifer
Jul 11, 2004
21,867
7
81
A Rabbit 3000A. I know I should be using interrupts, but I suck coding them.

Edit: Nevermind. I got it to work. I tied an interrupt pin to one of the legs of the Quad Decoder and it worked great.

Sometimes...I need to step back and take a deep breath. I tend to freak out too much *sigh* :(

Hahaha, it had a quadrature decoder the whole time :p

That's a pretty cool chip. The six SCI ports are pretty handy. I've never seen a chip with more than 2.
 

Modelworks

Lifer
Feb 22, 2007
16,240
7
76
Hahaha, it had a quadrature decoder the whole time :p

That's a pretty cool chip. The six SCI ports are pretty handy. I've never seen a chip with more than 2.

I use a lot of the microchip pic chips and they have a bunch of them with quad decoders. They have a lot of chips with good features especially for motor control. This one sells for about $5 and includes everything from motor control to CAN networking for cars, to an audo DAC for sound. It is amazing what you can get for $5 now.
http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en532303

. Up to 40 MIPS operation (at 3.0-3.6V):
. Modified Harvard architecture
. C compiler optimized instruction set
. 16-bit wide data path
. 24-bit wide instructions
. Linear program memory addressing up to 4M instruction words
. Linear data memory addressing up to 64 Kbytes
. 83 base instructions: mostly 1 word/1 cycle
. Two 40-bit accumulators with rounding and saturation options
. Flexible and powerful addressing modes:
- Indirect
- Modulo
- Bit-Reversed
. Software stack
. 16 x 16 fractional/integer multiply operations
. 32/16 and 16/16 divide operations
. Single-cycle multiply and accumulate:
- Accumulator write back for DSP operations
- Dual data fetch
. Up to &#177;16-bit shifts for up to 40-bit data
On-Chip Flash and SRAM:
. Flash program memory
. Data SRAM
. Boot, Secure, and General Security for program Flash
Direct Memory Access (DMA):
. 8-channel hardware DMA
. Up to 2 Kbytes dual ported DMA buffer area (DMA RAM) to store data transferred via DMA:
- Allows data transfer between RAM and a peripheral while CPU is executing code (no cycle stealing)

Timers/Capture/Compare/PWM:
. Timer/Counters, up to five 16-bit timers:
- Can pair up to make two 32-bit timers
- One timer runs as a Real-Time Clock with an external 32.768 kHz oscillator
- Programmable prescaler
. Input Capture (up to four channels):
- Capture on up, down or both edges
- 16-bit capture input functions
- 4-deep FIFO on each capture
. Output Compare (up to four channels):
- Single or Dual 16-bit Compare mode
- 16-bit Glitchless PWM mode
. Hardware Real-Time Clock/Calendar (RTCC):
- Provides clock, calendar, and alarm functions

Interrupt Controller:
. 5-cycle latency
. 118 interrupt vectors
. Up to 53 available interrupt sources
. Up to three external interrupts
. Seven programmable priority levels
. Five processor exceptions

Digital I/O:
. Peripheral pin Select functionality
. Up to 35 programmable digital I/O pins
. Wake-up/Interrupt-on-Change for up to 21 pins
. Output pins can drive from 3.0V to 3.6V
. Up to 5V output with open drain configuration
. All digital input pins are 5V tolerant
. 4 mA sink on all I/O pins


Power Management:
. On-chip 2.5V voltage regulator
. Switch between clock sources in real time
. Idle, Sleep, and Doze modes with fast wake-up

Analog-to-Digital Converters (ADCs):
. 10-bit, 1.1 Msps or 12-bit, 500 Ksps conversion:
- Two and four simultaneous samples (10-bit ADC)
- Up to nine input channels with auto-scanning
- Conversion start can be manual or synchronized with one of four trigger sources
- Conversion possible in Sleep mode
- &#177;2 LSb max integral nonlinearity
- &#177;1 LSb max differential nonlinearity

Audio Digital-to-Analog Converter (DAC):
- 16-bit Dual Channel DAC module
- 100 Ksps maximum sampling rate
- Second-Order Digital Delta-Sigma Modulator

Comparator Module:
. Two analog comparators with programmable input/output configuration

Motor Control Peripherals:
. 6-channel 16-bit Motor Control PWM:
- Three duty cycle generators
- Independent or Complementary mode
- Programmable dead time and output polarity
- Edge-aligned or center-aligned
- Manual output override control
- One Fault input
- Trigger for ADC conversions
- PWM frequency for 16-bit resolution (@ 40 MIPS) = 1220 Hz for Edge-Aligned mode, 610 Hz for Center-Aligned mode
- PWM frequency for 11-bit resolution (@ 40 MIPS) = 39.1 kHz for Edge-Aligned mode, 19.55 kHz for Center-Aligned mode
. 2-channel 16-bit Motor Control PWM:
- One duty cycle generator
- Independent or Complementary mode
- Programmable dead time and output polarity
- Edge-aligned or center-aligned
- Manual output override control
- One Fault input
- Trigger for ADC conversions
- PWM frequency for 16-bit resolution (@ 40 MIPS) = 1220 Hz for Edge-Aligned mode, 610 Hz for Center-Aligned mode
- PWM frequency for 11-bit resolution (@ 40 MIPS) = 39.1 kHz for Edge-Aligned mode, 19.55 kHz for Center-Aligned mode

. 2-Quadrature Encoder Interface module:
- Phase A, Phase B, and index pulse input
- 16-bit up/down position counter
- Count direction status
- Position Measurement (x2 and x4) mode
- Programmable digital noise filters on inputs
- Alternate 16-bit Timer/Counter mode
- Interrupt on position counter rollover/underflow

Communication Modules:
. 4-wire SPI (up to two modules):
- Framing supports I/O interface to simple codecs
- Supports 8-bit and 16-bit data
- Supports all serial clock formats and sampling modes

. I2C&#8482; :
- Full Multi-Master Slave mode support
- 7-bit and 10-bit addressing
- Bus collision detection and arbitration
- Integrated signal conditioning
- Slave address masking

. UART (up to two modules):
- Interrupt on address bit detect
- Interrupt on UART error
- Wake-up on Start bit from Sleep mode
- 4-character TX and RX FIFO buffers
- LIN bus support
- IrDA&#174; encoding and decoding in hardware
- High-Speed Baud mode
- Hardware Flow Control with CTS and RTS

. Enhanced CAN (ECAN. module) 2.0B active:
- Up to eight transmit and up to 32 receive buffers
- 16 receive filters and three masks
- Loopback, Listen Only and Listen All
- Messages modes for diagnostics and bus monitoring
- Wake-up on CAN message
- Automatic processing of Remote Transmission Requests
- FIFO mode using DMA
- DeviceNet. addressing support

. Parallel Master Slave Port (PMP/EPSP):
- Supports 8-bit or 16-bit data
- Supports 16 address lines
. Programmable Cyclic Redundancy Check (CRC):
- Programmable bit length for the CRC generator polynomial (up to 16-bit length)
- 8-deep, 16-bit or 16-deep, 8-bit FIFO for data input
 
Last edited: