Rotary encoders experiments – part 2

Here is the second article of the series about reading rotary encoders.

In this section we will explore reading of 15 rotary encoders  with Atmega1284 and Arduino IDE.

15 is the maximum of encoders that can be connected to the microcontroller, considering that we have to keep free some free pins to communicate results outside microcontroller.I chose to keep free the serial port pins PD0(RX) and PD1(TX) equivalent to the D8 si D9 in my Arduino setup. (you can read more about using Atmega1284 with Arduino IDE here).

My choice for the serial port was determined by the ease of connection and debugging.

This module can be used in a larger project or can be used standalone (almost) connecting RX and TX to an USB – MIDI interface like this


The circuit diagram is made with gEDA. Outputs A and B are connected in pairs to the microcontroller ports. Serial port pins D8 and D9 (PD0 and PD1) are connected to J2 header along with VDD and GND.


In the following I will present my experimental setup for this schematic. It is made on a cheap 18x12cm prototype board. It may look ugly but represents the first stage to test the code and see if it really works as expected. This prototype will be the subject of an article on Instructables; there I will detail step by step making of this board.



Here are preview of PCB as has been designed in gEDA suite. It’s almost done but I will not put design files here, before we making first PCB (to be sure that everything is ok). Afterwards, all design files (geda and gerber) will be available to download.




The code is based on finite state-machine (FSM) which was presented in my previous article. Actually I replicated one FSM to 15 (not transition table, only state variables).


The code was written to be achieved two goals:

  • Interruptions to be executed as fast as possible
  • Code to be easily read and understood

I chose to do not make an Arduino library. Even if the module is developed in Arduino is designed as an add-on to an Arduino project. Making a library would be worth to use this module as a shield, not in own firmware module (At least I see this way at this time).

I was in doubt whether to post the whole code in article body, but I tried to comment code as best I could in a way that code complete article text.

Download schematic and code: megaEncoders v1.


Updated: March 19, 2015 — 9:27 am


Add a Comment
  1. I do not how it works but your “transition table” on handling incremental encoder is one of the most clever way that I found. I tried many source code but yours is the most effective.
    In my case was necessary only one encoder and did some modification;

    #define ENC_PHA 13 // (PD5)
    #define ENC_PHB 14 // (PD6)
    #define ENC_SW 2 // (PB2)

    void setupPins (void)
    pinMode (ENC_SW, INPUT_PULLUP);
    pinMode (ENC_PHA, INPUT_PULLUP);
    pinMode (ENC_PHB, INPUT_PULLUP);

    // Enable interrupt for a pin …
    pciSetup (ENC_PHA);
    pciSetup (ENC_PHB);

    void pciSetup (byte pin)
    // Enable pin
    *digitalPinToPCMSK (pin) |= bit (digitalPinToPCMSKbit (pin));
    // Clear any outstanding interrupt
    PCIFR |= bit (digitalPinToPCICRbit (pin));
    // Enable interrupt for the group
    PCICR |= bit (digitalPinToPCICRbit (pin));

    Thank You very much.


    1. And I thank you! 🙂 I’m glad I was helpful.

Leave a Reply to Silvius Cancel reply

Your email address will not be published. Required fields are marked *

OpenHardware.Ro © 2017 Frontier Theme