Reconocer y sobrellevar el rebote del contacto en el Pi de frambuesa

  1. Ordenadores
  2. Pieza de frambuesa
  3. Reconocer y sobrellevar el rebote del contacto en el Pi de frambuesa

Libro Relacionado

Por Mike Cook, Jonathan Evans, Brock Craft

Es posible que tenga que lidiar con el rebote de contacto para su próximo proyecto de frambuesa Pi. Leer un interruptor es muy sencillo. Devuelve un 0 o un 1, dependiendo de si el interruptor está pulsado. Los interruptores siempre deben conectarse entre la clavija de entrada/salida de propósito general (GPIO) y la tierra y habilitar la resistencia interna de arranque o fijar una resistencia externa a ellos. Cuando un interruptor está cerrado, hace un camino a tierra. Se lee una lógica baja o cero cuando se hace esta ruta.

Puede ver otras disposiciones en las que se conecta un conmutador entre la clavija de entrada GPIO y 3V3, pero esto no se recomienda porque los conmutadores normalmente están conectados a cables largos. El tendido de cables largos conectados a tierra es menos riesgoso que la conexión a una tensión de alimentación. Así es como se cablea un interruptor.

Aunque un interruptor a tierra con una resistencia pull-up a un alto voltaje puede leer sólo 1 o 0, la mayoría de los interruptores son un poco más complejos. Por ejemplo, tome una bolsa de 1 libra de azúcar y suéltela desde aproximadamente 6 pulgadas sobre una superficie dura como una mesa. Golpea la superficie con un ruido sordo y se detiene. Ahora intenta lo mismo con una pelota de ping-pong, y verás que rebota. El primer rebote de la pelota de ping-pong no es tan alto como la altura desde la que la dejaste caer, pero es bastante alto. Luego la pelota cae y rebota de nuevo, sólo ligeramente más abajo. Esto continúa con alturas de rebote cada vez más pequeñas hasta que la pelota llega al descanso. Observe que cuanto más bajo es el rebote, más corto es el tiempo entre rebote y rebote; el rebote se acelera hasta que la pelota llega al descanso.

Los contactos de conmutación son así: son superficies rígidas que se unen rápidamente y rebotan. Tanto es así que si examinamos los niveles lógicos que da el interruptor, veremos no una simple transición de un nivel alto a uno bajo, sino una sucesión de transiciones que se acercan cada vez más hasta que se alcanza un nivel estable. Esto se conoce como un borde sucio o rebote de contacto.

Este rápido cambio de 0 a 1 puede ser un problema si la computadora está mirando el interruptor muy rápidamente. De hecho, esto sucede mucho más rápido de lo que un usuario puede presionar un botón, pero a veces las circunstancias o el código permiten que esto suceda. Para ilustrar el problema, mire el siguiente código, conecte un interruptor entre GPIO 2 (pin 3) y tierra (pin 6). Este pasador tiene una resistencia pull-up instalada en la placa.

# Problema de rebote muestra contacto rebote# Autor: Mike Cookimport timeimport wiringpi2 as io.wiringPiSetupGpio()io.pinMode(2,0) # to inputlastPress = io.digitalRead(2)count = 0pressTime = time.time()print"botón pulsador de prueba"while True: press = io.digitalRead(2) if press == 0 and lastPress != press: count += 1 pressTime = time.time() if count >= 5: print"five presses" count = 0 lastPress = press

La técnica utilizada aquí es contar cinco pulsaciones de interruptor y luego imprimirlas cuando el ordenador las haya contado todas. Si lo intenta, puede encontrar que imprime que ha detectado cinco prensas después de cuatro o incluso tres prensas, así como cada cinco. En resumen, no es fiable porque el rebote de contacto está causando conteos erróneos.

Para investigar esto más a fondo, es necesario medir el intervalo entre las prensas. Esto se hace con el siguiente código.

# Bounce Measure# mide el intervalo de tiempo de contacto# Autor: Mike Cookimport timeimport wiringpi2 as io.wiringPiSetupGpio()io.pinMode(2,0) # to inputlastPress = io.digitalRead(2)count = 0startTime = time.time()interval =[0.0,0.0,0,0.0,0.0,0,0,0.0]print"botón pulsador de prueba"while True: press = io.digitalRead(2) if press == 0 and lastPress != press: interval[count] = time.time() - startTime count +=1 startTimeTime = time.time() if count >= 5: print"five press ",interval count = 0 startTime = time.time() lastPress = press

El intervalo entre cada pulsación del interruptor se registra en una lista. Esto se deriva del reloj de la hora del sistema y cuenta el número de segundos desde que el sistema se inició. Al restar la hora del sistema de la hora de la prensa actual, se obtiene la hora desde la última pulsación. Aquí se muestra el resultado de la ejecución de este programa:

cinco prensas[1.2872810363769531, 0.25738978385925293,6.198883056640625e-05, 0.27149009704589844, 6.699562072753906e-05]cinco prensas[2.247836112976074, 0.31453490257267263184, 0.32202887537535095215, 0.2885620594024658, 0.33057308197021484]cinco prensas[1.04812598222284546, 3.504753112792969e-05, 0.56369590907592927734, 0.43523192405700684, 0.4095041751861572]cinco prensas[14.676625967025757, 0.2473571300506565918, 0.24397802352905273, 0.33951711654663086, 0.34607601165771484].

Note que el código no hace ningún intento de reducir el número de bits significativos en las lecturas, pero observe de cerca algunos de ellos, y verá que algunos terminan con un e-05. Esta es la forma predeterminada de decir 10 a la potencia de -5; esto se conoce como formato de exponente y es la forma predeterminada en que los números de coma flotante se muestran en la mayoría de los cálculos. Así que, olvidando el ridículo número de lugares después del punto decimal, este número, 6.12e-05, se interpreta como 0.0000612 o 61.2 microsegundos (uS), que es mucho más rápido que cualquier humano puede presionar cualquier cosa. Este es un ejemplo de rebote de contacto. No se ven todos los rebotes porque la computadora sólo muestrea el nivel lógico de la línea a intervalos discretos.

La forma de evitar que esto suceda es introducir un tiempo muerto, es decir, ignorar el interruptor durante un tiempo específico después de que se haya producido una pulsación. En muchas ocasiones, esto ocurrirá de forma natural porque es posible que tenga una declaración impresa o algún otro código que tarde algún tiempo en volver a examinar el conmutador. Si no es así, una solución sencilla sería añadir un retardo justo después de que se haya detectado el interruptor para que no se haga nada durante el tiempo de rebote potencial.

Sin embargo, para el rebote final, debe anotar la hora en que se detecta la transición de un conmutador. Luego, cuando se detecte otra transición, trátela como real sólo si ha transcurrido un tiempo específico entre la última transición real y el tiempo presente. Un ejemplo de esto se muestra en el siguiente código.

# Bounce Solution# Cómo lidiar con bounce# Autor: Mike Cookimport timeimport wiringpi2 as io.wiringPiSetupGpio()io.pinMode(2,0) # to inputlastPress = io.digitalRead(2)count = 0pressTime = time.time()print"botón pulsador de prueba"while True: press = io.digitalRead(2) if press == 0 and lastPress != press and (time.time() - pressTime) > 0.025: count += 1 pressTime = time.time() if count >= 5: print"five presses" count = 0 lastPress = press

Aquí el secreto es la prueba extra en la declaración if que comprueba que han transcurrido al menos 25 milisegundos (mS) antes de que una transición sea tomada como real.

Los diferentes tipos de interruptores mecánicos rebotan en un grado diferente. Dependiendo exactamente de cuál sea su código y de lo rápido que funcione, esto puede o no ser un problema. Si usted experimenta transiciones «fantasmas» al leer un interruptor mecánico, es probable que sea un rebote de contacto. Si es así, puede utilizar una de las técnicas descritas aquí para eliminar el efecto.

Reply