Algoritmo antirrebote de pulsadores

Indagando en foros uno se da cuenta que lo que parece tan fácil como capturar la simple pulsación de una tecla conectada a un pin de un microcontrolador, en el fondo lleva consigo algunas técnica a tener en cuenta; Muchos son los que preguntan, sobretodo cuando se está iniciando en materia de programación de microcontroladores, como debería ser un buen algoritmo de antirrebote. Pues bien, en esta ocasión les traigo la implementación de la rutina escrita en CCS C para PIC16F88, que, si bien puede que no sea la mejor, es sin duda, muy funcional y práctica, al menos cumple su función a las mil maravillas. Es el modo en que hago el antirrebote en mis códigos y hasta ahora no ha fallado nunca.

La teoría es bastante sencilla, el programa espera a que se pulse una tecla, cuando detecta la pulsación guarda el número de tecla pulsada en una variable, luego comprueba que sea la primera vez que se pulsó, si es así actúa en consecuencia y si es que está pulsada desde antes, comprueba que haya pasado un tiempo determinado para volver a tenerla en cuenta. De este modo se puede hacer, por ejemplo un reloj que cuando se incremente alguno de sus parámetros, por ejemplo los minutos, y la tecla correspondiente se mantenga pulsada, luego del primer incremento comience a avanzar mas rápido.


He aquí el código en CCS C:
#include <16f88.h>
#use delay(clock=8MHz)
#use fast_io(all)
#fuses MCLR,NOPUT,INTRC_IO,NOWDT,NOBROWNOUT


#define Tec1   PIN_B0
#define Tec2   PIN_B1
#define Tec3   PIN_B2
#define Tec4   PIN_B3   //Pines del PIC correspondientes a cada tecla.

#define Nada   0  
#define Mas    1     // valores validos para Flag
#define Menos  2  

int Segs;            // Segundos.
int Minu;            // Minutos.
int Hora;            // Hora.
int Tmp;             // Temporal.
int Tecla;           // Tecla pulsada.
int anTecla;         // Tecla pulsada en la comprobacion anterior
int Tiempo;          // Tiempo transcurrido desde la ultima comprobacion
                     // de teclado.
int CuantoTiempo;    // Cuanto tiempo debe esperar para la
                     // proxima comprobacion.
int Flag;            // Flag para incrementar o decrementar
                     // el valor deseado.
int Set;             // Flag para seleccionar el valor a cambiar.

void main(){
   
   setup_oscillator(OSC_8MHz);
   
   set_tris_a(0);                // Puerto A como salida
   set_tris_b(0b00001111);       // Puerto B<7:4> salida B<3:0> entradas
   
   // Inicio Variables
   anTecla=255;
   Set=0;
   Hora=0;
   Minu=0;
   Segs=0;  
   
   
   do{   
   
      Tecla=0;
      if (input(Tec1))Tecla=1;        // Comprueba que pulsador se activó
      if (input(Tec2))Tecla=2;        // y lo guarda en Tecla
      if (input(Tec3))Tecla=3;
      if (input(Tec4))Tecla=4;        
      
      if (++Tiempo>CuantoTiempo||Tecla!=anTecla) {  // Incrementa el
                              // tiempo transcurrido, Si se pasa de
                              // CuantoTiempo o cambia el estado de
                              // de las teclas con respecto a la
                              // iteracion anterior.
Flag=Nada;                    // Limpia el flag
            
         if(Tecla!=0){                 // Si hay una tecla pulsada
            if(Tecla!=anTecla){        // si la tecla es la primera
                                       // vez que se pulsa.
               CuantoTiempo=100;       // establece el tiempo de
                                       // espera en 100.               
               if(Tecla==1){           // Si se pulsó la tecla 1
                  if(++Set>3) Set=1;   // Avanza el flag para setear
                                       // segs/minu/hora
               }
               if(Tecla==4) Set=0;     // Se pulsó la tecla 4, desactiva
                                       // el modo configuracion
            
            }else{                     // Si no es la primera vez que se
                                       // pulsa la tecla
               CuantoTiempo=30;        // la proxima comprobacion la
                                       // hará en menos tiempo.
            }
            
            if(Tecla==2) Flag=Menos;   // Si la tecla pulsada es la 2
                                       // flag de decremento
            if(Tecla==3) Flag=Mas;     // y si es la 3 flag de incremento
         }
         
         
         if (Set!=0){                  // Si está en modo configuracion
            
            if(Set==1) Tmp=Segs;       // Si se está configurando los
                                       // segundos Segs a temporal
            if(Set==2) Tmp=Minu;       // lo mismo si está configurando
                                       // los minutos
            if(Set==3) Tmp=Hora;       // o la hora
            
            if (Flag==Menos){          // si el flag es de decremento
               if(--Tmp>200)Tmp=59;    // le resta 1 al temporal si es
                                       // menor a 0 pasa a 59
               if(Set==3&&Tmp==59)Tmp=23;// Si está configurando las
                                       // horas el limite es 23
            }
            
            if (Flag==Mas){            // Si el flag es de incremento
               if(++Tmp>59)Tmp=0;      // Incrementa el temporal y si
                                       // se pasa de 59 vuelve a 0
               if(Set==3&&Tmp>23)Tmp=0;// Si configura las horas y
                                       // se pasa de 23 vuelve a 0
            }
            
            if(Set==1) Segs=Tmp;
            if(Set==2) Minu=Tmp;       // Guarda el valor temporal
            if(Set==3) Hora=Tmp;       // en donde corresponda...
         }      
         anTecla=Tecla;                // Almacena la tecla pulsada
                                       // para la próxima 
         Tiempo=0;                     // iteración, Tiempo a 0 para
                                       // volver a contar el tiempo
            
      }
      delay_ms(5);   // Entre iteración e iteración espera 5 ms que
                     // multiplicado por CuantoTiempo, es el tiempo
                     // que tarda en reaccionar a las pulsaciones y
                     // cuanto tarda en avanzar cuando se mantiene
                     // pulsado un botón.
     
   }while(true);
}

Y aquí un video del algoritmo implantado en un pseudo-reloj, en el ejemplo solo incluí la parte de los pulsadores y el display que están controlados con shift register.



4 comentarios:

  1. Francisco Hernandez19/12/12

    En que parte del código envias el BCD correspondiente y el multiplexeo para cada display?

    ResponderEliminar
  2. Anónimo5/6/13

    has probado algo mas simple para el antirrebote como:
    while (RA0==0){
    }
    while (RA0==1){
    delay_ms(5);
    }
    con esto esperas a que el pulsador sea soltado, es muy efectiva y simple

    ResponderEliminar
  3. bien anonimo como dijiste , es simple y efectivo

    ResponderEliminar
  4. hola amigos tengo un proyecto que realizar de tarea universitaria la verdad no se por donde comenzar dice asi:
    realisar un temporizador descendente de tiempo que cada vez que se al pulse un buton de entrada activa una salida de un led y empiece a sumar de 15,30,60,120,..... minutos cada vez que se pulse el botón pero que ademas guarde valores en caso de cortes de lus. teniendo encenta que por ejemplo si lleva 8 minutos de 15 al precionar el boton sume lo que lleva + el próximo valor de tiempo es decir 8+30 =38 y lo muestre en un display de 7 segmentos gracias y si alguien me puede ayudar se lo agradecería ya que no e podido realizar periodos de tiempo largos con delay_ms() solo alcanso tiempos no mayores de 3 minutos y la verdad no se que aser estoy desesperado

    ResponderEliminar

Tal vez le interese: