Tengo un proyecto muy simple en el que necesitaba eliminar el rebote de un botón (en el software). Lógicamente, mi proceso de pensamiento es:
Si el estado ha sido estable durante un tiempo y cambia, señale inmediatamente un evento.
Asegúrese de que el siguiente estado sea estable antes de permitir otro cambio de estado.
Entonces, si no se presiona un botón y ha estado así durante un tiempo, pero de repente leo una entrada modificada, no creo que deba esperar para confirmar que la entrada modificada ha sido estable (lo sé que ha habido un cambio físico real en el estado del botón). Simplemente puedo señalar un evento, pero no permitir nuevos eventos durante un período de tiempo determinado para evitar que los rebotes de botones falsos señalen eventos.
Aquí está el código arduino para una función getAction() hecha de esta manera:
static int buttonBounceState = BUTTON_STATE_UP; // "Bouncing" state
static int buttonState = BUTTON_STATE_UP; // Debounced state
static unsigned long lastChangeMillis = 0; // Time of last state transition
unsigned long currentMillis;
buttonBounceState = digitalRead(BUTTON_PIN);
if (buttonBounceState != buttonState) {
// Only allow state change if it's been 20 millis since last
currentMillis = millis()
if (currentMillis >= lastChangeMillis + 20) {
buttonState = buttonBounceState; // Change state
lastChangeMillis = currentMillis; // Only update timings at state transition
// Button state has changed, so return an action
if (buttonState == BUTTON_STATE_DOWN) return ACT_PRESS;
else return ACT_RELEASE;
}
}
// No button state change. Return no action.
return ACT_NONE;
Sin embargo, parece que dondequiera que miro, la forma en que se realiza el antirrebote es que la transición de estado inicial debe estabilizarse antes de realizar una señalización de evento/cambio de estado de software. Por ejemplo, la imagen inferior aquí: https://www.baldengineer.com/arduino-de-bounce-a-button-with-micros.html
Mi pregunta: ¿es mejor hacer el antirrebote de esta manera? ¿Hay algo en mi método que podría fallar en lo que no estoy pensando, es decir, algún tipo de ruido mientras el botón está abierto o cerrado? Si no, parece que mi método daría tiempos más precisos; y no me pierdo los toques de botón muy rápidos (pero lo retrasaría hasta que se estable). Además, ¿cómo se relacionan estos dos métodos de software con la eliminación de rebotes de hardware? ¿Cómo se implementaría un antirrebote de hardware que pueda cronometrar cosas similares a mi método?
Si elimina el rebote reaccionando de inmediato y dejando el botón en blanco (ignorando los cambios de etapa subsiguientes durante un tiempo predeterminado), el beneficio es una latencia baja. El inconveniente es la vulnerabilidad al ruido inducido que puede hacer o deshacer algunos sistemas.
Las personas no reaccionan lo suficientemente rápido como para notar una latencia de 10 ms, por lo que creo que, por lo general, es mejor eliminar el rebote verificando que un cambio de estado sea estable durante unos pocos ms antes de reaccionar. De esa manera, puede evitar problemas inesperados de ruido.
La razón principal por la que a veces reboto con "reaccionar inmediatamente y luego en blanco" es cuando estoy escribiendo un código de prueba rápido y sucio que finalmente se eliminará. Por lo general, encuentro que es más simple y menos invasivo codificar el rebote de esta manera, por lo que es más rápido de escribir y más fácil de eliminar del código final.
Algunos dispositivos antirrebote de hardware como el MAX6816 usan temporizadores y contadores cableados. El MAX6816, en particular, espera a que el estado sea estable durante un cierto período de tiempo antes de pasar.
En un FPGA también está cableado en el sentido de que se utilizan temporizadores, contadores y registro de muestreo. Puede hacer que reaccione inmediatamente y luego en blanco, o esperar hasta que el interruptor se estabilice antes de pasar la señal.
Los dispositivos antirrebote JK-flip flop cambian de estado inmediatamente y luego "en blanco". Pongo en blanco entre comillas porque no usan un intervalo de tiempo para ignorar los cambios posteriores. Más bien, se basa en algo más parecido a la histéresis mecánica. Inmediatamente cambia de estado si y solo si se hace un contacto eléctrico positivo. No reacciona si simplemente se pierde el contacto. Por lo tanto, si se pierde el contacto dentro del interruptor (como debido a un rebote) pero no se hace un nuevo contacto positivo, no cambian de estado. El interruptor nunca debe poder rebotar tan fuerte que vuele lo suficientemente lejos en la dirección opuesta para golpear el otro contacto. Esto es similar a la conservación de la energía en la que una pelota que se deja caer nunca debe rebotar hasta la altura desde la que se dejó caer.
También existen otros métodos de eliminación de rebotes, como el uso de filtros de paso bajo y comparadores, que dependen de que el interruptor sea estable durante el tiempo suficiente, pero también pueden activarse falsamente si el interruptor rebota demasiadas veces y la constante de tiempo se elige para ser demasiado corto ya que el capacitor continuará cargándose o descargándose a medida que el interruptor haga contacto con cada rebote.
No hay absolutamente nada de malo en hacer un antirrebote de "vanguardia" como lo describe; de hecho, es el método que prefiero en mis propios proyectos.
Como dices, tan pronto como ves el primer borde, sabes que el usuario ha iniciado una acción, por lo que no hay razón para retrasar la acción. El sistema se "sentirá" más sensible al usuario.
La única razón para usar el antirrebote de "borde posterior" (el tipo que ha estado encontrando) sería si hay alguna razón (EMI, ESD, etc.) por la que una entrada podría fallar que en realidad no es causada por la acción del usuario.
No hay mejor manera ya que cada caso puede tener diferentes interruptores, diferentes entornos o diferentes requisitos. Su solución funcionará bien, si no hay pulsos falsos por alguna razón. Un ejemplo sería una conexión normalmente cerrada, pero bajo vibraciones mecánicas podría abrirse y provocar activaciones falsas ocasionales, y reaccionar a cada borde solo amplificaría el problema. Es un delicado equilibrio entre eliminar el rebote lo suficiente como para mantener alejado el ruido no deseado y no gastar demasiado tiempo, como sondear en un bucle cerrado durante 10 milisegundos que el pin IO realmente permanece activo durante ese tiempo antes de creer que está presionado.
Si busca lo suficiente, puede encontrar muchos sistemas complicados para eliminar rebotes.
Pocos de ellos superan a los muy simples, solo espera .
Su sistema tendrá un requisito de tiempo de respuesta, tiene que funcionar más rápido que, o reaccionar a pulsos más cortos que un tiempo de umbral, llamado . El algoritmo de espera sondea el interruptor un poco más rápido que esto y lo ignora por completo entre tiempos.
Si su conmutador realmente rebota durante más tiempo que este tiempo, entonces su conmutador no es lo suficientemente bueno para cumplir con los requisitos de su sistema. Ningún esquema de rebote arbitrariamente complicado puede eliminar la ambigüedad de un pulso corto al que el sistema debería responder de un rebote largo.
En la versión más simple, solo sondeamos el interruptor cada . Habrá una latencia variable según el momento exacto en que se presionó el interruptor, lo que podría ser perceptible y molesto si era más grande que 100mS más o menos.
En una versión más receptiva y un poco más complicada, sondeamos con mucha más frecuencia y actuamos en un cambio de estado del interruptor. Una vez que el estado ha cambiado, esperamos a que antes de sondear el interruptor de nuevo.
phil g
broma