mirror of https://github.com/joan2937/pigpio
309 lines
11 KiB
HTML
309 lines
11 KiB
HTML
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
|
<head>
|
|
<meta name="description" content="Raspberry Pi Reg. C GPIO library and Python GPIO module and shell command utilities to control the GPIO, including SPI, I2C, and serial links." />
|
|
<meta name="keywords" content="raspberry, pi, C, Python, GPIO, library, shell, command, utilities, module, SPI, I2C, serial" />
|
|
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
|
<title>pigpio library</title>
|
|
<link rel="stylesheet" type="text/css" href="scripts/index.css">
|
|
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
|
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
|
</head>
|
|
<body>
|
|
|
|
<table style="padding:0px; border:0px; margin:0px; width:780px; background-color:#e0e0e0;">
|
|
<td style="background:#EAF2E6 url('images/sidebar.gif') repeat-y; width:35px; height:100%"></td>
|
|
<td>
|
|
<table>
|
|
<div style="background:url('images/topbar.gif') repeat-x; height: 70px; font-size:1.5em; vertical-align: top;"><a href="index.html"><img src="images/pigpio-logo.gif" border="0" /></a>pigpio library</div>
|
|
</table>
|
|
<table><div>
|
|
<td><img src="images/driver.jpg" width="250"></td>
|
|
<td><img src="images/imu-3.jpg" width="250"></td>
|
|
<td><img src="images/ir-motion.jpg" width="250"></td>
|
|
</div></table>
|
|
<table>
|
|
<td style="vertical-align: top; background-color: #98bf21;"><a class="l1" href="index.html">pigpio</a>
|
|
<a class="l1" href="cif.html">pigpio C I/F</a>
|
|
<a class="l1" href="pigpiod.html">pigpiod</a>
|
|
<a class="l1" href="pdif2.html">pigpiod C I/F</a>
|
|
<a class="l1" href="python.html">Python</a>
|
|
<a class="l1" href="pigs.html">pigs</a>
|
|
<a class="l1" href="piscope.html">piscope</a>
|
|
<a class="l1" href="misc.html">Misc</a>
|
|
<a class="l1" href="examples.html">Examples</a>
|
|
<a class="l1" href="download.html">Download</a>
|
|
<a class="l1" href="faq.html">FAQ</a>
|
|
<a class="l1" href="sitemap.html">Site Map</a>
|
|
</td>
|
|
<td><center><h2>IR Remote Example</h2></center>
|
|
<p>The following code shows one way to read an infrared remote
|
|
control device (the sort used in TVs and stereo systems).</p>
|
|
<h3>SETUP</h3>
|
|
<img alt="fritzing diagram" style="width: 200px; height: 317px;"
|
|
src="images/ir-fritz.png" align="left" hspace="10">The device used
|
|
is a <span itemprop="name">SFH5110 (IR Receiver for remote control,
|
|
carrier 38 kHz).<br>
|
|
<br></span> Pin 1 (left from front) may be connected to any spare
|
|
gpio. Here it's connected via a 4K7 current limiting
|
|
resistor. This isn't really needed as the device has an
|
|
internal 23K resistor in-line. It does no harm though.<br>
|
|
<br>
|
|
Pin 2 should be connected to a Pi ground pin.<br>
|
|
<br>
|
|
Pin 3 should be connected to a Pi 5V pin.<br>
|
|
<p>Here pin 1 to gpio7 (P1-26) via a 4K7 resistor, pin 2 to ground
|
|
(P1-14), and pin 3 to 5V (P1-2).<br clear="all"></p>
|
|
<p><img src="images/ir-photo.jpg" style=
|
|
"width: 500px; height: 500px;" alt="photo of set-up"></p>
|
|
<h3>CODE</h3>
|
|
<code>#include <stdio.h><br>
|
|
<br>
|
|
#include <pigpio.h><br>
|
|
<br>
|
|
#define IR_PIN 7<br>
|
|
<br>
|
|
#define OUTSIDE_CODE 0<br>
|
|
#define INSIDE_CODE 1<br>
|
|
<br>
|
|
#define MIN_MESSAGE_GAP 3000<br>
|
|
#define MAX_MESSAGE_END 3000<br>
|
|
<br>
|
|
#define MAX_TRANSITIONS 500<br>
|
|
<br>
|
|
/*<br>
|
|
using the FNV-1a
|
|
hash <br>
|
|
|
|
from
|
|
http://isthe.com/chongo/tech/comp/fnv/#FNV-param<br>
|
|
*/<br>
|
|
<br>
|
|
#define FNV_PRIME_32 16777619<br>
|
|
#define FNV_BASIS_32 2166136261U<br>
|
|
<br>
|
|
static volatile uint32_t ir_hash = 0;<br>
|
|
<br>
|
|
typedef struct<br>
|
|
{<br>
|
|
int state;<br>
|
|
int count;<br>
|
|
int level;<br>
|
|
uint16_t micros[MAX_TRANSITIONS];<br>
|
|
} decode_t;<br>
|
|
<br>
|
|
/* forward declarations */<br>
|
|
<br>
|
|
void alert(int gpio, int level, uint32_t
|
|
tick);<br>
|
|
uint32_t getHash(decode_t * decode);<br>
|
|
void updateState(decode_t * decode, int
|
|
level, uint32_t micros);<br>
|
|
<br>
|
|
int main(int argc, char * argv[])<br>
|
|
{<br>
|
|
if (gpioInitialise()<0)<br>
|
|
{<br>
|
|
return 1 ;<br>
|
|
}<br>
|
|
<br>
|
|
/* IR pin as input */<br>
|
|
<br>
|
|
gpioSetMode(IR_PIN, PI_INPUT);<br>
|
|
<br>
|
|
/* 5ms max gap after last pulse */<br>
|
|
<br>
|
|
gpioSetWatchdog(IR_PIN, 5);<br>
|
|
<br>
|
|
/* monitor IR level changes */<br>
|
|
<br>
|
|
gpioSetAlertFunc(IR_PIN, alert);<br>
|
|
<br>
|
|
while (1)<br>
|
|
{<br>
|
|
if (ir_hash)<br>
|
|
{<br>
|
|
/* non-zero means
|
|
new decode */<br>
|
|
printf("ir code is
|
|
%u\ ", ir_hash);<br>
|
|
ir_hash = 0;<br>
|
|
}<br>
|
|
<br>
|
|
gpioDelay(100000); /* check remote
|
|
10 times per second */<br>
|
|
}<br>
|
|
<br>
|
|
gpioTerminate();<br>
|
|
}<br>
|
|
<br>
|
|
void alert(int gpio, int level, uint32_t tick)<br>
|
|
{<br>
|
|
static int inited = 0;<br>
|
|
<br>
|
|
static decode_t activeHigh, activeLow;<br>
|
|
<br>
|
|
static uint32_t lastTick;<br>
|
|
<br>
|
|
uint32_t diffTick;<br>
|
|
<br>
|
|
if (!inited)<br>
|
|
{<br>
|
|
inited = 1;<br>
|
|
<br>
|
|
activeHigh.state = OUTSIDE_CODE;
|
|
activeHigh.level = PI_LOW;<br>
|
|
activeLow.state =
|
|
OUTSIDE_CODE; activeLow.level = PI_HIGH;<br>
|
|
<br>
|
|
lastTick = tick;<br>
|
|
return;<br>
|
|
}<br>
|
|
<br>
|
|
diffTick = tick - lastTick;<br>
|
|
<br>
|
|
if (level != PI_TIMEOUT) lastTick = tick;<br>
|
|
<br>
|
|
updateState(&activeHigh, level, diffTick);<br>
|
|
updateState(&activeLow, level, diffTick);<br>
|
|
}<br>
|
|
<br>
|
|
void updateState(decode_t * decode, int level, uint32_t micros)<br>
|
|
{<br>
|
|
/*<br>
|
|
We are dealing with active high as
|
|
well as active low<br>
|
|
remotes. Abstract the common
|
|
functionality.<br>
|
|
*/<br>
|
|
<br>
|
|
if (decode->state == OUTSIDE_CODE)<br>
|
|
{<br>
|
|
if (level == decode->level)<br>
|
|
{<br>
|
|
if (micros >
|
|
MIN_MESSAGE_GAP)<br>
|
|
{<br>
|
|
|
|
decode->state = INSIDE_CODE;<br>
|
|
|
|
decode->count = 0;<br>
|
|
}<br>
|
|
}<br>
|
|
}<br>
|
|
else<br>
|
|
{<br>
|
|
if (micros > MAX_MESSAGE_END)<br>
|
|
{<br>
|
|
/* end of message
|
|
*/<br>
|
|
<br>
|
|
/* ignore if last
|
|
code not consumed */<br>
|
|
<br>
|
|
if (!ir_hash)
|
|
ir_hash = getHash(decode);<br>
|
|
<br>
|
|
decode->state =
|
|
OUTSIDE_CODE;<br>
|
|
}<br>
|
|
else<br>
|
|
{<br>
|
|
if
|
|
(decode->count < (MAX_TRANSITIONS-1))<br>
|
|
{<br>
|
|
|
|
if (level != PI_TIMEOUT)<br>
|
|
|
|
decode->micros[decode->count++] = micros;<br>
|
|
}<br>
|
|
}<br>
|
|
}<br>
|
|
}<br>
|
|
<br>
|
|
int compare(unsigned int oldval, unsigned int newval)<br>
|
|
{<br>
|
|
if (newval < (oldval
|
|
* 0.75)) {return 1;}<br>
|
|
else if (oldval < (newval * 0.75)) {return 2;}<br>
|
|
|
|
else
|
|
{return 4;}<br>
|
|
}<br>
|
|
<br>
|
|
uint32_t getHash(decode_t * decode)<br>
|
|
{<br>
|
|
/* use FNV-1a */<br>
|
|
<br>
|
|
uint32_t hash;<br>
|
|
int i, value;<br>
|
|
<br>
|
|
if (decode->count < 6) {return 0;}<br>
|
|
<br>
|
|
hash = FNV_BASIS_32;<br>
|
|
<br>
|
|
for (i=0; i<(decode->count-2); i++)<br>
|
|
{<br>
|
|
value =
|
|
compare(decode->micros[i], decode->micros[i+2]);<br>
|
|
<br>
|
|
hash = hash ^ value;<br>
|
|
hash = (hash * FNV_PRIME_32);<br>
|
|
}<br>
|
|
<br>
|
|
return hash;<br>
|
|
}<br></code>
|
|
<h3>BUILD</h3>
|
|
<code>cc -o ir_remote ir_remote.c -lpigpio -lrt
|
|
-lpthread<br></code>
|
|
<h3>RUN</h3>
|
|
<code>sudo ./ir_remote</code><br>
|
|
<p>A hash code is formed from the level transitions detected during
|
|
a remote key press. This is likely to be unique over multiple
|
|
remotes and keys.</p>
|
|
<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 >ir.vcd &<br>
|
|
pigs nb 0 0x80 # set bits for gpios 7 (0x80)<br></code>
|
|
<p>Press a few different remotes and keys. Then enter<br></p>
|
|
<code>pigs nc 0</code><br>
|
|
<p>The file ir.vcd will contain the captured waveform, which can be
|
|
viewed using GTKWave.</p>
|
|
<p>Overview</p>
|
|
<img src="images/ir-wave-1.png" style=
|
|
"width: 600px; height: 100px;" alt="ir remote waveform 1"><br>
|
|
<p>Remote A typical waveform</p>
|
|
<img src="images/ir-wave-2.png" style=
|
|
"width: 600px; height: 100px;" alt="ir remote waveform 2"><br>
|
|
<p>Remote B typical waveform</p>
|
|
<img style="width: 600px; height: 100px;" alt=
|
|
"ir remote waveform 3" src="images/ir-wave-3.png">
|
|
</td>
|
|
</table>
|
|
<div style="vertical-align: center; text-align: center; background-color:#98bf21; font-size:0.8em; height:30px"><a class="l2" href="index.html">[pigpio]</a>
|
|
<a class="l2" href="cif.html">[pigpio C I/F]</a>
|
|
<a class="l2" href="pigpiod.html">[pigpiod]</a>
|
|
<a class="l2" href="pdif2.html">[pigpiod C I/F]</a>
|
|
<a class="l2" href="python.html">[Python]</a>
|
|
<a class="l2" href="pigs.html">[pigs]</a>
|
|
<a class="l2" href="piscope.html">[piscope]</a>
|
|
<a class="l2" href="misc.html">[Misc]</a>
|
|
<a class="l2" href="examples.html">[Examples]</a>
|
|
<a class="l2" href="download.html">[Download]</a>
|
|
<a class="l2" href="faq.html">[FAQ]</a>
|
|
<a class="l2" href="sitemap.html">[Site Map]</a>
|
|
</div>
|
|
<table><tr>
|
|
<td style="width: 200px"><div style="text-align: left;"><small>© 2012-2020</small></div></td>
|
|
<td style="width: 350px"><div style="text-align: center;">e-mail: pigpio @ abyz.me.uk</div></td>
|
|
<td style="width: 200px"><div style="text-align: right;"><small>Updated: 29/04/2020</small></div></td>
|
|
</tr></table>
|
|
</td>
|
|
</table>
|
|
</body>
|
|
</html>
|