En este artículo, exploraremos cómo conectar y programar botones y pulsadores con una Raspberry Pi.
Un botón o pulsador es un interruptor mecánico que, al ser presionado, cierra un circuito eléctrico, permitiendo el flujo de corriente. Cuando se suelta, el circuito se abre nuevamente.
Estos componentes son ampliamente utilizados en electrónica. Podemos usar los GPIO de la Raspberry Pi para leer su estado y usarlos como dispositivos de entrada.
Conexión del botón a la Raspberry Pi
La conexión de un botón a la Raspberry Pi requiere un circuito simple que incluya una resistencia que pone el pin en un estado conocido cuando cuando el interruptor está abierto.
La resistencia puede configurarse en modo pull-up o pull-down, dependiendo de cómo queramos interpretar el estado del botón.
La Raspberry Pi tiene resistencias pull-up y pull-down internas (de entre 50k-60k) que pueden ser activadas mediante software.
Expande para ver un ejemplo de resistencias pull-up externas
Si en lugar de usar resistencias internas prefieres usar resistencias en el circuito (lo cuál muchas veces es una buena idea) puedes hacerlo así.
Resistencia pull-down
En este esquema, la resistencia se coloca entre el pin de entrada GPIO y tierra (GND). Cuando el botón no está presionado, el pin GPIO lee un valor bajo (0V). Al presionar el botón, el pin se conecta a 3.3V, leyendo un valor alto.
GPIO Pin ---- Botón ---- 3.3V
|
Resistor (10kΩ) ---- GND
Resistencia pull-up
En este caso, la resistencia se coloca entre el pin de entrada GPIO y 3.3V. Cuando el botón no está presionado, el pin GPIO lee un valor alto (3.3V). Al presionar el botón, el pin se conecta a tierra, leyendo un valor bajo.
GPIO Pin ---- Botón ---- GND
|
Resistor (10kΩ) ---- 3.3V
Si quieres aprender más sobre resistencias Pull-up y Pull-down consulta,
Programación del botón en Python
Una vez que tenemos el botón correctamente conectado, podemos escribir un programa en Python para detectar cuándo se presiona.
Vamos a ver un ejemplo usando la biblioteca RPi.GPIO
(que vimos en la entrada anterior), con un código en Python que lee el estado del botón conectado al pin GPIO 17.
import RPi.GPIO as GPIO
import time
# Configuración del pin GPIO
BUTTON_PIN = 17
GPIO.setmode(GPIO.BCM) # Usar numeración BCM
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Configurar como entrada con pull-down
try:
while True:
# Leer el estado del botón
button_state = GPIO.input(BUTTON_PIN)
if button_state == GPIO.HIGH:
print("Botón presionado")
else:
print("Botón no presionado")
time.sleep(0.1) # Pequeña pausa para evitar lecturas rápidas
except KeyboardInterrupt:
print("Programa terminado")
finally:
GPIO.cleanup() # Limpiar la configuración de los GPIO
- Importación de bibliotecas: Importamos
RPi.GPIO
para controlar los pines GPIO ytime
para agregar pausas en el bucle. - Configuración del pin: Usamos
GPIO.setmode(GPIO.BCM)
para usar la numeración BCM de los pines GPIO. Luego, configuramos el pin 17 como entrada con una resistencia pull-down usandoGPIO.setup()
. - Lectura del estado: En el bucle
while
, leemos el estado del botón conGPIO.input()
. Si el estado esGPIO.HIGH
, significa que el botón está presionado. - Manejo de excepciones: Capturamos
KeyboardInterrupt
para permitir que el programa termine limpiamente cuando el usuario presioneCtrl+C
. Finalmente, llamamos aGPIO.cleanup()
para restablecer los pines GPIO.
Debounce
Los botones mecánicos pueden generar señales erróneas debido a rebotes físicos al presionarlos o soltarlos. Para evitar esto, podemos implementar un sistema de debounce en el software.
import RPi.GPIO as GPIO
import time
BUTTON_PIN = 17
DEBOUNCE_TIME = 0.2 # Tiempo de debounce en segundos
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
last_state = GPIO.LOW
last_time = 0
try:
while True:
current_state = GPIO.input(BUTTON_PIN)
current_time = time.time()
if current_state != last_state:
last_time = current_time
if current_time - last_time > DEBOUNCE_TIME:
if current_state != last_state:
last_state = current_state
if current_state == GPIO.HIGH:
print("Botón presionado")
else:
print("Botón liberado")
time.sleep(0.01)
except KeyboardInterrupt:
print("Programa terminado")
finally:
GPIO.cleanup()
Uso de interrupciones
En lugar de leer constantemente el estado del botón, también podemos usar interrupciones para detectar cambios de estado.
import RPi.GPIO as GPIO
import time
BUTTON_PIN = 17
def button_callback(channel):
if GPIO.input(channel) == GPIO.HIGH:
print("Botón presionado")
else:
print("Botón liberado")
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(BUTTON_PIN, GPIO.BOTH, callback=button_callback, bouncetime=200)
try:
while True:
time.sleep(1) # Mantener el programa en ejecución
except KeyboardInterrupt:
print("Programa terminado")
finally:
GPIO.cleanup()
En este ejemplo, GPIO.add_event_detect()
configura una interrupción que llama a button_callback()
cada vez que el estado del botón cambia.
Si quieres aprender más sobre interrupciones consulta,
Ejemplos prácticos
Control de un LED
Podemos usar un botón para controlar un LED conectado a otro pin GPIO. Por ejemplo, encender y apagar el LED cada vez que se presiona el botón.
import RPi.GPIO as GPIO
import time
BUTTON_PIN = 17
LED_PIN = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(LED_PIN, GPIO.OUT)
try:
while True:
if GPIO.input(BUTTON_PIN) == GPIO.HIGH:
GPIO.output(LED_PIN, GPIO.HIGH) # Encender LED
else:
GPIO.output(LED_PIN, GPIO.LOW) # Apagar LED
time.sleep(0.1)
except KeyboardInterrupt:
print("Programa terminado")
finally:
GPIO.cleanup()
Contador de pulsaciones
Este ejemplo cuenta cuántas veces se ha presionado el botón y muestra el resultado en la consola.
import RPi.GPIO as GPIO
import time
BUTTON_PIN = 17
counter = 0
def button_callback(channel):
global counter
counter += 1
print(f"Pulsaciones: {counter}")
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(BUTTON_PIN, GPIO.RISING, callback=button_callback, bouncetime=200)
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Programa terminado")
finally:
GPIO.cleanup()