# Reading 10K positions from a 2.5K rotary encoder

**URL:** <https://community.sparkfun.com/t/reading-10k-positions-from-a-2-5k-rotary-encoder/14505>\
**Category:** MicroMod\
**Tags:** avr-atmel\
**Created:** [February 14, 2010, 10:00pm UTC](https://community.sparkfun.com/t/reading-10k-positions-from-a-2-5k-rotary-encoder/14505 "2010-02-14T22:00:48Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![rst26508](https://avatars.discourse-cdn.com/v4/letter/r/ac91a4/32.png) [@rst26508](https://community.sparkfun.com/u/rst26508)\
**Post date:** [February 14, 2010, 10:00pm UTC](https://community.sparkfun.com/t/reading-10k-positions-from-a-2-5k-rotary-encoder/14505/1 "2010-02-14T22:00:48Z")

</div>

I been playing with a US Digital Optical Encoders (S2-2500-250-I-N-D - superceeded bvy [http://www.usdigital.com/assets/general … heet\_3.pdf](http://www.usdigital.com/assets/general/82_s6_datasheet_3.pdf)

I’ve done some testing with a 5V mini-pro and am currently using a Mega.

The encoder has an index line which helps get an absolute position.

By sensing a change of state each of the A and B lines I can get 10k positions out of the encoder. At a fast hand turn speed the accuracy drops off (some missed steps) but for slow fine control it’s great.

/\*

- Basic Rotary Encoder reader.

\*/

const int Channel\_a = 2;

const int Channel\_b = 3;

const int IndexPin = 21;

int StepCount = 0;

int Ch\_a\_state;

int Ch\_b\_state;

int Index\_state;

int LastCount = 0;

void StateChange0() {

Ch\_a\_state = digitalRead(Channel\_a);

Ch\_b\_state = digitalRead(Channel\_b);

Index\_state = digitalRead(IndexPin);

if ( Ch\_a\_state == Ch\_b\_state ) ++StepCount;

else --StepCount;

}

void StateChange1() {

Ch\_a\_state = digitalRead(Channel\_a);

Ch\_b\_state = digitalRead(Channel\_b);

Index\_state = digitalRead(IndexPin);

if ( Ch\_a\_state != Ch\_b\_state ) ++StepCount;

else --StepCount;

}

void StateChange2() {

Index\_state = digitalRead(IndexPin);

// if ( Index\_state != LOW )

Serial.println(“Index pin state change”);

Serial.print("StepCount is ");

Serial.println(StepCount);

StepCount = 0;

}

void setup()

{

pinMode(Channel\_a, INPUT);

pinMode(Channel\_a, INPUT);

pinMode(IndexPin, INPUT);

attachInterrupt(0, StateChange0, CHANGE);

attachInterrupt(1, StateChange1, CHANGE);

attachInterrupt(2, StateChange2, RISING);

Serial.begin(9600);

}

void loop()

{

if ( StepCount != LastCount )

{

Serial.print("Changing Position to ");

Serial.println(StepCount);

LastCount = StepCount;

}

delay(100);

}

---

<div class="post-metadata">

**Author:** ![Liencouer](https://avatars.discourse-cdn.com/v4/letter/l/dbc845/32.png) [@Liencouer](https://community.sparkfun.com/u/Liencouer)\
**Post date:** [February 15, 2010, 1:22pm UTC](https://community.sparkfun.com/t/reading-10k-positions-from-a-2-5k-rotary-encoder/14505/2 "2010-02-15T13:22:58Z")

</div>

if you needed to maintain accurate counts and get a faster shaft speed, you can always use the internal timer/counter modules to do the pulse counting for you. I dont know if the arduino ide supports that - you could probably find some c examples fairly easily enough.

---

<div class="post-metadata">

**Author:** ![rst26508](https://avatars.discourse-cdn.com/v4/letter/r/ac91a4/32.png) [@rst26508](https://community.sparkfun.com/u/rst26508)\
**Post date:** [February 17, 2010, 11:28am UTC](https://community.sparkfun.com/t/reading-10k-positions-from-a-2-5k-rotary-encoder/14505/3 "2010-02-17T11:28:16Z")

</div>

Liencouer thanks for that. I’m having a play with direct reading of the ports and some bit manipulation to see if that improves the performance. A few lessons to learn along the way with that but I’m making progress.

The code as it now stands -

/\*

- Basic Rotary Encoder reader.

\*/

#define Ch\_a\_state (PINE & (1\<\<4))\>\>4

#define Ch\_b\_state (PINE & (1\<\<5))\>\>5

#define Index\_state (PIND & (1\<\<0))

// Channel\_a = 2;

// Channel\_b = 3;

// IndexPin = 21;

int StepCount = 0;

int LastCount = 0;

void StateChange0() {

if ( Ch\_a\_state == Ch\_b\_state ) ++StepCount;

else --StepCount;

}

void StateChange1() {

if ( Ch\_a\_state != Ch\_b\_state ) ++StepCount;

else --StepCount;

}

void StateChange2() {

// if ( PIND & (1\<\<0) )

// Serial.println(“Index pin state change”);

// Serial.print("StepCount is ");

Serial.println(StepCount);

StepCount = 0;

}

void setup()

{

// Not sure how to do the next two lines’s with defines (or const’s) to make them more portable.

// Setup for the encoder rotation and index channels

DDRE = DDRE & B11001111;

DDRD = DDRD & B11111110;

attachInterrupt(0, StateChange0, CHANGE);

attachInterrupt(1, StateChange1, CHANGE);

attachInterrupt(2, StateChange2, RISING);

Serial.begin(9600);

}

void loop()

{

if ( StepCount != LastCount )

{

Serial.print("Changing Position to ");

Serial.println(StepCount);

LastCount = StepCount;

}

delay(300);

}

---

<div class="post-metadata">

**Author:** ![monstrum](https://avatars.discourse-cdn.com/v4/letter/m/b2d939/32.png) [@monstrum](https://community.sparkfun.com/u/monstrum)\
**Post date:** [February 17, 2010, 12:44pm UTC](https://community.sparkfun.com/t/reading-10k-positions-from-a-2-5k-rotary-encoder/14505/4 "2010-02-17T12:44:56Z")

</div>

From what I can see, you are sending serial debug-messages from inside each state-change routine. That is the limiting factor in your case, no matter how you detect the pulses.

So, remove the serial printing, and do that in the main loop instead.

---

<div class="post-metadata">

**Author:** ![Liencouer](https://avatars.discourse-cdn.com/v4/letter/l/dbc845/32.png) [@Liencouer](https://community.sparkfun.com/u/Liencouer)\
**Post date:** [February 19, 2010, 12:50am UTC](https://community.sparkfun.com/t/reading-10k-positions-from-a-2-5k-rotary-encoder/14505/5 "2010-02-19T00:50:40Z")

</div>

```auto
// Not sure how to do the next two lines's with defines (or const's) to make them more portable.
// Setup for the encoder rotation and index channels
DDRE = DDRE & B11001111;
DDRD = DDRD & B11111110;

```

can look something like

```auto
 #define BIT0 0
#define BIT4 4
#define BIT5 5
DDRE &= ~((1<<BIT4) | (1<<BIT5)); // will clear bits 4 and 5 of DDRE
DDRD &= ~(1<<BIT0); // will clear bit 0 of DDRD

```

and you can name BIT0 to something more descriptive, if you feel so inclined

recommended reading: [http://www.avrfreaks.net/index.php?name … ic&t=37871](http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=37871)

---

<div class="post-metadata">

**Author:** ![rst26508](https://avatars.discourse-cdn.com/v4/letter/r/ac91a4/32.png) [@rst26508](https://community.sparkfun.com/u/rst26508)\
**Post date:** [February 22, 2010, 9:21am UTC](https://community.sparkfun.com/t/reading-10k-positions-from-a-2-5k-rotary-encoder/14505/6 "2010-02-22T09:21:37Z")

</div>

monstrum and Liencouer thank you both for the additional comments. It’s much more reliable now. The next step will be to hook up two encoders and see how it goes.

Bob
