En un post anterior ya vimos como detectar un evento de un botón, pero muchas veces podemos ralizar una tarea de distintas maneras. En este post os voy a mostrar otra manera de ejecutar una función usando 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).
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).
Para empezar vamos a crear un pequeño programa en python que al ejecutarlo nos permita detectar si se ha pulsado un 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 librerias
import RPi.GPIO as GPIO
import time
# indicamos el uso de la identificacion BCM para los GPIO
GPIO.setmode(GPIO.BCM)
# configuramos el pin 18 como entrada y activamos
# la resistencia de activacion del pin 18 con PUD_UP
# esto hará que al presionar el botón se interrumpe
# la tensión de 3,3V del pin
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
# bucle infinito que recoge el estado de la resistencia
# del pin18, si el estado es Falso (interrupción 3,3V)
# mostramos el texto boton presionado
while True:
input_state=GPIO.input(18)
if input_state==False:
print('Boton presionado')
time.sleep(0.2)
click aquí para descargar el código
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,
si presionamos el botón en la pantalla aparecerá el texto Boton presionado. Fijaos que no estamos capturando el evento de presionado del botón como en el post anterior, sino que la función dentro del bucle infinito comprueba si el estado del pin de activación ha cambiado (se ha desactivado la corriente de 3,3V) y si es así se ejecuta la funció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. La línea final time.sleep(0.2) sirve para evitar el rebote ya que deja en suspensión la ejecución del código durante 0.2 segundos, si queréis podéis aumentar el tiempo de latencia para mejorar el funcionamiento.
Enhorabuena, ya conocéis otra técnica para detectar la presión del botón a través del cambio de estado de un PIN. Vamos a ver algo más.
2.2 Crear un switch (on/off) con un botón
Vamos a modificar el código anterior para crear un swtich (on/off) que enciende y apaga un led. Aqui os dejo una imagen de como debe quedar el circuito
y aquí tenéis el código, en el que vamos a usar el GND, GPIO18 y GPIO23
# importamos librerias
import RPi.GPIO as GPIO
import time
# indicamos el uso de la identificacion BCM para los GPIO
GPIO.setmode(GPIO.BCM)
# configuramos el pin 18 como entrada y activamos
# la resistencia de activacion del pin 18 con PUD_UP
# esto hará que al presionar el botón se interrumpe
# la tensión de 3,3V del pin
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
# configuramos el pin 23 como salida para el led
GPIO.setup(23,GPIO.OUT)
# definimos dos variables para guardar el estado del led
# por defecto el estado del led es False (apagado)
switch_state=False
# por defecto el estado anterior es True (encendido)
old_input_state=True # activada
# bucle infinito que recoge el estado del pin18
# cada vez que presionamos el botón,el estado del switch
# alterna entre True/False
while True:
# guardo en una variable el estado del pin
new_input_state=GPIO.input(18)
# si el estado es False (presionado),y el estado
# anterior es True cambiamos el valor del switch
if new_input_state==False and old_input_state==True:
switch_state=not switch_state
# tiempo de demora para evitar rebote
time.sleep(0.3)
# guardamos el estado actual del GPIO18
old_input_state=new_input_state
# modificamos el estado del led
GPIO.output(23,switch_state)
click aquí para descargar el código
al ejecutarlo podréis activar y desactivar el led cada vez que pulsamos el botón.
Espero que os haya gustado, nos leemos pronto.
1. Organización del circuito
En primer lugar vamos a ver como nos debe quedar nuestro circuito para este ejercicio. Aquí os dejo una imagen para que veáis la distribución que he usado, es la misma que en el ejercicio anterior.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
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 librerias
import RPi.GPIO as GPIO
import time
# indicamos el uso de la identificacion BCM para los GPIO
GPIO.setmode(GPIO.BCM)
# configuramos el pin 18 como entrada y activamos
# la resistencia de activacion del pin 18 con PUD_UP
# esto hará que al presionar el botón se interrumpe
# la tensión de 3,3V del pin
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
# bucle infinito que recoge el estado de la resistencia
# del pin18, si el estado es Falso (interrupción 3,3V)
# mostramos el texto boton presionado
while True:
input_state=GPIO.input(18)
if input_state==False:
print('Boton presionado')
time.sleep(0.2)
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,
si presionamos el botón en la pantalla aparecerá el texto Boton presionado. Fijaos que no estamos capturando el evento de presionado del botón como en el post anterior, sino que la función dentro del bucle infinito comprueba si el estado del pin de activación ha cambiado (se ha desactivado la corriente de 3,3V) y si es así se ejecuta la funció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. La línea final time.sleep(0.2) sirve para evitar el rebote ya que deja en suspensión la ejecución del código durante 0.2 segundos, si queréis podéis aumentar el tiempo de latencia para mejorar el funcionamiento.
Enhorabuena, ya conocéis otra técnica para detectar la presión del botón a través del cambio de estado de un PIN. Vamos a ver algo más.
2.2 Crear un switch (on/off) con un botón
Vamos a modificar el código anterior para crear un swtich (on/off) que enciende y apaga un led. Aqui os dejo una imagen de como debe quedar el circuito
y aquí tenéis el código, en el que vamos a usar el GND, GPIO18 y GPIO23
# importamos librerias
import RPi.GPIO as GPIO
import time
# indicamos el uso de la identificacion BCM para los GPIO
GPIO.setmode(GPIO.BCM)
# configuramos el pin 18 como entrada y activamos
# la resistencia de activacion del pin 18 con PUD_UP
# esto hará que al presionar el botón se interrumpe
# la tensión de 3,3V del pin
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
# configuramos el pin 23 como salida para el led
GPIO.setup(23,GPIO.OUT)
# definimos dos variables para guardar el estado del led
# por defecto el estado del led es False (apagado)
switch_state=False
# por defecto el estado anterior es True (encendido)
old_input_state=True # activada
# bucle infinito que recoge el estado del pin18
# cada vez que presionamos el botón,el estado del switch
# alterna entre True/False
while True:
# guardo en una variable el estado del pin
new_input_state=GPIO.input(18)
# si el estado es False (presionado),y el estado
# anterior es True cambiamos el valor del switch
if new_input_state==False and old_input_state==True:
switch_state=not switch_state
# tiempo de demora para evitar rebote
time.sleep(0.3)
# guardamos el estado actual del GPIO18
old_input_state=new_input_state
# modificamos el estado del led
GPIO.output(23,switch_state)
click aquí para descargar el código
al ejecutarlo podréis activar y desactivar el led cada vez que pulsamos el botón.
Espero que os haya gustado, nos leemos pronto.
Buenas noches:
ResponderEliminarestoy entrando en el mundo de la raspberry y he intentado por mucho hacer un pequeño programa que me imprima en la interfaz de tkinter los eventos de un boton pulsador como hacer la suma de cada ves que se pulse tengo este codigo que hace exactamente lo que quiero, pero lo hace desde un Button de tkinter, la pregunta es como puedo hacer esto desde un pulsador conectado a un GPIO(23) espero explicarme bien,
from tkinter import*
import RPi.GPIO as GP
GP.setwarnings(False)
GP.setmode(GP.BCM)
GP.setup(2, GP.IN)#Boton
GP.setup(23, GP.OUT)
GP.output(23, False)
raiz=Tk()
cont=0
def ledon():
global cont
cont+=1
lcon.set(cont)
print("LED button pressed")
print(cont)
if GP.input(23)==True:
GP.output(23,False)
ledButton["text"] = "PRENDER LED"
else:
GP.output(23,True)
ledButton["text"] = "APAGAR LED"
def cerrarPrograma():
print("exit Button pressed")
GP.cleanup()
raiz.quit()
raiz.title("Manejo de led desde tk")
raiz.resizable(0,0)
raiz.geometry("250x200")
exitButton = Button(raiz, text="exit", command = cerrarPrograma, bg='red', height=4, width=6 )
exitButton.pack(side=BOTTOM)
ledButton=Button(raiz, text="PRENDER LED", command=ledon, bg='green', height=4, width=8)
ledButton.pack()
lcon=StringVar(value=cont)
vercontador=Label(raiz, textvariable=lcon, bg='yellow', height=4, width=4)
vercontador.pack()
raiz.mainloop()
Hola, en el ejemplo, Controlar un botón con Python, detectar un evento del botón (Parte 2), el código muestra como interceptar el evento de botón presionado, en el momento en que se cumple esta situación deberías añadir el código que deseas ejecutar. El input_state es el que "captura" el estado.
EliminarEn el ejemplo, Controlar un botón con Python, detectar un evento del botón (Parte 1), también tienes un ejemplo de código, al presionar el botón se imprime en la consola "boton presionado", deberías sustituir esta línea por el código que deseas que se ejecute.
buen dia Alx Garcia gracias por responder
ResponderEliminaresa parte la comprendo o mejor dicho te pregunto como capturo ese evento en la interfaz Tkinter? por ejemplo en una etiqueta Label mostrar las veses que voy presionando el boton, realmente eso es lo que quiero pero no he podido dar con el chiste mira este codigo y si te das a la tarea de correrlo veras el problema en el que me encuentro y a lo mejor me puedas ayudar a encontrar la solucion, veras que solo falta hacer el llamado de la funcion y corre bien lo que no corre es la interfaz, no muestra ventana por ningun lado y si lo quitas corre la interfaz pero por obvias razones no correra el script
from tkinter import*
import RPi.GPIO as GP
import threading
GP.setwarnings(False)
GP.setmode(GP.BCM)
GP.setup(2, GP.IN)#Boton
GP.setup(23, GP.OUT)
GP.output(23, False)
cont=0
def control(sel):
while True:
if GP.input(2):
GP.output(23, GP.LOW)
else:
GP.output(23, GP.HIGH)
GP.cleanup()
raiz=Tk()
raiz.title("Manejo de led desde tk")
raiz.resizable(0,0)
raiz.geometry("250x200")
#raiz.attributes("-fullscreen",True)
lcon=StringVar(value=cont)
vercontador=Label(raiz, textvariable=lcon, bg='yellow', height=4, width=4)
vercontador.pack()
raiz.mainloop()
Hola, disculpa que haya tardado un poco pero voy bastante liado, partiendo del esquema con el botón y el led de este mismo ejemplo, puedes aplicar el siguiente código modificado a partir del mismo ejemplo (a mi me ha funcionado perfectamente, ya me dirás que tal)
Eliminarfrom tkinter import*
# importamos librerias
import RPi.GPIO as GPIO
import time
# indicamos el uso de la identificacion BCM para los GPIO
GPIO.setmode(GPIO.BCM)
# configuramos el pin 18 como entrada y activamos
# la resistencia de activacion del pin 18 con PUD_UP
# esto hará que al presionar el botón se interrumpe
# la tensión de 3,3V del pin
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
# configuramos el pin 23 como salida para el led
GPIO.setup(23,GPIO.OUT)
# definimos dos variables para guardar el estado del led
# por defecto el estado del led es False (apagado)
switch_state=False
# variable guarda presion del boton
cont=0
# funcion que se ejecuta repetidamente gracais a raiz.after
def presionado():
#indicamos que cont es una variable global
global cont
# guardo en una variable el estado del pin
new_input_state=GPIO.input(18)
# si el estado es False (presionado)
if new_input_state==False:
# tiempo de demora para evitar rebote
time.sleep(0.3)
# aumentamos la variable cont
cont=cont+1
# transformo cont en una stringVar
lcon=StringVar(value=cont)
# asigno el nuevo valor al label
vercontador.configure(textvariable=lcon)
# llamamos de nuevo a la funcion
raiz.after(10,presionado)
# inicializo pantalla de tkinter
raiz=Tk()
# nombre de la pantalla
raiz.title("Manejo de led desde tk")
# caracteristicas de la pantalla
raiz.resizable(0,0)
raiz.geometry("250x250")
# transformo cont en una stringVar
lcon=StringVar(value=cont)
# inicializo un label que mostrara un numero
vercontador=Label(raiz, textvariable=lcon, bg='yellow', height=4, width=4)
# pongo el label en un pack() para posicionarlo
vercontador.pack()
# llamamos a la funcion afer por primera vez
raiz.after(10,presionado)
# iniciamos el programa
raiz.mainloop()
muchísimas gracias corre super el código. yo ya había logrado mostrar el estado con el .after pero lo raro era que solo funcionaba bien con el GPIO 2, si lo cambiaba el script corría derecho, sin presionar el botón el led y el contador aumentaba sin parar y con este corre perfecto en cualquier gpio ademas me ahorraste la parte de averiguar el uso pull_up ya que en ves de el botón voy a conectar un sensor y me recomendaron hacer uso de esta sentencia para saber su estado.
ResponderEliminarmuchísimas gracias.
Buenas noches, hace mucho de esta entrada. Espero que me puedas ayudar.
ResponderEliminarTu codigo me funciona muy bien, pero si quisiera que fueran para 16 pulsadores y 16 reles. Que solucion me darias?
yo he echo una prueba con dos. Pero es escribir mucho codiga tontamente(soy novato)y seguro que hay una forma mas corta.
Gracias
Saludos
Hola Xavi, para ahorrar código deberías separar tu código en funciones. Las funciones pueden recibir parámetros y se pueden llamar tantas veces como quieras...
Eliminar