There has been quite a lot of discussion regarding Quadrature Encoders and Arduino. I have typically used Microchip PIC24 with embedded hardware or added external circuity to off load the cpu. I do want to have example code for class. This is my implementation on an ATMega8 (Dagu Mini Driver) which has only 2 external interrupts.
/*
* Arduino sketch to demonstrate processing quadrature encoded
* pulses on a processor such as the Dago Mini Driver that only
* supports 2 external interrupts.
*
* For this sketch:
*
* Wire the left encoder A signal to pin 2 and B to pin 4.
* Wire the right encoder A signal to pin 3 and B to pin 5.
*
* For speed purposes use the hardware PORT names instead of the
* Arduino builtin pin read functions.
*
* Notes:
* 1. My test jig actually is a Sparkfun AT328P board with hand cranked
* rotary encoder.
* 2. The counts are limited to -128 … +127. If you can possibly overflow
* the signed 8-bit storage either decrease the sample interval or
* change to 16-bit signed integers.
* 3. Make sure that the interrupt does not occur while copying and
* reseting the counters!!
* 4. With only one interput per encoder you do lose half the speed
* resolution but do keep the direction.
* 5. You may need to change the sign on one of the encoder counts for
* dual opposing encoders.
*
* This is free code. No restrictions, no complaints accepted!
*
*/#include <Arduino.h>
#define L 0
#define R 1int8_t count[2][2];
void setup()
{
int
i, j;<span style="color: #008000; font-weight: bold;">for</span> (i <span style="color: #666666;">=</span> <span style="color: #666666;">0</span>; i <span style="color: #666666;"><</span> <span style="color: #666666;">2</span>; i<span style="color: #666666;">++</span>) { <span style="color: #008000; font-weight: bold;">for</span> (j <span style="color: #666666;">=</span> <span style="color: #666666;">0</span>; j <span style="color: #666666;"><</span> <span style="color: #666666;">2</span>; j<span style="color: #666666;">++</span>) count[i][j] <span style="color: #666666;">=</span> <span style="color: #666666;">0</span>; } attachInterrupt(<span style="color: #666666;">0</span>, intrQuadL, CHANGE); attachInterrupt(<span style="color: #666666;">1</span>, intrQuadR, CHANGE); pinMode(<span style="color: #666666;">2</span>, INPUT); pinMode(<span style="color: #666666;">3</span>, INPUT); pinMode(<span style="color: #666666;">4</span>, INPUT); pinMode(<span style="color: #666666;">5</span>, INPUT); Serial.begin(<span style="color: #666666;">115200</span>); delay(<span style="color: #666666;">200</span>);
}
void loop()
{
/*
* Critical Region - Atomic operation must be guarenteed!!!
* 1. Disable interrupts
* 2. Copy ISR counters to working
* 3. Reset ISR counts
* 4. Enable interrupts
*/
noInterrupts();count[L][<span style="color: #666666;">0</span>] <span style="color: #666666;">=</span> count[L][<span style="color: #666666;">1</span>]; count[L][<span style="color: #666666;">1</span>] <span style="color: #666666;">=</span> <span style="color: #666666;">0</span>; count[R][<span style="color: #666666;">0</span>] <span style="color: #666666;">=</span> count[R][<span style="color: #666666;">1</span>]; count[R][<span style="color: #666666;">1</span>] <span style="color: #666666;">=</span> <span style="color: #666666;">0</span>; interrupts(); <span style="color: #408080; font-style: italic;">/*</span>
* Display results using our copy
*/
printByte(count[L][0]);
Serial.print(" ");
printByte(count[R][0]);
Serial.println();delay(<span style="color: #666666;">200</span>);
}
/*
* Lookup table. For speed purposes I am using 3 bits but bit 1 is always
* 0 so states 2,3,6,7 can never happen. With a little more work in the
* ISR you could reduce the table to 4 entries. It is also possible to
* rework the ISR to use SWITCH or IF constructs.
*/
const int8_t quadDelta[8] = {-1, 1, 0, 0, 1, -1, 0, 0};/*
* Left Quadratue Decoder ISR
*/
void intrQuadL(void)
{
register uint8_t
i;i <span style="color: #666666;">=</span> (PIND <span style="color: #666666;">>></span> <span style="color: #666666;">2</span>) <span style="color: #666666;">&</span> <span style="color: #666666;">0x05</span>; <span style="color: #408080; font-style: italic;">// isolate bits of interest</span> count[L][<span style="color: #666666;">1</span>] <span style="color: #666666;">+=</span> quadDelta[i];
}
/*
* Right Quadratue Decoder ISR
*/
void intrQuadR(void)
{
register uint8_t
i;i <span style="color: #666666;">=</span> (PIND <span style="color: #666666;">>></span> <span style="color: #666666;">3</span>) <span style="color: #666666;">&</span> <span style="color: #666666;">0x05</span>; count[R][<span style="color: #666666;">1</span>] <span style="color: #666666;">+=</span> quadDelta[i];
}
void printByte(int8_t n)
{
uint8_t
k;k <span style="color: #666666;">=</span> abs(n); <span style="color: #008000; font-weight: bold;">if</span> (k <span style="color: #666666;"><</span> <span style="color: #666666;">100</span>) Serial.print(<span style="color: #ba2121;">" "</span>); <span style="color: #008000; font-weight: bold;">if</span> (k <span style="color: #666666;"><</span> <span style="color: #666666;">10</span>) Serial.print(<span style="color: #ba2121;">" "</span>); <span style="color: #008000; font-weight: bold;">if</span> (n <span style="color: #666666;">>=</span> <span style="color: #666666;">0</span>) Serial.print(<span style="color: #ba2121;">" "</span>); Serial.print(n);
}