||| ArdSimX Articles/Guides Project Archive SimVim Panel Baron-58 sim Forum

Connecting encoders to Arduino

For home cockpits, inexpensive mechanical incremental rotary encoders are typically used. These encoders have two signal outputs and one "common pin". Each signal output is cyclically connected to the "common" with 90 degrees out of phase when the shaft is rotated, i.e. the encoder generates quadrature signal ( see more below on this page about encoder types, detents, resolution etc. ).

In this project the polling of inputs is used to read encoder state changes (i.e. without using interrupts). This method works without problems if the full program loop takes up to 10 msec. The libraries include functions to correctly read encoders of different types (from 1/4 cycle per detent to 1 cycle per detent).

ArdSim / ArdSimX libraries support two methods of encoder connection to Arduino:

  • "Direct" connection, when each device uses its own input pins and the controller reads these inputs for each device independetly.
  • "Bus" connection, when some input pins are combined in one bus that is used as "port" for reading the states of all devices when the controller connects each device to the bus one by one.

You can use both these methods simultaneously in ArdSimX. In previous ArdSim 3..4 versions you could use only one of these connections types at a time for one board.

Bus connection

Each encoder uses only one output of Arduino (the common "C" encoder pin). Two Arduino inputs (#22,23 on this diagram) are used as "bus" for reading all encoder states.

All encoder "phase" pins (A,B) should be connected to this port strictly through diodes to exclude interference and Arduino damage!

Direct connection
Each encoder uses two adjacent pins. Common contacts of all encoders are all attached to the GND, and two "phase" pins are connected to a pair of adjacent Arduino inputs (n, n+1).

No additional components are needed.

Using encoder built-in push button and an external button as encoder mode switch
Built-in button can be used:
  • as simple button for any simulator command, not linked with encoder itself
  • as "push & hold" encoder mode switch (for radio encoders etc.), for example, when Com/Nav encoder is pushed (and held in this position) it adjusts MHz, when not pressed - KHz.
  • as "click" mode switch (for single-knob equipment). The video on the right below shows an ADF with 3-digits - when the button is clicked in a cycle it adjusts "ones", "tens", or "hundreds".

Any external buttons/switches can be used to control encoder modes too. In ArdSimX there is no difference between external and built-in buttons that all count as "external".

Video - Encoder Demo


The difference between ArdSimX and ArdSim bus connection

In ArdSimX library only two Arduino pins are used for encoders as bus, with no additional bus wire for internal buttons. All buttons are configured as external in configurator and can be used with any mode option.

Encoder numbering in the configuration is defined by the number of Arduino pins used for each encoder (E24 means the encoder is connected to pin #24):

In ArdSim library 3 Arduino pins are used for encoders as bus (Port), two of them for encoder phase lines and one additional bus wire for internal buttons. Internal buttons cannot be configured as external.

Encoder numbering starts with 1, in the order the "EncoderPin()" functions are written in the setup section of Arduino code (E1, E2... )

Encoders technical data

There are many types of rotary encoders described in tech literature and on the Internet - absolute and incremental, optical, magnetic, mechanical, binary code, Gray code... an so on.

For home cockpits, inexpensive mechanical incremental rotary encoders are typically used (they are also used nowadays on consumer electronics for volume control etc. instead of potentiometers).

These encoders have only two signal outputs and one "common". Each signal output is cyclically, with 90 degrees out of phase, connected to the "common input" when the shaft is rotated. Thus, the encoder generates quadrature signal (2-bit Gray Code sequence).

The code sequence can be interpreted (by controller or hardware circuit) as direction and velocity.

Commonly, in relation to the simulator, we need to get the moment of status change and the direction it was changed.


For each 360 degrees of rotation the number of full quadrature cycles ( 00-10-11-01) determines resolution of the encoder. Having 20 full cycles (or 20 PPR), for example, the encoder generates 80 changes of state. I.e. we can register up to 80 parameter changes per full turn using appropriate Arduino code for that (resolution = 80 units per rotation). But whether we could use the full resolution or not, depends on such encoder parameter as detents.

Detents and resolution

encoder_wave In detent position the encoder shaft is fixed between rotation steps (switch effect) and eventually this can limit the "fixed" resolution, because within one click of an encoder from 1 to 4 code changes may occur, depending on the number of detents per quadrature cycle - 1, 2 or 4 detents/cycle ( or 1/4, 1/2, 1 cycles or pulses per detent).

If we have encoder with 1 cycle/detent (or one detent per each 4 state change - see encoder #4 below), and in our code each state change is processed with maximum resolution, we can discover that our controlled parameter increments/decrements for 4 units in one click (e.g. 4 degree course stepping)!

It may be acceptable for such parameters as lighting brightness but unusable for course adjustment. For this type of encoder we need to program it for reading states between detents, for determining direction, but take in account only one change per detent (i.e. the whole cycle). Say, using an encoder with resolution 80 state changes (or 80/4 = 20 PPR), and having 20 detents we can actually control HSI OBS by 20 deg/rev. (not 80).

Encoders without detents could have the maximum programmable resolution, but no tactile feedback. Also, encoders with 1/4 cycle per detent have full resolution. For example, if an encoder has 36 detents and 9 cycles/rev (9 PPR), it can generate 36 state changes, i.e. one per each detent.

encoder_waveType 1) Encoder with 1/4 cycle per detent,
or one cycle = 4 detents - (detents 00,10,11,01)

Actual (programmable) resolution is equal to maximum
number of state changes and equal to number
of detents.
encoder_waveType 2) Encoder with 1/2 cycle per detent - (detents 10,01)
- useful (programmable) resolution is half of maximum
resolution and equal to number of detents.

Encoder on right picture has 30 detents, 15 PPR,
60 state (code) changes -->
encoder_waveType 3) Encoder with 1/2 cycle per detent - (detents 00,11)
- useful (programmable) resolution is half of maximum
resolution and equal to number of detents.

Encoder on right picture has 24 detents, 12 PPR,
48 state (code) changes -->
encoder_waveType 4) Encoder with 1 cycle per detent - (detent 00 )
- useful (programmable) resolution is 1/4 of maximal
resolution and equal to number of detents.

Encoders on right picture have
20 and 24 detents and PPR,
80 and 96 state (code) changes -->

Common pin location on different encoders:

Encoders substitutes


As an option you can use a simplified way to emulate encoders - use two buttons or two-way switch - this will be working the same way as we click areas on the screen.... I've made it for my transponder knobs, using two-way springed micro switches taken from old CD-ROMs.


Another way that could be useful for such instruments as Radio Altimeter, etc. - using potentiometer connected to analog input. It lets properly emulate the real knob, when the arrow is rotating correspondingly with rotating knob. See more...

© Copyright 2012-2016 - Vlad Sychev