Pulsadores, interrupciones y antirrebote en Micropython

7 de Octubre, 2024 - Tiempo de lectura: 2 minutos

Una de las primeras cosas que se aprende cuando se programa microcontroladores es que cuando se trabaja con botones o pulsadores puede ocurrir lo siguiente. Los pulsadores son elementos mecánicos que cuando son pulsados realizan un contacto eléctrico entre dos terminales. Ese contacto no es perfecto, no pasa de estar desconectado a estar conectado de manera limpia. Cuando se tocan los contactos, pueden rebotar o simplemente no entrar en contacto de forma instantánea.

Los microcontroladores pueden llegar a ejecutar su ciclo de programa decenas de veces por segundo, así que esos pequeños rebotes que se producen, los interpretarán como varias pulsaciones muy rápidas de un botón. Si se programa una aplicación, por ejemplo para incrementar un contador o ajustar la hora de un reloj, se produce un resultado no deseado. El valor que debería incrementarse de uno en uno, se incrementa de forma descontrolada.

Para ese tipo de aplicaciones se puede utilizar interrupciones, aunque no es estrictamente necesario. En el ejemplo de más abajo utilizo una interrupción asociada al pin 22, configurado como entrada, para incrementar un número.

from machine import Pin, Timer, I2C
import utime

#(....)

# GPIO I/O
button = Pin(22, Pin.IN, Pin.PULL_DOWN)
led_amarillo = Pin(15, Pin.OUT)

utc_offset = 0
last_time =0
def adjust_utc_offset(pin):
    global utc_offset
    global last_time

    new_time = utime.ticks_ms()
    # if it has been more that 1/5 of a second since the last event, we have a new event
    if (new_time - last_time) > 200: 
        utc_offset += 1
        last_time = new_time

button.irq(trigger=machine.Pin.IRQ_FALLING, handler=adjust_utc_offset)

Para evitar los rebotes, cuando entra en la interrupción espera un poco (200ms) antes de seguir ejecutando el programa. Así no detectará un rebote, pero si una nueva pulsación que se pudiera producir. Ese tiempo se debería ajustar según el "feeling" que nos dé el botón utilizado, la velocidad de la aplicación, etc.

Todo esto también puede aplicarse a sensores basados en contactos electromecánicos, como finales de carrera.