Autor Tema: Optimizando la lectura de un pulsador  (Leído 1430 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Optimizando la lectura de un pulsador
« en: 16 de Mayo de 2014, 12:47:43 »
La lectura de un pulsador es una de las tareas más sencillas y prácticas a la que todos nos hemos enfrentado en nuestros comienzos.
Y una vez que te enfrentas a ello, lo que en principio parece muy obvio, te encuentras con distintos problemas y oportunidades de mejora que van complicando la tarea.

Por ejemplo, ¿no habéis tenido que programar un delay antirrebotes?, ¿no tenéis pulsadores en lógica directa y otros en lógica inversa?, ¿no os gustaría en determinadas acciones que vuestro pulsador tuviera autorrepetición?

Intentando dar servicio a estos problemas de una forma estándar y abierta he preparado la función que veis a continuación, y que está comentada para que sea más fácil de digerir.

Esta función está pensada para ser metida en un bucle, ya sea en el main o en una interrupción del timer, y ofrece:
  • la función devuelve un 1 tan pronto como recibe una pulsación
  • pero no admite otra pulsación válida hasta que se supere el periodo marcado como ANTIRREBOTES
  • si la tecla se mantiene pulsada, devolverá un 1 cuando toque hacer una autorrepetición, y un 0 durante las pausas. Estas pausas pueden ser configuradas en tres bloques en función del tiempo que el usuario mantenga la tecla apretada
  • también admite un parámetro que definirá si la tecla está en lógica directa o inversa

Seguro que se puede mejorar y optimizar, así que serán bienvenidas cuantas mejoras y ampliaciones que queráis hacerle.

Espero que os sea muy útil.

Código: [Seleccionar]
unsigned int1 Pulsacion(unsigned int8 Indice, unsigned int8 Pin, unsigned int1 TipoPin, unsigned int1 Logica) { 
   /*
      Esta función gestiona las entradas de pulsador, mediante el control de un retardo
      antirrebotes y con la opción de autorrepetición de hasta 3 velocidades
     
      Para que funcione, hay que dimensionar la variable Entradas con el nº de pulsadores
      que queramos controlar.
     
      ENTRADAS
         Indice: hace referencia al nº de pulsador a chequear
         Pin: indica el estado del pin del pulsador (lógica inversa)
         TipoPIN:
            TipoPin=0   -> No tiene autorrepetición
            TipoPin=1   -> Pin con autorrepetición   
         
      SALIDA
         La función devuelve un 1 si el pulsador está en condiciones de ser procesado
         y un 0 en caso contrario.
     
   */
   
   #define ANTIRREBOTES    20    // Nº de ciclos mínimo antes de detectar otra pulsación
   #define CAMBIO1         100   // Nº de ciclos para el primer intervalo
   #define CAMBIO2         500   // Nº de ciclos para el segundo intervalo
   #define CAMBIO3         2000  // Nº de ciclos para el tercer intervalo
   #define VELOCIDAD1      100   // Velocidad de autorrepetición más lenta
   #define VELOCIDAD2      50    // Velocidad de autorrepetición mediana
   #define VELOCIDAD3      10    // Velocidad de autorrepetición más rápida
   #define SIN_REPETICION  0     // La tecla no repite si se mantiene pulsada
   #define CON_REPETICION  1     // La tecla sí repite si se mantiene pulsada
   #define LOGICA_DIRECTA  0     // Al pulsar se recibe un 0
   #define LOGICA_INVERSA  1     // Al pulsar se recibe un 1
   
   static unsigned int16 Entradas[5]={0,0,0,0,0};  // Dimensionar en función del nº de pulsadores
   unsigned int16 j;
   unsigned int1 resultado=0;
   
   j=Entradas[Indice];  // Como leemos muchas veces el array, lo pasamos a variable local para
                        // incrementar la velocidad de ejecución
                       
   // Si se detecta pulsación y antes no había, devolvemos un 1 en resultado
   if ((((!Pin && Logica==LOGICA_INVERSA) || (Pin && Logica==LOGICA_DIRECTA)) && (j==0))) {
         resultado=1;
         j=1;
   };
   
   // Cada vez que se entra a la función se incrementa una unidad el array
   if (j>0)
         Entradas[Indice]++;
   
   // Si se detecta que ya no se está pulsando, inicializamos a 0 el array
   if (((Pin && Logica==LOGICA_INVERSA) || (!Pin && Logica==LOGICA_DIRECTA)) && j>ANTIRREBOTES)
      Entradas[Indice]=0;
     
   if (TipoPin) { // Si el pulsador tiene autorrepetición
      // Cuando se supera el nº de ciclos 3, devolveremos un 1 con la frecuencia VELOCIDAD3
      if ((j>=CAMBIO3) && !(j%VELOCIDAD3)){           
         resultado=1;
      } else
         // Cuando se supera el nº de ciclos 2, devolveremos un 1 con la frecuencia VELOCIDAD2
         if ((j>=CAMBIO2) && !(j%VELOCIDAD2)){
            resultado=1;
      } else
         // Cuando se supera el nº de ciclos 1, devolveremos un 1 con la frecuencia VELOCIDAD1
         if ((j>CAMBIO1) && !(j%VELOCIDAD1)){
            resultado=1;
      };
   }
   
   return (resultado);
}


Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: Optimizando la lectura de un pulsador
« Respuesta #1 en: 16 de Mayo de 2014, 13:32:56 »
Hoy mismo la probaré
gracias por compartir Nocturno
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Optimizando la lectura de un pulsador
« Respuesta #2 en: 16 de Mayo de 2014, 17:20:01 »
que bien!, incluye todas las opciones en una función. Gracias Manolo!!
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: Optimizando la lectura de un pulsador
« Respuesta #3 en: 16 de Mayo de 2014, 18:43:38 »
Muy bien mano,

gracias por compartirlo. Hace algunos años compartí una subrutina mía, pero estaba orientada a dos pulsadores, y permitía registrar los eventos:

1) pulsación corta del pulsador A;
2) pulsación corta del pulsador B;
3) pulsación larga (c/ repetición) del pulsador A;
4) pulsación larga (c/ repetición) del pulsador A;
5) pulsador A mantenido y se presiona el B;
6) pulsador B mantenido y se presiona el A;
7) ambos A y B mantenidos;

Creo que esas eran todas.

Si sirve la vuelvo a colgar, aunque era más rebuscado el código que el tuyo.

Saludos!

"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Optimizando la lectura de un pulsador
« Respuesta #4 en: 18 de Mayo de 2014, 07:39:37 »
He colgado un vídeo demostrando el funcionamiento de la función y el código fuente que he usado en el ejemplo.

Podéis verlo aquí:
http://www.micropic.es/mpblog/2014/05/gestion-de-pulsadores/