jueves, 22 de junio de 2017

Controlar un botón con Python, detectar un evento del botón (Parte 1)

En este post os voy a mostrar como usar los puertos GPIO y un pequeño programa en Python para controlar botón o pulsador, aquí os dejo una imagen del que he usado yo.



Para ello voy a usar una placa protoboard, cables de conexión, 1 botón y mi RaspberryPi. Si sois nuevos en esto os aconsejo leer los anteriores posts (del uso de los GPIO en el apartado Programación/GPIO).


1. Organización del circuito

En primer lugar vamos a ver como nos debe quedar nuestro circuito para poder controlar un pulsador. Aquí os dejo una imagen para que veáis la distribución que he usado.



si no habéis leído los anteriores post os recomiendo hacerlo (sobretodo el primero, en el que detallo el uso de las conexiones y hay un apartado al final sobre el uso de las resistencias, aquí está el link). 
Bien, como podéis ver uso el pin número 6 (cable negro para tierra, etiquetado como GROUND) y el pin número 12 (cable rojo para el positivo, etiquetado como GPIO18). 


2. Código Python

2.1 Capturar la pulsación de un botón

Para empezar vamos a crear un pequeño programa en python que al ejecutarlo nos permita capturar la pulsación que hagamos en el botón. Si no sabéis como crear un archivo con un programa en python os recomiendo leer los post sobre programación python del apartado Programación/GPIO del blog.

En primer lugar abrimos el IDLE de Python en nuestra RaspberryPi (yo uso Python3), una vez abierto creamos un nuevo fichero (en el menú File-New File) y introducimos el siguiente código

# importamos la librerias necesarias
import RPi.GPIO as GPIO
import time
# indicamos el uso de  la identificacion BCM para los GPIO
GPIO.setmode(GPIO.BCM)
# definimos una funcion que al ejecutarla muestra un texto
def boton_press(channel):
    print('Boton presionado')
# configuramos el pin 18 como de entrada y activamos la
# resistencia de activacion del pin 18 con PUD_UP
# esto hace que al presionar el boton se interrumpa la
# tension de 3,3V del pin
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
# con el siguiente evento detectamos si hemos presionado el
# boton y ejecutamos la funcion
GPIO.add_event_detect(18,GPIO.FALLING,callback=boton_press)
# creamos un bucle que muestra los segundos trasncurridos
# i detiene la ejecucion un segundo
i=0
while True:
    i=i+1
    print(i)
    time.sleep(1)

guardamos el archivo en una ubicación conocida (en el menú File-Save As), si es necesario apuntad la ruta por si la necesitáis usar más tarde. 

Podemos ejecutar directamente este pequeño programa presionando la tecla F5 (también se puede ejecutar des de el menú Run-Run Module)

Si todo es correcto se abre una nueva ventana de IDLE de python y empieza la ejecución, 
en la pantalla veremos como aparecen los segundos transcurridos si presionamos el botón en la pantalla aparecerá el texto Boton presionado. Fijaos que estamos capturando el evento de presionado, o sea que la función boton_presionado se ejecuta al apretar el botón (no al soltarlo) y cambiar el estado del conector GPIO18. Si cambiáramos FALLING por RISING, se capturaria al linerar el botón. Podéis mantener presionado el botón y por el efecto de rebote del botón veréis que la función se ejecuta más de una vez (luego veremos como evitarlo). 
Felicidades ya sabéis detectar que hemos presionado un botón.

2.2 Evitar el rebote de un botón

Para evitar el efecto de rebote del botón podemos añadir un parámetro (bouncetime=milisegundos) que evita que se vuelva a disparar el botón. La función quedaría como os muestro a continuación

# importamos la librerias necesarias
import RPi.GPIO as GPIO
import time
# indicamos el uso de  la identificacion BCM para los GPIO
GPIO.setmode(GPIO.BCM)
# definimos una funcion que al ejecutarla muestra un texto
def boton_press(channel):
    print('Boton presionado')
# configuramos el pin 18 como de entrada y activamos la
# resistencia de activacion del pin 18 con PUD_UP
# esto hace que al presionar el boton se interrumpa la
# tension de 3,3V del pin
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
# con el siguiente evento detectamos si hemos presionado el
# boton y ejecutamos la funcion
GPIO.add_event_detect(18,GPIO.FALLING,callback=boton_press,bouncetime=400)
# creamos un bucle que muestra los segundos trasncurridos
# i detiene la ejecucion un segundo
i=0
while True:
    i=i+1
    print(i)
    time.sleep(1)

El númeo de milisegundos dependerá de la calidad del botón, de la persona que lo presiona y la finalidad de uso del botón, tendréis que realizar diferentes pruebas para determinar los milisegundos necesarios.

3. Funcionamiento del circuito


Para poder ver de manera más fácil como funciona vamos añadir un led a nuestro circuito para ver lo que sucede. Modificad el circuito como os muestro en la siguiente imagen (no he usado resistencia porque en mi caso el botón ya ejerce suficiente resistencia para no estropear mi Raspberry Pi)



una vez tenéis el circuito como el de la imagen, ejecutad el programa en python que hemos escrito anteriormente. Fijaos que el led se ilumina (seguramente muy poco), al presionar el botón veréis que el led se apaga mientras tenemos el botón presionado. Vamos a explicarlo. Con la orden

GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)

hemos indicado que el GPIO18 es de entrada y que se active la resistencia de activación del GPIO18, esto hace que por defecto tengamos circulación de corriente entre el pin GND o el GPIO18.

con la orden

GPIO.add_event_detect(18,GPIO.FALLING,callback=boton_press,bouncetime=400)

podemos capturar si tenemos el  botón presionado, esta acción desactiva la resistencia de activación del puerto GPIO18, lo que interrumpe la entrada de corriente, y por ello se apaga el led (se interrumpe la circulación de corriente de 3,3V).