mirror of https://github.com/joan2937/pigpio
177 lines
6.2 KiB
Plaintext
177 lines
6.2 KiB
Plaintext
|
|
<p>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.</p>
|
|
<h3>SETUP</h3>
|
|
<img alt="fritzing diagram" style="width: 200px; height: 300px;"
|
|
src="images/re-fritz.png" align="left" hspace="10">The common
|
|
(centre) terminal should be connected to a Pi ground.
|
|
<p>The A and B terminals may be connected to any spare gpios.</p>
|
|
<p>Here A to gpio18 (P1-12), common to ground (P1-20), B to gpio7
|
|
(P1-26).<br clear="all"></p>
|
|
<p><img src="images/re-photo.jpg" style=
|
|
"width: 400px; height: 300px;" alt="photo of set-up"></p>
|
|
<h3>CODE</h3>
|
|
<code>#include <stdio.h><br>
|
|
<br>
|
|
#include <pigpio.h><br>
|
|
<br>
|
|
/*<br>
|
|
Rotary encoder connections:<br>
|
|
<br>
|
|
Encoder A - gpio
|
|
18 (pin P1-12)<br>
|
|
Encoder B - gpio
|
|
7 (pin P1-26)<br>
|
|
Encoder Common - Pi ground (pin P1-20)<br>
|
|
*/<br>
|
|
<br>
|
|
#define ENCODER_A 18<br>
|
|
#define ENCODER_B 7<br>
|
|
<br>
|
|
static volatile int encoderPos;<br>
|
|
<br>
|
|
/* forward declaration */<br>
|
|
<br>
|
|
void encoderPulse(int gpio, int lev, uint32_t tick);<br>
|
|
<br>
|
|
int main(int argc, char * argv[])<br>
|
|
{<br>
|
|
int pos=0;<br>
|
|
<br>
|
|
if (gpioInitialise()<0) return 1;<br>
|
|
<br>
|
|
gpioSetMode(ENCODER_A, PI_INPUT);<br>
|
|
gpioSetMode(ENCODER_B, PI_INPUT);<br>
|
|
<br>
|
|
/* pull up is needed as encoder common is grounded
|
|
*/<br>
|
|
<br>
|
|
gpioSetPullUpDown(ENCODER_A, PI_PUD_UP);<br>
|
|
gpioSetPullUpDown(ENCODER_B, PI_PUD_UP);<br>
|
|
<br>
|
|
encoderPos = pos;<br>
|
|
<br>
|
|
/* monitor encoder level changes */<br>
|
|
<br>
|
|
gpioSetAlertFunc(ENCODER_A, encoderPulse);<br>
|
|
gpioSetAlertFunc(ENCODER_B, encoderPulse);<br>
|
|
<br>
|
|
while (1)<br>
|
|
{<br>
|
|
if (pos != encoderPos)<br>
|
|
{<br>
|
|
pos =
|
|
encoderPos;<br>
|
|
printf("pos=%d\ ",
|
|
pos);<br>
|
|
}<br>
|
|
gpioDelay(20000); /* check pos 50
|
|
times per second */<br>
|
|
}<br>
|
|
<br>
|
|
gpioTerminate();<br>
|
|
}<br>
|
|
<br>
|
|
void encoderPulse(int gpio, int level, uint32_t tick)<br>
|
|
{<br>
|
|
/*<br>
|
|
<br>
|
|
|
|
+---------+
|
|
+---------+ 0<br>
|
|
|
|
|
|
|
|
|
|
| |<br>
|
|
A
|
|
|
|
|
|
|
|
| |<br>
|
|
|
|
|
|
|
|
|
|
| |<br>
|
|
|
|
+---------+
|
|
+---------+ +-----
|
|
1<br>
|
|
<br>
|
|
|
|
+---------+
|
|
+---------+
|
|
0<br>
|
|
|
|
|
|
|
|
|
|
| |<br>
|
|
B
|
|
|
|
|
|
|
|
| |<br>
|
|
|
|
|
|
|
|
|
|
| |<br>
|
|
----+
|
|
+---------+
|
|
+---------+ 1<br>
|
|
<br>
|
|
*/<br>
|
|
<br>
|
|
static int levA=0, levB=0, lastGpio = -1;<br>
|
|
<br>
|
|
if (gpio == ENCODER_A) levA = level; else levB =
|
|
level;<br>
|
|
<br>
|
|
if (gpio != lastGpio) /* debounce */<br>
|
|
{<br>
|
|
lastGpio = gpio;<br>
|
|
<br>
|
|
if ((gpio == ENCODER_A) &&
|
|
(level == 0))<br>
|
|
{<br>
|
|
if (!levB)
|
|
++encoderPos;<br>
|
|
}<br>
|
|
else if ((gpio == ENCODER_B)
|
|
&& (level == 1))<br>
|
|
{<br>
|
|
if (levA)
|
|
--encoderPos;<br>
|
|
}<br>
|
|
}<br>
|
|
}<br></code>
|
|
<h3>BUILD</h3>
|
|
<code>cc -o rotary_encoder rotary_encoder.c -lpigpio -lrt
|
|
-lpthread<br></code>
|
|
<h3>RUN</h3>
|
|
<code>sudo ./rotary_encoder</code><br>
|
|
<p>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.</p>
|
|
<code>pigs no<br>
|
|
pig2vcd </dev/pigpio0 >re.vcd &<br>
|
|
pigs nb 0 0x40080 # set bits for gpios 7 (0x80) and 18
|
|
(0x40000)<br></code>
|
|
<p>Twiddle the rotary encoder forwards and backwards for a few
|
|
seconds. Then enter<br></p>
|
|
<code>pigs nc 0</code><br>
|
|
<p>The file re.vcd will contain the captured waveform, which can be
|
|
viewed using GTKWave.</p>
|
|
<br>
|
|
Overview<br>
|
|
<br>
|
|
<img src="images/re-wave-1.png" style=
|
|
"width: 600px; height: 100px;" alt=
|
|
"rotary encoder waveform overview"><br>
|
|
<br>
|
|
Detail of switch bounce. Contact A bounces for circa 700 us
|
|
before completing the level transition<br>
|
|
<br>
|
|
<img src="images/re-wave-2.png" style=
|
|
"width: 600px; height: 100px;" alt=
|
|
"rotary encoder waveform detail"><br>
|