Shield de infrarojos para Raspberry Pi

La comunicación mediante infrarojos se utiliza constantemente en nuestras vidas. Desde cambiar los canales de la televisión, encender el aire acondicionado o utilizar los disparadores remotos de las cámaras de foto. La automatización de estas funciones mediante dispositivos como Raspberry-PI o Arduino son muy útiles y va a ser usada ampliamente con la llegada de los dispositivos de hogar digital, como Amazon Alexa o Google Home. Existen muchos tutoriales de como hacer funcionar estos pequeños módulos con una Raspberry-PI, pero a todos ellos tienen algún pequeño detalle que hace que no funcione correctamente el dispositivo. Este artículo explica como usar los módulos de Infrarojos paso a paso.

Búsqueda de un dispositivo compatible con Raspberry PI

Lo primero que hice es buscar un dispositivo que funcionara con mis Raspberry PI, tanto versión 1, como versión 2 como las nuevas de versión 3. En mi caso encontré este módulo Emisor y Receptor de Infrarojos para Raspberry Pi .

El módulo (también llamado shield (escudo) por como se coloca en la Raspberry Pi) es lo más rápido de instalar y configurar. Dispone de dos dispositivos de tipo LED, uno para emisión y otro para recepción y dos botones configurables para realizar otras funciones.

El dispositivo receptor es el VS1838B . El emisor es un LED de infrarojos estándar.

Instalación del shield en la Raspberry Pi

La instalación del shield en la placa Raspberry Pi se hace utilizando el conector GPIO (General Purpose Input/Output, Entrada/Salida de Propósito General). Los conectores de GPIO son diferentes entre las diferentes Rasperry Pi, como se puede observar en la siguiente imagen:

Raspberry Pi Pinout

Aunque los conectores son diferentes, son compatibles entre ellos. Así, las placas shield que se utilizan en los modelos Raspberry Pi versiones A y B, pueden ser utilizados en el conector de 40 pines del resto de modelos, porque esos pines están colocados en el mismo lugar. El modelo de placa seleccionado es compatible por lo tanto con todos los modelos de Raspberry Pi. En la siguiente imagen la podemos ver instalada en la Raspberry Pi 1:

IR Shield en Raspberry Pi 1

Configuración del shield en Raspbian

Configuración del hardware

La Raspberry Pi donde vamos a instalar el módulo de infrarojos va a utilizar el sistema operativo Linux, mediante la distribución Raspbian .

Lo primero que haremos es decirle al kernel que utilice unos pines de la parte de GPIO, aquellos que sirven para comunicarnos con el módulo de infrarojos. En el módulo shield que hemos adquirido son los pines siguientes:

Uso Pin
gpio_out_pin 17
gpio_in_pin 18

Por lo tanto, configuraremos el fichero /boot/config.txt añadiendo las siguientes líneas:


# Habilitar el modulo de infrarojos lirc-rpi
dtoverlay=lirc-rpi,gpio_in_pin=18,gpio_out_pin=17

El siguiente paso consiste en indicar a Raspbian que queremos que utilice el módulo del kernel correspondiente al dispositivo infrarojos. Este módulo es lirc_rpi y también cargaremos el módulo lirc_dev. Para ello editarmos el fichero de configuración /etc/modules y añadiremos las siguientes dos líneas al final del mismo:


lirc_dev
lirc_rpi gpio_in_pin=18 gpio_out_pin=17

En este caso, le estamos indicando al módulo que pines son los que utilizaremos como entrada y como salida, que coinciden con los pines indicados en el fichero /boot/config.txt.

Reiniciaremos la Raspberry Pi mediante el comando reboot

Instalación del software lirc

El software que vamos a utilizar para enviar las señales infrarojas a través del módulo se llama lirc. Para instalarlo utilizaremos los comandos habituales de instalación de software en Debian o Raspbian:

$ sudo apt update
$ sudo apt install lirc-rpi

Tras la ejecución de los comandos anteriores, dispondremos del software necesario para enviar y recibir señales.

Configuración de lirc

Uno de los mayores problemas que podemos encontrar es la configuración del lirc. La razón es que existen muchos manuales realizados para las versiones anteriores de este software, pero las nuevas versiones utilizan ficheros de configuración distintos. La principal diferencia es la utilización del fichero de configuración /etc/lirc/lirc_options.conf para incluir toda la configuración y la no utilización del fichero /etc/lirc/hardware.conf que se utilizaba en versiones más antiguas. Adicionalmente se incluye un script en la distribución (/usr/share/lirc/lirc-old2new), que convierte la configuración antigua en la nueva, sin embargo la configuración generada no funciona porque utiliza un tipo de doble comillas inglesas (❝ ❞) en vez de las comillas habituales (” “).

Por lo tanto, es necesario editar el fichero de configuración /etc/lirc/lirc_options.conf e incluir en el mismo las siguientes líneas:

[lircd]
nodaemon        = False
driver          = default
device          = /dev/lirc0
output          = /var/run/lirc/lircd
pidfile         = /var/run/lirc/lircd.pid
plugindir       = /usr/lib/arm-linux-gnueabihf/lirc/plugins
permission      = 666
allow-simulate  = No
repeat-max      = 600

[lircmd]
uinput          = False
nodaemon        = False

En el directorio /etc/lirc/ encontraremos además los siguientes ficheros y directorios:

  • lircd.conf: Este fichero únicamente tiene una línea que permite leer los ficheros con extensión .conf que hay en el directorio lircd.conf.d. La línea es
    include "lircd.conf.d/*.conf"
  • lircd.conf.d: Este directorio contiene ficheros de configuración de los equipos a manejar mediante infrarojos. Inicialmente el directorio contiene un fichero (devinput.lircd.conf) que deshabilitaremos cuando configuremos nuestros mandos a distancia.
  • lircmd.conf: Este fichero no cotiene nada, únicamente líneas de comentario.

Ahora que tenemos configurada la aplicación lirc, es momento de reiniciar el proceso para ver que todo es correcto:

$ sudo /etc/init.d/lircmd stop
[ ok ] Stopping lircmd (via systemctl): lircmd.service.
$ sudo /etc/init.d/lircd stop
[….] Stopping lircd (via systemctl): lircd.serviceWarning: Stopping lircd.service, but it can still be activated by:
lircd.socket
. ok
$ sudo /etc/init.d/lircd start
[ ok ] Starting lircd (via systemctl): lircd.service.
$ sudo /etc/init.d/lircmd start
[ ok ] Starting lircmd (via systemctl): lircmd.service.
$

Mediante los siguientes comandos en negrita, vemos que el proceso está corriendo y que todo es correcto (marco en sin cursiva y negrita la parte importante que nos devuelve el sistema):

$ sudo /etc/init.d/lircmd status
● lircmd.service - Convert IR remotes button presses to mouse movements and clicks
Loaded: loaded (/lib/systemd/system/lircmd.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2018-07-30 16:34:36 UTC; 1h 0min ago
Docs: man:lircmd(8)
http://lirc.org/html/configure.html
Main PID: 3098 (lircmd)
CGroup: /system.slice/lircmd.service
└─3098 /usr/sbin/lircmd –nodaemon

Jul 30 16:34:36 raspberry systemd[1]: Started Convert IR remotes button presses to mouse movements and clicks.
Jul 30 16:34:36 raspberry lircmd[3098]: lircd-0.10.0[3098]: Notice: lircmd: Opening log, level: Notice
Jul 30 16:34:36 raspberry lircd-0.10.0[3098]: Notice: lircmd: Opening log, level: Notice
> $ sudo /etc/init.d/lircd status
● lircd.service - Flexible IR remote input/output application support
Loaded: loaded (/lib/systemd/system/lircd.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2018-07-30 16:34:32 UTC; 1h 0min ago
Docs: man:lircd(8)
http://lirc.org/html/configure.html
Main PID: 3060 (lircd)
CGroup: /system.slice/lircd.service
└─3060 /usr/sbin/lircd –nodaemon

Jul 30 16:34:32 raspberry lircd-0.10.0[3060]: Notice: Driver version: 0.10.0
Jul 30 16:34:32 raspberry lircd-0.10.0[3060]: Notice: Driver info: See file:///usr/share/doc/lirc/plugindocs/default.html
Jul 30 16:34:32 raspberry lircd-0.10.0[3060]: Info: lircd: Opening log, level: Info
Jul 30 16:34:32 raspberry lircd-0.10.0[3060]: Warning: Running as root
Jul 30 16:34:32 raspberry lircd-0.10.0[3060]: Info: Using remote: tv.
Jul 30 16:34:32 raspberry lircd-0.10.0[3060]: Notice: lircd(default) ready, using /var/run/lirc/lircd
Jul 30 16:34:36 raspberry lircd[3060]: lircd-0.10.0[3060]: Notice: accepted new client on /var/run/lirc/lircd
Jul 30 16:34:36 raspberry lircd[3060]: lircd-0.10.0[3060]: Info: Cannot configure the rc device for /dev/lirc0
Jul 30 16:34:36 raspberry lircd-0.10.0[3060]: Notice: accepted new client on /var/run/lirc/lircd
Jul 30 16:34:36 raspberry lircd-0.10.0[3060]: Info: Cannot configure the rc device for /dev/lirc0
$

El siguiente paso es reiniciar el sistema antes de comenzar con las pruebas de recepción y emisión:

$ sudo reboot

Pruebas de recepción

La primera de las pruebas que vamos a realizar es en recepción. Para ello necesitamos parar los procesos lircdy lircmd:

$ sudo /etc/init.d/lircmd stop
[ ok ] Stopping lircmd (via systemctl): lircmd.service.
$ sudo /etc/init.d/lircd stop
[….] Stopping lircd (via systemctl): lircd.serviceWarning: Stopping lircd.service, but it can still be activated by:
lircd.socket
. ok
$

Una vez parados los procesos, pasaremos a ver si el módulo de infrarojos está recibiendo correctamente y pasándo la información al núcleo del sistema. El núcleo nos enviará la información recibida mediante el fichero de dispositivo /dev/lirc0. Para ello, ejecutaremos mode2 -d /dev/lirc0 y el proceso quedará a la espera de recibir señales. Apuntaremos con el mando a distancia a los LED de la shield desde la parte donde reciben la información (la que apunta al lateral más cercano de la Raspberry Pi) y pulsaremos uno o más botones. Automáticamente, empezaremos a ver códigos en la pantalla, similares a los siguientes:

$ mode2 -d /dev/lirc0
Using driver default on device /dev/lirc0
Trying device: /dev/lirc0
Using device: /dev/lirc0
space 16777215
pulse 9058
space 4476
pulse 575

En caso de tener algún error, revisa la configuración del fichero /etc/lirc/lirc_options.conf. Uno de los problemas que tuve fue que recibía la siguiente información:

$ sudo modprobe lirc_rpi
$ sudo kill $(pidof lircd)
$ mode2 -d /dev/lirc0
Using driver devinput on device /dev/lirc0
Trying device: /dev/lirc0
Using device: /dev/lirc0
Partial read 8 bytes on /dev/lirc0
$

El problema era únicamente que el driver especificado en el fichero de configuración era driver = devinput en vez de driver = default.

Guardar las pulsaciones de botón

Si queremos guardar las pulsaciones de los botones de nuestro mando a distancia, algo que nos será útil si queremos luego enviarlas desde la Raspberry Pi, es necesario realizar los siguientes pasos. Lo primero es parar los procesos lircdy lircmd (si vienes del paso anterior, ya estarán parados), para ello debemos realizar

$ sudo /etc/init.d/lircmd stop
[ ok ] Stopping lircmd (via systemctl): lircmd.service.
$ sudo /etc/init.d/lircd stop
[….] Stopping lircd (via systemctl): lircd.serviceWarning: Stopping lircd.service, but it can still be activated by:
lircd.socket
. ok
$

Una vez parados, utilizaremos el comando irrecord para salvar las capturas. Es necesario ejecutarlo como usuario root. El comando sería el siguiente:

$ sudo irrecord -d /dev/lirc0 ~/tv.conf

Esto indica que el comando irrecord se ejecute como usuario root (para ello el comando sudo), utilizando el dispositivo /dev/lirc0 y guardando la información en ~/tv.conf. Es importante que al ejecutar este comando el fichero de destino (en este caso tv.conf) pueda escribirse en el directorio de destino. En el ejemplo se está usando el directorio home del usuario (~). Es importante que si hay un problema de permisos, se revise que se está ejecutando como usuario root y que el directorio donde se escribe el fichero tenga permisos para que ese usuario pueda escribir.

Una vez ejecutado, se deben seguir los pasos indicados en el proceso. El programa nos pedirá el nombre del dispositivo a usar, para el resto de esta guía usaré el dispositivo tv. Posteriormente, nos pedirá que pulsemos de forma repetida varios botones del mando a distancia, evitando dejar el botón pulsado, para que se identifique el tipo de mando. El último de los procesos es donde se almacenan las pulsaciones de botón de nuestro mando, indicando el tipo el botón al que corresponde la pulsación. Los nombres de los botones se pueden obtener mediante el comando irrecord -l. Los códigos más importantes son los siguientes:

Nombre botón Descripción
KEY_POWER Encender/Apagar
KEY_VOLUMEUP Volume +
KEY_VOLUMEDOWN Volume -
KEY_CHANNELUP Canal +
KEY_CHANNELDOWN Canal -
KEY_UP Arriba
KEY_DOWN Abajo
KEY_LEFT Izquierda
KEY_RIGHT Derecha
KEY_MENU Menu
KEY_OK Ok
KEY_BACK Atras
KEY_0 0
KEY_1 1
KEY_2 2
KEY_3 3
KEY_4 4
KEY_5 5
KEY_6 6
KEY_7 7
KEY_8 8
KEY_9 9

La primera vez recomiendo recoger solo algunos de los botones, por ejemplo KEY_POWER y los botones de subir y bajar canales y volumen. El proceso puede ser largo y es mejor estar seguro que está funcionando correctamente todo salvando únicamente unos pocos botones.

Con ello se genera el fichero de configuración (en este ejemplo, el fichero tv.conf).

Usar la configuración de nuestro mando

Una vez que tenemos un fichero para nuestro mando, del ejemplo anterior el fichero tv.conf vamos a guardarlo para que lirclo use.

Lo primero que vamos a hacer es quitar el fichero que viene por defecto y que no vamos a usar. El fichero es /etc/lirc/lircd.conf.d/devinput.lircd.conf. Lo que hacemos es símplemente cambiarle el nombre. Como la configuración de lirc lee los ficheros que están en /etc/lirc/lircd.conf.d/ y que tienen la extensión .conf, con cambiarle el nombre es suficiente:

$ sudo mv /etc/lirc/lircd.conf.d/devinput.lircd.conf /etc/lirc/lircd.conf.d/devinput.lircd.dist

Una vez movido el fichero, ponemos nuestro fichero en ese directorio. El fichero generado anteriormente debería estar en nuestro home según lo indicado en los comandos previos, por lo tanto, el comando a ejecutar sería el siguiente:

$ sudo mv ~/tv.conf /etc/lirc/lircd.conf.d/

Ahora, arrancamos los procesos de lirc. Si has seguido esta guía, deberían estar parados, en caso contrario, para los procesos primero como está indicado anteriormente. Los procesos los arrancamos mediante estos comandos:

$ sudo /etc/init.d/lircd start
[ ok ] Starting lircd (via systemctl): lircd.service.
$ sudo /etc/init.d/lircmd start
[ ok ] Starting lircmd (via systemctl): lircmd.service.
$

Usar la configuración de nuestro mando

El último de los procesos es usar la configuración que hemos salvado de nuestro mando a distancia para hacer lo que el mando haría. Para ello usamos el comando irsend, indicando el dispositivo que hemos indicado:

$ irsend SEND_ONCE tv KEY_POWER
$ irsend SEND_ONCE tv KEY_VOLUMEUP

Hasta este momento no hemos probado que el dispositivo envíe señales. Si no está funcionando correctamente puede ser por diferentes problemas. Lo primero que haremos es verificar que el shield está enviando datos. Para ello yo he usado una aplicación para Android que permite mediante la cámara de un móvil o tablet ver si se están enviado señales. La aplicación es IR Remote Tester . Como la pulsación dura únicamente un instante, he usado el siguiente script que envía cada segundo una pulsación al dispositivo tv para que se encienda mientras que observo con el teléfono:

$ while [ 1 ]; do echo $1; sleep 1; irsend SEND_ONCE tv KEY_POWER; done

Si vemos que se envían señales, pero no se está encendiendo el dispositivo, puede que no se esté apuntando correctamente con el shield. Es importante que el LED que está emitiendo apunte hacia el dispositivo que queremos encender y que esté a una distancia adecuada y sin obstáculos.

En caso de seguir fallando, es recomendable volver a realizar la grabación de las pulsaciones. Recuerda volver a poner el fichero generado en su lugar y rearrancar los procesos de lirc.

Enlaces de interes: