The following code shows one way to read an incremental mechanical rotary enoder (the sort used for volume control in audio systems). These rotary encoders have two switches A and B which return a quadrature output, i.e. they are 90 degrees out of phase.

### SETUP

The common (centre) terminal should be connected to a Pi ground.

The A and B terminals may be connected to any spare gpios.

Here A to gpio18 (P1-12), common to ground (P1-20), B to gpio7 (P1-26).

### CODE

`#include <stdio.h>
#include <pigpio.h>
/*
Rotary encoder connections:
Encoder A - gpio 18 (pin P1-12)
Encoder B - gpio 7 (pin P1-26)
Encoder Common - Pi ground (pin P1-20)
*/
#define ENCODER_A 18
#define ENCODER_B 7
static volatile int encoderPos;
/* forward declaration */
void encoderPulse(int gpio, int lev, uint32_t tick);
int main(int argc, char * argv[])
{
int pos=0;
if (gpioInitialise()<0) return 1;
gpioSetMode(ENCODER_A, PI_INPUT);
gpioSetMode(ENCODER_B, PI_INPUT);
/* pull up is needed as encoder common is grounded */
gpioSetPullUpDown(ENCODER_A, PI_PUD_UP);
gpioSetPullUpDown(ENCODER_B, PI_PUD_UP);
encoderPos = pos;
/* monitor encoder level changes */
gpioSetAlertFunc(ENCODER_A, encoderPulse);
gpioSetAlertFunc(ENCODER_B, encoderPulse);
while (1)
{
if (pos != encoderPos)
{
pos = encoderPos;
printf("pos=%d\ ", pos);
}
gpioDelay(20000); /* check pos 50 times per second */
}
gpioTerminate();
}
void encoderPulse(int gpio, int level, uint32_t tick)
{
/*
+---------+ +---------+ 0
| | | |
A | | | |
| | | |
+---------+ +---------+ +----- 1
+---------+ +---------+ 0
| | | |
B | | | |
| | | |
----+ +---------+ +---------+ 1
*/
static int levA=0, levB=0, lastGpio = -1;
if (gpio == ENCODER_A) levA = level; else levB = level;
if (gpio != lastGpio) /* debounce */
{
lastGpio = gpio;
if ((gpio == ENCODER_A) && (level == 0))
{
if (!levB) ++encoderPos;
}
else if ((gpio == ENCODER_B) && (level == 1))
{
if (levA) --encoderPos;
}
}
}
`

### BUILD

`cc -o rotary_encoder rotary_encoder.c -lpigpio -lrt -lpthread
`

### RUN

`sudo ./rotary_encoder`

While the program is running you can capture the waveform using the notification feature built in to pigpio. Issue the following commands on the Pi.

`pigs no
pig2vcd </dev/pigpio0 >re.vcd &
pigs nb 0 0x40080 # set bits for gpios 7 (0x80) and 18 (0x40000)
`

Twiddle the rotary encoder forwards and backwards for a few seconds. Then enter

`pigs nc 0`

The file re.vcd will contain the captured waveform, which can be viewed using GTKWave.

Overview
Detail of switch bounce. Contact A bounces for circa 700 us before completing the level transition