Reconocer y hacer frente a rebote de contacto en la pi de frambuesa
Puede que tenga que hacer frente a rebote de contacto para su próximo proyecto Raspberry Pi. Lectura de un interruptor es bastante simple. Se devuelve un 0 o un 1, dependiendo de si se pulsa el interruptor. Interruptores siempre deben estar conectados entre la entrada de uso general / salida (GPIO) pin de entrada y tierra y, o bien permitir que la resistencia pull-up interna o fijar una resistencia externa a ellos. Cuando un interruptor está cerrado, tiene una trayectoria a tierra. Lees un lógico bajo o cero cuando se hace este camino.
Usted puede ver otros acuerdos donde un interruptor está conectado entre el pin de entrada GPIO y 3V3, pero esto no es recomendable porque los interruptores están normalmente en los cables largos. Enrutamiento cables largos conectados a tierra es menos riesgoso que se conecta a una tensión de alimentación. Así es como se cablea un interruptor.
Aunque el cambio a tierra con una resistencia pull-up a un voltaje alto puede leer sólo un 1 o 0, la mayoría de los interruptores son un poco más complejo. Por ejemplo, llevar una bolsa de 1 libra de azúcar y dejarlo caer de aproximadamente 6 pulgadas sobre una superficie dura como una mesa. Se llega a 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 bote de la pelota de ping-pong no es tan alto como la altura se le cayó desde, pero es bastante alto. A continuación, la bola cae y rebota de nuevo, sólo ligeramente inferior. Esto continúa con alturas de rebote cada vez más pequeños hasta que la bola se detiene. Tenga en cuenta que cuanto menor es el rebote, menor será el tiempo entre bounces- los rebotes aceleran hasta que la bola se detiene.
Los contactos del interruptor son así - son superficies rígidas que se unen rápidamente, y que rebotan. Tanto es así que si se examinan los niveles lógicos del interruptor da a cabo, verás, no una transición sencilla desde una alta a una baja, pero una sucesión de transiciones cada vez más cerca y más cerca hasta que se alcance 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 el equipo está mirando el interruptor con gran rapidez. De hecho, esto ocurre mucho más rápidamente que un usuario puede pulsar un botón, pero a veces las circunstancias o código permitirá que esto suceda. Para ilustrar el problema, mira el siguiente código, conectar un interruptor entre GPIO 2 (pin 3) y tierra (pin 6). Este pin tiene una resistencia pull-up instalado en el tablero.
# Rebote Problema muestra rebote de contacto # Autor: Mike Cookimport timeimport wiringpi2 como ioio.wiringPiSetupGpio () io.pinMode (2,0) # para inputlastPress = io.digitalRead (2) count = 0pressTime = time.time () print "pruebas de empuje botón "while True: presione = io.digitalRead (2) si la prensa == 0 y lastPress = prensa: contar + = = 1pressTime time.time () si la cuenta> = 5: impresión" cinco prensas "count = = 0lastPress prensa
La técnica utilizada aquí es contar cinco prensas de conmutación y luego imprimir cuando el equipo los ha contado. Si intenta esto, es posible que imprime que ha detectado cinco prensas después de cuatro o incluso tres prensas, así como todos los cinco. En resumen, no es fiable porque el contacto de rebote está causando conteos erróneos.
Para investigar este más profundo, es necesario medir el intervalo entre las prensas. Esto se hace con el siguiente código.
# Medida de rebote # medidas de tiempo de contacto intervalo # Autor: Mike Cookimport timeimport wiringpi2 como ioio.wiringPiSetupGpio () io.pinMode (2,0) # para inputlastPress = io.digitalRead (2) count = 0startTime = time.time () Intervalo = [0.0,0.0,0.0,0.0,0.0] print "pruebas pulsador" while True: presione = io.digitalRead (2) si la prensa == 0 y lastPress = prensa: intervalo [count] = time.time () - startTimecount + = = 1startTime time.time () si la cuenta> = 5: impresión "cinco prensas", IntervalCount = 0startTime = time.time () = lastPress prensa
El intervalo entre cada pulsación del interruptor se registra en una lista. Esto se deriva de el reloj de tiempo del sistema y cuenta el número de segundos desde que el sistema arranca. Restando la hora del sistema desde el momento de la prensa actual, se obtiene el tiempo transcurrido desde la última pulsación. El resultado de la ejecución de este programa se muestra aquí:
cinco prensas [1.2872810363769531, 0.25738978385925293,6.198883056640625e-05, ,27149009704589844, 6.699562072753906e-05] cinco prensas [2.247836112976074, 0.31453490257263184,0.32202887535095215, 0.2885620594024658, ,33057308197021484] cinco prensas [1.048125982284546, 3.504753112792969e-05,0.5636959075927734, ,43523192405700684, ,4095041751861572] cinco prensas [14,676625967025757, 0.24735713005065918,0.24397802352905273, 0.33951711654663086, 0,34607601165771484]
Tenga en cuenta que el código no hace ningún intento de reducir el número de bits significativos en las lecturas, pero tener un vistazo de cerca a algunos de ellos, y verás que algunos terminan con un e-05. Esa es la forma por defecto de decir 10 a la potencia de -5- esto se conoce como el formato exponente y es la forma predeterminada números de punto flotante se muestran en la mayor parte de la computación. Así que, olvidando el número ridículo de posiciones después del punto decimal, este número, 6.12e-05, se interpreta como 0.0000612 o 61,2 microsegundos (US), lo cual es mucho más rápido que cualquier humano puede presionar nada. Este es un ejemplo de rebote de contacto. Usted no se ve todos rebote porque el equipo sólo muestras el nivel lógico de la línea en intervalos discretos.
La manera de evitar que esto suceda es introducir un tiempo muerto - es decir, ignorar el interruptor durante un tiempo específico después de haberse producido una prensa. En muchas ocasiones, esto va a suceder de forma natural, ya que podría tener una sentencia print o algún otro código que toma un poco de tiempo antes de que el interruptor se miró de nuevo. Si no, una solución simple sería añadir un retraso justo después del interruptor se ha detectado de manera que no se hace nada durante el tiempo potencial de rebote.
Sin embargo, para la supresión de rebotes último, es necesario hacer una nota de la vez que se detecta una transición interruptor. Luego, cuando se detecta otra transición, sólo se tratan como real si ha transcurrido un tiempo específico entre la última transición real y el momento actual. Un ejemplo de esto se muestra en el siguiente código.
# Rebote Solución # Cómo lidiar con rebote # Autor: Mike Cookimport timeimport wiringpi2 como ioio.wiringPiSetupGpio () io.pinMode (2,0) # para inputlastPress = io.digitalRead (2) count = 0pressTime = time.time () print "pulsador de prueba" while True: presione = io.digitalRead (2) si la prensa == 0 y lastPress = pulse y (time.time () - Presstime)> 0.025: contar + = = 1pressTime time.time () si contar> = 5: print "cinco prensas" count = = 0lastPress prensa
Aquí el secreto es la prueba adicional en el si declaración que comprueba que hayan transcurrido al menos 25 milisegundos (ms) antes de tomar una transición tan real.
Los diferentes tipos de interruptores mecánicos rebotan en un grado diferente. Dependiendo de exactamente lo que su código es y lo rápido que se ejecuta, esto puede o no ser un problema. Si usted experimenta transiciones "fantasmas" en la lectura de un interruptor mecánico, es probable que sea el contacto de rebote. Si es así, puede utilizar una de las técnicas descritas aquí para eliminar el efecto.