Solución al ejercicio del prototipo con pulsador

Hace un par de semanas nos divertíamos con un prototipo que contaba nada menos que con un LED y un pulsador, aprendiendo a controlar el LED gracias a la señal proveniente del pulsador que introducíamos por un PIN GPIO.

Al final del artículo os proponía un ejercicio que decía así:

Tomando como base los programas de este artículo, consigue variar su funcionamiento de tal forma que pulsar el botón cambie su estado. Es decir, una pulsación lo enciende, otra lo apaga; si dejamos el dedo oprimiendo el pulsador, el LED parpadea cambiando de estado cada segundo. Como en este vídeo:

Consideraciones para Python: puedes usar un bucle infinito en Python (while True:), y terminar el programa usando la combinación de teclas CTRL + C (pulsar a la vez las teclas Control y C).

Lo mejor, en cualquier caso, sería que usases un bloque try: ... finally: ... como los que vimos en el artículo de excepciones, para hacer cosas como liberar recursos y apagar el LED antes de finalizar el programa.

Vamos a ver la solución.

Para este ejercicio monta el prototipo del artículo “Vuelve la electrónica: recibir información a través del GPIO de la Raspberry Pi“.

Solución en Python

Tomando como base el programa que enciende el LED durante un segundo, lo que debemos hacer es dotar de memoria al bucle, para que en una pasada invierta el estado en el que se puso con la anterior.

Para eso usaremos una variable llamada estadoen la que almacenaremos el valor presente en el pin GPIO número 12, que es el que usábamos como salida. Como inicialmente el LED estará apagado, la inicializaremos a False. Dentro del bucle, pondremos una sentencia de control ifque, en función del valor de estado, pondrá el contrario y lo almacenará en la misma variable.

Prueba el siguiente código:

#!/usr/bin/python3

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(6, GPIO.IN)

estado = False
GPIO.output(12, GPIO.LOW)

try:
    while True:
        if (not GPIO.input(6)):
        
            if (not estado):
                # LED Apagado
                print ("LED encendido")
                GPIO.output(12,GPIO.HIGH)
            else:
                # LED encendido
                print ("LED apagado")
                GPIO.output(12, GPIO.LOW)
            estado = not estado
finally:
    print ("Haciendo limpieza")
    GPIO.cleanup()
    print ("Hasta luego")

Habrás notado que tenemos un comportamiento extraño en el LED, y es que en ocasiones se queda encendido, otras veces se queda apagado, algunas parpadea un poco.¿Por qué ocurre esto? A la vista del código, no debería fallar.

Esto ocurre cuando combinamos la programación con el mundo físico: las cosas no funcionan de forma perfecta. El pulsador es un dispositivo físico ruidoso, es decir, al oprimirlo y soltarlo, emite variaciones aleatorias al PIN GPIO, y eso hace que el LED tenga esos transitorios extraños. Al entrar esa señal en el programa, en ocasiones éste registra más pulsaciones de las que hemos hecho, y es por culpa de ese ruido de origen mecánico.

Para evitarlo vamos a poner un temporizador corto, que nos permita retirar el dedo del pulsador antes de dejar que el bucle entre en la siguiente pasada:

time.sleep(0.5) # Filtro de rebotes

Lo pondremos antes de salir de una pasada del bucle. El código queda como sigue:

#!/usr/bin/python3

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(6, GPIO.IN)

estado = False
GPIO.output(12, GPIO.LOW)

try:
    while True:
        if (not GPIO.input(6)):
        
            if (not estado):
                # LED Apagado
                print ("LED encendido")
                GPIO.output(12,GPIO.HIGH)
            else:
                # LED encendido
                print ("LED apagado")
                GPIO.output(12, GPIO.LOW)
            estado = not estado
            time.sleep(0.5) # Filtro de rebotes
finally:
    print ("Haciendo limpieza")
    GPIO.cleanup()
    print ("Hasta luego")

Pruébalo ahora para comprobar que, ahora sí, el programa funciona como debe. Puedes experimentar con el valor del temporizador de espera para obtener resultados distintos y encontrar el umbral mínimo a partir del cual el prototipo deja de funcionar.

Solución en Scratch

Las explicaciones son básicamente las mismas.

Solución en Scratch al ejercicio del LED (cambio de estado)
Solución en Scratch al ejercicio del LED (cambio de estado)

Espero que haya sido interesante. Podéis dejarme cualquier comentario en esta misma entrada, o enviándome cualquier comentario a tavés del formulario de contacto y la dirección de correo que allí os indico. Recordad también que PItando está tanto en twitter, como en Facebook, y en Google+ también podéis seguir mis publicaciones, incluyendo las del podcast (iTunesiVooxRSS).

5 comentarios en “Solución al ejercicio del prototipo con pulsador

  1. Hola, en primer lugar muchas gracias por el tutorial, lo hice y me funciona a la perfección el problema va en que cuando en lugar de un led a la salida del gpio 12 pongo un rele este no prende con las pulsaciones. sabrías por que puede estar pasando?

    1. Hola. No he probado todavía con relés pero el tema puede estar en el voltaje o la corriente de salida del GPIO. Ten en cuenta que si cambias la resistencia del GPIO 12 por una de menor valor para incrementar la corriente puedes quemar la placa, así que ve con cuidado porque los GPIO no están protegidos. Consulta la hoja de características del relé y este artículo http://pitando.net/2016/02/11/analisis-basico-de-circuitos-electricos/

      En especial fíjate en la referencia a los valores que soporta el GPIO: «La máxima intensidad de corriente que soporta la Raspberry Pi a través de sus puertos GPIO es de “16 mA por pin, no excediendo entre todos los pines un máximo de 50 mA” (fuente —en inglés) […]»

      1. En el gpio 12 no le puse resistencia por que asi tenia funcionando el rele perfectamente con un bash, pero me gustaría ademas de bash poder encenderlo por un pulsador.

        1. lo pude resolver, me estaba faltano el gnd.
          Ahora te hago otra consulta funciona perfecto mientras el led se encuentre apagado pero si el led esta encendido el botón ya no funciona, tienes idea como hacer para que el botón cambie el estado independientemente de cual sea el estado inicial del led?

          1. Tienes que depurar tu programa, inicializa el LED a un estado conocido y almacenarlo en una variable

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *