viernes, 13 de septiembre de 2024

Raspberry Pi: Pulsadores e Interruptores

Una de las características principales de las placas Raspberry Pi son sus pines GPIO (General Purpose Input Output) (Entrada y Salida de Propósito General). En estos pines podemos conectar todo tipo de componentes o dispositivos electrónicos. Unos de los componentes que podemos conectar son pulsadores e interruptores para interactuar con la placa.

Los pulsadores y los interruptores pueden estar abiertos o cerrados. Los pulsadores cambian de estado mientras se les presiona y vuelven a su estado inicial cuando se deja de presionar. Los interruptores mantienen su nuevo estado al dejar de presionar. Los pulsadores pueden ser NO (Normaly Open) (Normalmente Abierto) o NC (Normaly Closed) (Normalmente Cerrado). Algunos tienen tres contactos y se pueden usar de las dos formas.

En la placa hay dos filas de 20 pines. 2 de estos pines proporcionan 3,3 V y unos 500 mA de corriente continua. Otros dos pines proporcionan 5 V. Están conectados directamente a la entrada de alimentación de la placa y pueden proporcionar toda la energía del adaptador de corriente menos la usada por la propia placa. Entre los pines también hay 8 conexiones a tierra. Los 28 pines restantes son pines digitales de entrada/salida que podemos utilizar para conectar componentes y su voltaje debe estar entre 0 V y 3,3 V.

 1| 3,3V         2| 5V
 3| GPIO 2       4| 5V
 5| GPIO 3       6| TIERRA
 7| GPIO 4       8| GPIO 14
 9| TIERRA      10| GPIO 15
11| GPIO 17     12| GPIO 18
13| GPIO 27     14| TIERRA
15| GPIO 22     16| GPIO 23
17| 3,3v        18| GPIO 24
19| GPIO 10     20| TIERRA
21| GPIO 9      22| GPIO 25
23| GPIO 11     24| GPIO 8
25| TIERRA      26| GPIO 7
27| GPIO 0      28| GPIO 1
29| GPIO 5      30| TIERRA
31| GPIO 6      32| GPIO 12
33| GPIO 13     34| TIERRA
35| GPIO 19     36| GPIO 16
37| GPIO 26     38| GPIO 20
39| TIERRA      40| GPIO 21

Para controlar los pines podemos utilizar los comandos del paquete gpiod. Con el comando gpiodetect se detectan los chips GPIO del sistema y con el comando gpioinfo vemos información de las líneas de los chips. En la placa Raspberry Pi 4B los pines GPIO de la placa están controlados por las primeras 28 líneas del chip gpiochip0, en otros modelos puede ser algo diferente.

# apt-get install gpiod

# gpiodetect 

gpiochip0 [pinctrl-bcm2711] (58 lines)
gpiochip1 [raspberrypi-exp-gpio] (8 lines)

# gpioinfo gpiochip0

gpiochip0 - 58 lines:
	line   0:     "ID_SDA"       unused   input  active-high 
	line   1:     "ID_SCL"       unused   input  active-high 
	line   2:      "GPIO2"       unused   input  active-high 
	line   3:      "GPIO3"       unused   input  active-high
	line   4:      "GPIO4"       unused   input  active-high 
	line   5:      "GPIO5"       unused   input  active-high 
	line   6:      "GPIO6"       unused   input  active-high 
	line   7:      "GPIO7"       unused   input  active-high 
	line   8:      "GPIO8"       unused   input  active-high 
	line   9:      "GPIO9"       unused   input  active-high 
	line  10:     "GPIO10"       unused   input  active-high 
	line  11:     "GPIO11"       unused   input  active-high 
	line  12:     "GPIO12"       unused   input  active-high 
	line  13:     "GPIO13"       unused   input  active-high 
	line  14:     "GPIO14"       unused   input  active-high 
	line  15:     "GPIO15"       unused   input  active-high 
	line  16:     "GPIO16"       unused   input  active-high 
	line  17:     "GPIO17"       unused   input  active-high 
	line  18:     "GPIO18"       unused   input  active-high 
	line  19:     "GPIO19"       unused   input  active-high 
	line  20:     "GPIO20"       unused   input  active-high 
	line  21:     "GPIO21"       unused   input  active-high 
	line  22:     "GPIO22"       unused   input  active-high 
	line  23:     "GPIO23"       unused   input  active-high 
	line  24:     "GPIO24"       unused   input  active-high 
	line  25:     "GPIO25"       unused   input  active-high 
	line  26:     "GPIO26"       unused   input  active-high 
	line  27:     "GPIO27"       unused   input  active-high
...

La placa viene preparada para utilizar el pin GPIO 3 para iniciar y parar el sistema operativo. Cuando se para el sistema operativo la placa sigue encendida. Si mediante un pulsador NO conectamos los pines 5 y 6 (GPIO 3 y TIERRA), el sistema operativo volverá a iniciarse. Para conectar el pulsador a los pines podemos usar cables puente. En un extremo deben tener un conector hembra para el pin GPIO y en el otro hay que cortar el conector y pelar el cable para conectarlo al pulsador.


Si queremos que al volver a accionar el pulsador se pare el sistema operativo, podemos añadir al archivo de configuración /boot/firmware/config.txt el siguiente parámetro:

dtoverlay=gpio-shutdown

Si después de reiniciar ejecutamos el comando gpioinfo podremos ver como el pin GPIO 3 está en uso para parar el sistema.

# gpioinfo gpiochip0

gpiochip0 - 58 lines:

	line   3:      "GPIO3"   "shutdown"   input   active-low [used]

Para añadir más pulsadores para otras acciones podemos utilizar cualquiera de los pines GPIO y un pin de 3,3 V o TIERRA. Cuando el pulsador está abierto el pin GPIO está desconectado y tiene un voltaje indeterminado. Para poder detectar el cambio de estado del pulsador es necesario dar un voltaje al pin GPIO cuando está desconectado.

Si usamos un pin de TIERRA debemos conectar el pin GPIO a 3,3 V mediante una resistencia para subir su voltaje a 3,3 V. Si usamos un pin de 3,3 V debemos conectar el pin GPIO a tierra mediante una resistencia para bajar su voltaje a 0 V. El chip controlador de los pines incluye estas resistencias y no es necesario que las añadamos nosotros. Con estas configuraciones si el pulsador cambia de estado el voltaje del pin GPIO bajará de 3,3 V a 0 V o subirá de 0 V a 3,3 V. La resistencia para subir el voltaje recibe el nombre de "pull-up" y la resistencia para bajarlo "pull-down".

El comando gpiomon permite monitorizar los cambios de voltaje de un pin GPIO para detectar cuando se ha accionado el pulsador. Con el parámetro -f (falling) se le indica que solo detecte la bajada de voltaje de 3,3 V a 0 V. Con el parámetro -r (rising) se le indica que solo detecte la subida de voltaje de 0 V a 3,3 V. El parámetro -B permite fijar el voltaje de los pines GPIO desconectados con las opciones pull-up o pull-down.

PIN          RESISTENCIA     PULSADOR NO           PULSADOR NC
-----------  --------------  --------------------  --------------------
TIERRA (0V)  PULL-UP (3,3V)  FALLING (3,3V -> 0V)  RISING (0V -> 3,3V)
3,3V         PULL-DOWN (0V)  RISING (0V -> 3,3V)   FALLING (3,3V -> 0V)

Si conectamos el pin GPIO 27 a un pin TIERRA mediante un pulsador NO, debemos indicarle al comando gpiomon que suba el voltaje con el parámetro -B pull-up y detecte la bajada de voltaje con el parámetro -f. El parámetro -s hace que el comando no imprima nada por pantalla y el parámetro -n indica el número de eventos que debe detectar antes de terminar. Por último se le indica el chip y el pin o pines GPIO.

gpiomon -s -f -n 1 -B pull-up gpiochip0 27

Este comando lo podemos utilizar en un script. Cuando detecta el cambio de voltaje termina su ejecución y da paso al código siguiente. Si lo incluimos en un bucle infinito el script estará continuamente esperando la pulsación y ejecutando el código. Por ejemplo podemos tomar una imagen de una cámara con FFmpeg y enviarla por correo electrónico. También podemos enviarla con un sistema de notificaciones como Pushover.

#!/usr/bin/bash

GPIO=27
CAMERA=/dev/video0
DIRECTORY=/var/lib/notifications
TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
USER="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
MESSAGE="Camera Image"
SERVER=https://api.pushover.net/1/messages.json

while true
do
        gpiomon -s -f -n 1 -B pull-up gpiochip0 $GPIO

        datetime=`date +%F_%H-%M-%S`
        image=$DIRECTORY/$datetime.jpeg
        ffmpeg -f v4l2 -i $CAMERA -loglevel quiet $image
        curl -s -F token=$TOKEN -F user=$USER -F message="$MESSAGE" -F attachment=@$image $SERVER > /dev/null
done

Para ejecutar el script al iniciar el sistema operativo lo más conveniente es utilizar un servicio de Systemd. El script debemos copiarlo a un directorio de la variable $PATH y darle permisos de ejecución. El servicio tiene que ser ejecutado por un usuario que tenga permiso para acceder a los chips GPIO y a la cámara. Para ello debe pertenecer a los grupos gpio y video. Las imágenes tomadas de la cámara se pueden guardar en un subdirectorio de /var/lib.

# cp notifications.sh /usr/local/bin
# chmod +x /usr/local/bin/notifications.sh
# useradd notifications
# usermod -a -G gpio,video notifications
# mkdir /var/lib/notifications
# chown notifications:notifications /var/lib/notifications

# vi /lib/systemd/system/notifications.service

[Unit]
Description=Notifications

[Service]
Type=simple
User=notifications
ExecStart=/usr/local/bin/notifications.sh

[Install]
WantedBy=multi-user.target

# systemctl enable notifications

Mientras se ejecuta el comando gpiomon podemos ver con el comando gpioinfo como el pin GPIO 27 está en uso y con resistencia "pull-up". Cuando termina la ejecución del comando gpiomon el pin GPIO 27 vuelve a su estado inicial.

# gpioinfo gpiochip0

gpiochip0 - 58 lines:
	
	line  27:     "GPIO27"    "gpiomon"   input  active-high [used pull-up]

Si utilizamos un interruptor además de detectar cuando se abre o cierra podemos ver su estado en cualquier momento con el comando gpioget. Si conectamos el interruptor a un pin TIERRA, cuando esté abierto el comando devolverá el valor "1" y cuando esté cerrado el valor "0". Si queremos que sea al revés debemos indicar con el parámetro -l (active-low) que su valor activo es 0 V.

#!/usr/bin/bash

GPIO=21

switch=`gpioget -l -B pull-up gpiochip0 $GPIO`

if [ $switch -eq 0 ]
then
        echo "Switch Open"
else
        echo "Switch Closed"
fi

También se puede utilizar un control remoto como pulsador o interruptor. Un método muy usado son los controles remotos que usan chips EV1527 y la frecuencia 433 Mhz. Se componen de un receptor y un mando. El mando envía un código fijo de 24 bits sin cifrar. 20 bits identifican al mando y 4 bits el botón pulsado. Esto permite 1048576 (220) mandos distintos y 16 (24) botones por mando.

Los receptores tienen uno o varios relés o salidas digitales que son accionados al presionar los botones del mando. Los receptores tienen una lista con los códigos de los mandos a los que se permite enviar ordenes al receptor. Como el código es fijo y no está cifrado el sistema es muy sencillo, rápido y consume poca energía. Por ejemplo la batería de los mandos dura bastante. Pero si necesitamos seguridad tendremos que usar otro sistema con código variable y cifrado.

Yo he utilizado un control remoto con un solo relé. Debe ser alimentado por entre 5 V y 30 V, se puede utilizar un pin de 5 V de la placa. El relé tiene tres contactos: NO (Normaly Open) (Normalmente Abierto), COM (Común) y NC (Normaly Closed) (Normalmente Cerrado). En estado de reposo los contactos NO y COM están desconectados y los contactos NC y COM están conectados. Al accionar el relé se conectan los contactos NO y COM y se desconectan los contactos NC y COM. El receptor puede almacenar hasta 20 códigos de mando.

Para añadir un mando a la lista de mandos permitidos hay que presionar un botón del receptor y a continuación uno o dos botones del mando. Dependiendo del número de veces que se presione el botón del receptor se configura el mando para que funcione como pulsador, interruptor o interruptor temporal. Yo lo he configurado como pulsador, y conectando los contactos NO y COM a un pin TIERRA y un pin GPIO funciona igual que un pulsador NO.

PLACA      CABLE       CONTROL REMOTO
-------    --------    -------------------
TIERRA     NARANJA     TIERRA
5V         AMARILLO    5V
TIERRA     VERDE       NORMALMENTE ABIERTO
GPIO 27    AZUL        COMÚN



Si queremos tener más control, como por ejemplo realizar diferentes acciones dependiendo del código del mando, podemos utilizar un receptor de 433 MHz conectado a los pines GPIO y RPI-RF. También es posible usar un receptor SDR (Software Defined Radio) (Radio Definida por Software) y RTL_433.

No hay comentarios:

Publicar un comentario