Tengo un botón de hardware que conecté a una interrupción, pero mi problema es que rebota un poco, lo que hace que el botón no sea confiable. Creo que una buena parte de estos problemas se resolvería mediante el muestreo en el bucle principal, pero eso se siente técnicamente mal.
¿Las interrupciones son más apropiadas para la comunicación dentro del circuito o las interrupciones también son apropiadas para los interruptores de hardware? Si es así, ¿qué técnicas de rebote puedo usar?
Intenté mantener una variable del temporizador y compararla con el tiempo actual, los retrasos y otras técnicas. Parece que los rebotes son tan rápidos que no importa.
interrupts
button
sampling
OneChillDude
fuente
fuente
Respuestas:
El rebote es una pregunta frecuente. Debería poder encontrar ... un número casi ilimitado de páginas web sobre el tema. Smith también comentó sobre el PDF ampliamente leído de Jack Ganssle sobre el tema. Y con todas estas respuestas tienes métodos de hardware y software.
Agregaré un poco a esta "literatura" hablando principalmente de ideas que no están bien cubiertas. Pero antes de hacerlo, un punto o dos:
Como mencioné el estiramiento del pulso usando un 74121 y como Jack Ganssle no lo menciona, y tampoco lo hace nadie aquí todavía, también puedo proporcionar este enlace adicional como lectura adicional sugerida sobre el uso del 74121 o 555 como una sola vez temporizador para interruptores antirrebote.
Ahora, para hacerlo a través de la observación con un microcontrolador.
Usualmente uso una máquina de estado para manejar el rebote. Esto casi siempre es impulsado por un temporizador regular de "latidos" que configuré aproximadamente8em , donde sea posible. (Generalmente, NO uso eventos de interrupción activados por bordes por varias razones).
La máquina de estado se ve así:
simular este circuito : esquema creado con CircuitLab
El valor de DEBOUNCED para el conmutador podría tomar valores "inactivos", "activos" y "desconocidos". De esta manera, puede asegurarse de que su software espere hasta que el valor del interruptor se establezca después de la inicialización. Pero por lo general, no me molesto con eso. Reemplazo el valor "desconocido" con algún valor predeterminado y solo uso un sistema de valores binarios.
La máquina de estado se ingresa configurando primero el valor de rebote a su valor predeterminado y luego ingresando el estado "CAMBIO" de la máquina de estado. En cada intervalo de tiempo (típicamente8em si me salgo con la suya), leeré el valor actual del interruptor y realizaré una actualización del estado actual y, posiblemente, el valor sin rebote. Entonces solo salgo. El código de alto nivel solo accede al estado sin rebote.
Si me importa, también puedo mantener un estado anterior sin rebote. En estos casos, cuando actualice el propio estado sin rebote, primero copiaré ese estado a un "estado sin rebote anterior". Entonces puedo usar el par de valores para determinar si ha habido una transición sin rebote. A veces, no me importan las transiciones. A veces lo hago. Entonces eso depende. Pero en todos los casos, solo quiero saber acerca de las transiciones que han sido eliminadas. Nunca me importan las transiciones runt . Por lo tanto, el código de alto nivel nunca usa ninguno de los estados internos que la máquina de estado usa para su propio trabajo.
Una de las cosas buenas de este método es que puedo eliminar el rebote de un puerto completo de conmutadores, a la vez. Y también puedo hacerlo sin una sola rama en el código de interrupción. Esto significa un código de eliminación de rebotes muy rápido y corto para hasta el ancho del puerto del microcontrolador (generalmente de 8 bits de ancho). Un ejemplo del Atmel AT90 muestra cómo se logra esto usando un evento de interrupción Timer0:
Ahora, este ejemplo muestra la oferta completa, incluidos los valores de cambio sin rebote anteriores y actuales. Y también realiza todas las transiciones de estado necesarias. No muestro la inicialización de este código. Pero lo anterior deja claro lo fácil que es operar la máquina de estado y el poco código que se requiere para hacerlo. Es bastante rápido y simple y no requiere ramificación (lo que a veces implica ciclos adicionales, así como espacio de código adicional).
Prefiero usar8em tiempo porque las pruebas largas con una variedad de personas diferentes que utilizan equipos en los que he trabajado en el pasado me han llevado allí. He intentado períodos más largos y cuando lo hago, empiezo a hacer que la gente me diga que la "capacidad de respuesta" no es lo suficientemente "enérgica". (En estos días, con los niños que crecen trabajando en tiempo real en juegos "shoot 'em up", incluso podría acortarlo aún más. Se quejarán amargamente incluso por retrasos leves causados por los televisores digitales modernos al configurar y mostrar un marco).
Algunas personas tendrán sentimientos muy claros acerca de cuán nítido y receptivo debe ser un sistema. Crujiente y sensible significa muestra más a menudo, no menos Pero personalmente, encuentro20em Períodos de observación aceptables. (Sin embargo, no encuentro tiempos más largos lo suficientemente buenos incluso para mí).
Tenga en cuenta que la máquina de estado que mencioné primero debe ingresar el estado SETTLED y luego permanecer allí durante un tiempo de muestra más antes de que se actualice el valor de DEBOUNCED. Por lo tanto, presionar un botón y mantenerlo presionado, incluso en las mejores circunstancias, requerirá estas transiciones:
Por lo tanto, un nuevo estado sin rebote requiere un mínimo de 3 períodos de tiempo de muestra para lograrlo.
Un botón pulsador requerirá al menos 6 veces de muestra para pasar de inactivo a activo y luego a inactivo.
Mencioné los detalles anteriores para que quede absolutamente claro que un tiempo de muestra de8em significa que en algún lugar entre dieciséisms <t≤24em para pasar de inactivo a un resultado sin rebote activo reconocido. Y tomará otro24em antes de que el estado pueda volver a estar inactivo. Eso es un mínimo de40ms<t≤48ms para pasar por un ciclo completo de botones.
El uso de tiempos de muestra más largos tendrá períodos correspondientemente más largos. Utilizando el20ms Ya lo mencioné como "aceptable" para mí, entonces significa en algún lugar 100ms<t≤120ms para un ciclo completo de botones. Y que está recibiendo de lleno hasta la zona donde la gente no tienden a aviso. Ciertamente no me gusta la "sensación" si se hace más larga que eso.
Si sigue esta ruta, no sea arrogante al usar tiempos de muestreo más largos. Si debe hacerlo, creo que también debe hacer muchas pruebas con usuarios / consumidores.
Y si está desarrollando código para un teclado de mecanografía, use tiempos más cortos. El récord para un mecanógrafo se estableció hace décadas en 217 palabras por minuto. Esto da como resultado aproximadamente una clave cada45ms . Los mecanógrafos como ese están presionando varias teclas en un orden controlado. Para obtener un buen rendimiento para mecanógrafos muy rápidos que usan un sistema de conmutación de relé de láminas humedecido con mercurio, descubrí que2ms funcionado bien.
fuente
El rebote se puede hacer en el software enmascarando las IRQ para el tiempo de rebote o en el hardware agregando un condensador de retención con su RC = T> tiempo de rebote que varía de 1 a 15 ms dependiendo del tamaño del interruptor.
fuente
Para realizar un rechazo de SW, registre la marca de tiempo del evento actual y verifique el retraso del último evento válido:
UPD: con poca modificación puede registrar doble clic:
fuente
Las interrupciones son definitivamente excelentes para los interruptores de hardware también. Al utilizar interrupciones, está evitando un gran desperdicio de recursos y posiblemente de energía, especialmente si se trata de dispositivos que funcionan con baterías.
Además, a medida que su código se hace más y más grande, verá que es aún más fácil implementar las interrupciones para los botones que sondearlos en su bucle principal.
En cuanto a su eliminación, probablemente sea un problema de codificación. Generalmente uso un temporizador de ~ 10 ms para eliminar el rebote, mientras verifico la liberación del botón. Asegúrese de deshabilitar también temporalmente la interrupción del botón mientras lo cancela, para que la rutina de interrupción no se ejecute varias veces.
Si aún tiene problemas, publique el código aquí, para que podamos ayudarlo.
fuente
Esto es bastante similar a la respuesta de Tony Stewart, pero creo que podría ampliarse un poco.
El esquema superior es para una interrupción en el borde bajo o en el borde descendente. El esquema inferior es para una interrupción en el borde alto o ascendente.
simular este circuito : esquema creado con CircuitLab
personalmente, dado el costo de un condensador, vale la pena simplemente usarlo, en lugar de preocuparme si mi software rebota es defectuoso.
Tenga en cuenta que, como dijo Tony Stewart, la constante de tiempo en este circuito es de 10 ms(R∗C o 10kΩ∗1μF) . Va a tomar entre tres y cinco constantes de tiempo (dependiendo de la sensibilidad de su microcontrolador para que el botón se reinicie, así que si su microcontrolador tiene problemas para repetir la función de interrupción, esa puede ser la causa, y es posible que necesite ajuste la tapa / resistencia para que la interrupción no ocurra varias veces (es decir, solo si su interrupción está configurada para funcionar en una señal alta o baja, y no en el borde ascendente o descendente.
Relacionado con el rebote de hardware
fuente
Los humanos son lentos, no necesitamos la atención inmediata de un micro que está en el rango de microsegundos.
Por supuesto, esta no es la única ni la forma correcta de hacerlo siempre, pero en general me parece más sensato configurar un temporizador (muchos micros tienen marcas de sistema) para disparar una interrupción a intervalos fijos y cambiar el estado del pin a un variable para que el código lo examine más tarde. Terminas con una var que está llena de cenizas durante el rebote
10010110 ceniza
pero en ciertos puntos en el tiempo obtendrá estos 4 valores:
01111111 borde ascendente acaba de eliminar el
botón 11111111 en estado estable hacia arriba
10000000 borde descendente acaba de eliminar el
botón 00000000 en estado estable hacia abajo
Sin embargo, la mayoría de las veces, solo uso un contador que se restablece durante el rebote. Es rápido, probado y fácil de hacer.
Si falla, ¡intento algo más inteligente del documento de Ganssle que otros sugirieron!
fuente