PIC12F509 ¿Desea el cambio en el comunicado de prensa o ambos?

1

Tengo una pregunta con respecto al debouncing del switch. Estoy usando un PIC12F509 y el oscilador RC interno que funciona a 4 MHz.

Enciendo y apagando un LED conectado a GP1 (salida) a través de un interruptor de botón momentáneo en GP3 (entrada) que se mantiene alto a través de una resistencia de 10 K cuando el interruptor está abierto. Estoy usando la siguiente macro y el siguiente código para deshacer el interruptor de botón pulsador. Utiliza el temporizador 0 configurado a una escala 1: 256.

Espera hasta que los contactos hayan permanecido en el mismo estado (abierto en este caso) durante 10 milisegundos antes de ejecutar el resto del código. Si rebotan (bajan) el temporizador 0 se reinicia.

DbnceHi     MACRO    port,pin
local       start,wait,DEBOUNCE
variable    DEBOUNCE=.10*.1000/.256 ; debounce count = 10ms/(256us/tick)

    pagesel    $ ; select current page for gotos
    start      clrf TMR0 ; button down, so reset timer (counts "up" time)
    wait       btfss port,pin ; wait for switch to go high (=1)
    goto       start
    movf       TMR0,w ; has switch has been up continuously for
    xorlw      DEBOUNCE ; debounce time?
    btfss      STATUS,Z ; if not, keep checking that it is still up
    goto       wait

    ENDM

main_loop
; wait for button press

wait_dn   btfsc GPIO,3 ; wait until button low
goto      wait_dn

; toggle LED
movf      sGPIO,w
xorlw     b'000010' ; toggle shadow register
movwf     sGPIO
movwf     GPIO ; write to port

; wait for button release
DbnceHi     GPIO,3 ; wait until button high (debounced)

; repeat forever
goto     main_loop

END

Ahora en mi pregunta hasta ahora, he estado lanzando y soltando el botón. Me ha llamado la atención en el tutorial que sigo, que normalmente no es necesario rebatir tanto al presionar como al soltar un interruptor.

Puedo entender por qué, en teoría, porque después de que el interruptor se lee tan bajo a través de la instrucción btfsc (incluso si es momentáneo porque los contactos están rebotando). El LED se enciende y el código alto de rebote esperará hasta que los contactos se abran y dejen de rebotar antes de ejecutar el goto para hacer un bucle del código desde el principio.

En el lado positivo esto guarda la memoria del programa. Pero si algo parece demasiado bueno para ser verdad, generalmente, ¿cuáles son los peligros potenciales de este método?

Obviamente, para una aplicación simple como esta, el código es excesivo. Pero para algo más crítico, como poner el PIC en modo de suspensión y despertarse de un cambio de pin, debe eliminarse cualquier rebote para que el micro ingrese al modo de suspensión de manera confiable.

¿Cuáles son sus opiniones sobre el debouncing de conmutadores: rebote la prensa y el lanzamiento o solo uno?

Mis agallas me dicen que me ponga el cinturón y los tirantes y que solo los rebote para estar a salvo, pero no tengo ninguna razón lógica para ello.

    
pregunta Krankshaft

5 respuestas

2

Los interruptores mecánicos rebotan en ambas transiciones. El rebote en la apertura es generalmente más corto que en el cierre, pero ciertamente puede suceder.

Generalmente uso 50 ms de tiempo de rebote en ambas direcciones. Hace mucho tiempo, probé un montón de pulsadores. La mayoría deja de rebotar en 10-15 ms, pero algunos tardaron mucho más, como 40 ms. Me decidí por 50 ms, ya que parecía ser lo suficientemente largo para estar a salvo con casi cualquier interruptor, a menos que intentes mantenerlo en la transición. También hice algunas pruebas sobre la percepción del retraso humano, y llegué a la conclusión de que 50 ms era aproximadamente el límite con el que puedes escapar sin que se notara el retraso, a menos que quizás alguien lo esté buscando específicamente.

De todos modos, la mayoría de los proyectos de microcontroladores tienen una interrupción periódica de 1 ms por otras razones, por lo que generalmente le agrego código de rebote. Mantengo un contador y una bandera global para cada interruptor. La bandera indica el estado actual del interruptor que es el que utiliza todo el código de la aplicación como estado del interruptor. El contador es privado a la rutina de interrupción. Se establece en 50 cada vez que el estado real del conmutador coincide con el estado de rebote y se reduce en 1 cuando difieren. Cuando el contador llega a 0, el interruptor se vuelve oficialmente abonado en el nuevo estado y, por supuesto, el contador se restaura a 50 ya que el interruptor y el estado de rebote están de acuerdo.

He utilizado este enfoque básico en muchos proyectos de microcontroladores, y no he tenido ningún problema con los botones de rebote o los usuarios quejándose (o incluso notando) el retraso de 50 ms.

    
respondido por el Olin Lathrop
1

Aunque los datos pueden estar sesgados de una manera u otra, no confiaría que ninguna dirección esté completamente libre de rebotes.

La primera vez que comencé con el software integrado, usaba los temporizadores para el desalojo (ignorar las transiciones posteriores dentro del tiempo x aceptado), pero a medida que mi cuenta de E / S aumentó, rápidamente se volvió difícil de manejar.

Ahora escaneo toda la interfaz de usuario a una velocidad lo suficientemente baja como para que el rebote del interruptor ya no tenga importancia, pero aún lo suficientemente rápido para parecer sensible. ** Esto incluye tanto los botones como los LED.

En otras palabras, todo mi código de interfaz de usuario está en un lugar y se ejecuta periódicamente a esa velocidad. Sus controladores de bajo nivel (PWM, registros de desplazamiento, etc.) pueden ejecutarse más rápido que eso si es necesario o conveniente, pero no tiene sentido actualizar sus valores más rápidamente.

** La razón por la que esto funciona es si lo leí a mitad de rebote:

  • Puedo leer lo mismo que en la muestra anterior, lo que significa que no hay cambios y la detectaré la próxima vez.
  • Puedo leer lo mismo que en la siguiente muestra, lo que significa que lo atrapé esta vez.

De cualquier manera, obtengo una transición limpia en el software simplemente porque muestro más lento que el tiempo de rebote. Pero sigue siendo más rápido que la percepción del usuario de "instantáneo", por lo que un período de muestra de jitter está bien.

    
respondido por el AaronD
1

¿Por qué tendría que rebotar un botón que controla un LED? Si el estado del LED cambia rápidamente durante unos pocos milisegundos mientras su interruptor rebota, ¿a quién le importa?

Si está tratando de obtener más información sobre el desalojo, le sugiero que conecte su interruptor al reloj de un contador binario . Su contador debe avanzar solo 1 conteo por pulsación de botón. Si avanza 2 o más conteos, sabes que ha habido algún suceso de rebote.

Alternativamente, puedes programar tu PIC para que cuente los pulsos del botón. De hecho, podría ser más perspicaz tener su PIC (o chip lógico o lo que esté usando) para contar el número de bordes que ve. Esto puede indicar si su botón rebota cuando presiona, cuando suelta, o ambos.

TL; DR

Si desea obtener más información sobre la eliminación de rebotes, cree un circuito que capture los rebotes. De lo contrario, si solo está tratando de controlar un LED, probablemente no sea necesario el rebote.

    
respondido por el Ryan Jensen
1

Tengo . Tiene 3 botones que no tienen ningún circuito de desmontaje según el documento . Así que para estos botones utilizo técnicas de debouncing de software. Solo lo uso para presionar botones.

No soy bueno en lenguaje ensamblador, pero puede usar muchas técnicas de software de desmonte para su problema. Por ejemplo:

  1. Verificar que se presione el botón
  2. Añade un retraso de 100ms
  3. Vuelve a buscar el botón presionando
  4. Añade tu código

    if(BUTTON == PRESSED)
    {
     DelayMS(100);
     if(BUTTON == PRESSED)
     {
      LED = ON;
     }
    }
    
respondido por el Aircraft
0

Puedo ver dónde probablemente funcionará el rebote de la acción "presionar" solo , ya que durante el lanzamiento del botón, la rutina saltará inmediatamente a la función "presionar", pero será rechazada. Eso suena un poco sucio, pero debería funcionar lo suficientemente bien.

Puede considerar una rutina que no marque "presionar" o "soltar", sino que mantenga un estado de "ahora" y solo verifique que la entrada haya cambiado (durante los 10 ms o lo que sea). Luego actualice el estado "ahora", y el programa puede leer "ahora" para decidir dónde está el botón en cualquier momento. Esto tiene una serie de ventajas.

  • Este método anuncia el cambio en cualquier dirección, ya que solo está buscando un cambio. Así que obtienes "prensa" y obtienes "versión" gratis.
  • "Ahora" puede ser un byte y, por lo tanto, puede mantener hasta ocho interruptores. ¡Y puedes unirlas todas juntas! Una vez que todos y cada uno de ellos se hayan asentado, cambias "ahora" para reflejar sus estados.
  • Si organiza un método para llamar a la rutina de verificación periódicamente (generalmente se realiza con una interrupción del temporizador, pero existen otras formas creativas), tiene el resto del tiempo entre las comprobaciones para realizar un trabajo útil (es decir, ciclos de CPU adicionales). ).

Podrías adivinar que mucho de esto está escrito desde la experiencia; y lo es, así que compartiré que verifico los interruptores cada 10 ms y espero hasta que se hayan estabilizado 3 veces seguidas. A 30 ms, todavía no sentirás ningún retraso.

    
respondido por el gbarry

Lea otras preguntas en las etiquetas