Sensor encoder rotativo, Pic C Compiler

En esta sección aprenderás a programar un sensor encoder rotativo para detectar el giro del sensor mediante la lectura de las señales digitales «CLK» y «DT», y también detectar la señal del botón integrado mediante la lectura de la señal digital «SW». El objetivo es incrementar, decrementar y resetear una variable dependiendo de las señales generadas.

Encoder rotativo

El encoder rotativo KY-040 es un tipo común de encoder rotativo que utiliza tecnología óptica. Es ampliamente utilizado en proyectos de electrónica y prototipado, ya que es fácil de encontrar y trabajar con él. El KY-040 consta de un disco codificador con patrones y una serie de pines que proporcionan señales de salida para medir la rotación.

El KY-040 suele ser un encoder incremental, lo que significa que proporciona información sobre el movimiento relativo del eje en forma de pulsos. Tiene dos canales A y B, que generan señales en cuadratura cuando el disco codificador gira. Estas señales en cuadratura se utilizan para determinar la dirección de rotación y la velocidad del eje.

Además de los pines A y B, el KY-040 también tiene un pin de interruptor o botón que se activa al presionar el eje del encoder. Este botón a menudo se utiliza para realizar funciones adicionales, como selección de modo o cambio de parámetros en un sistema.

Características

  • Voltaje de Alimentación: 5v
  • Corriente: 10 mA
  • Desfase entre señal A y B: 90°
  • Rotación Angular: 30°
  • Ciclos por Resolución (CPR): 20
  • Dimensiones: 20 x 30 x 30 mm
  • Peso: 9 g

Funcionamiento 

El sensor rotativo tiene salidas digitales en los pines «CLK» y «DT», y dependiendo de la respuesta de las señales, se puede determinar el sentido de giro del sensor:

Si el flanco de subida o bajada de la señal DT esta adelantada con respecto a la señal del pin CLK, se determina que el sensor gira en sentido «horario». 

Si el flanco de subida o bajada de la señal DT esta atrasada con respecto a la señal del pin CLK, se determina que el sensor gira en sentido «anti-horario».

El tiempo de desfase entre los pines CLK y DT, depende de la velocidad de giro del sensor.

En las imágenes siguientes se muestra un ejemplo de la salida de las señales.

Si se gira «rápidamente» el sensor, el tiempo sera aproximadamente de 3 milisegundos.

Si se gira «lentamente» el sensor, el tiempo sera aproximadamente de 20 milisegundos.

El sensor puede generar rebotes de señal en los flancos de subida o bajada, debido a que funciona con partes mecánicas, por lo que se deben tomar en cuenta para evitar errores en la lectura de las señales.

El sensor cuenta con un pin de salida digital «SW» que corresponde a un «switch» o botón. 

La salida de la señal del pin «SW», se debe conectar en una configuración PULL UP para detectar los cambios en la señal cuando se pulse el botón.

Si no esta pulsado el botón, la salida de la señal en el pin «SW» sera «1» o «HIGH».

Si esta pulsado el botón, la salida de la señal en el pin «SW» sera «0» o «LOW.

Circuito de conexión

Procedimiento

Se definen los pines de entrada conectados a los pines del sensor.


#define CLK input(pin_b0)
#define DT input(pin_b1)
#define SW input(pin_b2)

Se declara una variable global que se incrementara o decrementara dependiendo del sentido de giro del sensor.


int8 valor = 0;

Habilitamos las interrupciones externas para el pin de «CLK»  y el pin «SW».


   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_EXT2_H2L);

Cuando se detecta un flanco de subida en el pin de interrupción externa «INT0» que corresponde a la señal del pin «CLK» se habilita la interrupción externa y el programa se dirige a la directiva de la interrupción «#INT_EXT».

Inicialmente de deja un «delay_ms()» para evitar los rebotes de señal, después se asegura que la señal de «CLK» siga en un pulso de subida esto para evitar que se este detectando un rebote de señal en un pulso de bajada, finalmente realiza una sentencia para hacer la lectura del pin «DT», si el pin de «DT» es «1» o «HIGH», el valor de la variable «valor» se decrementara, porque el sensor se esta girando en sentido anti-horario, si el pin de «DT» es «0» o «LOW»,  el valor de la variable «valor» se incrementara porque el sensor se esta girando en sentido horario.


#INT_EXT
void Interrupt_CLK()
{
   delay_ms(2); //antirrebote
   if(CLK)
   {
       if(DT)
       {
         valor--;
       }else
       {
         valor++;
       }
   }
}

Cuando se detecta un flanco de subida en el pin de interrupción externa «INT2» que corresponde a la señal del pin «SW» se habilita la interrupción externa y el programa se dirige a la directiva de la interrupción «#INT_EXT».

La función del botón sera de resetear a «o» el valor de la variable «valor».


#INT_EXT2
void Interrupt_LED()
{
   delay_ms(1);//antirrebote
   valor=0;
}

Finalmente se muestra el valor de la variable «valor» en la pantalla OLED.


void mostrar()
{
   char texto[20];

   sprintf(texto,"Valor:%03u",valor);
   OLED_DrawText(1,1,texto,1);

   OLED_Display();//Muestra la información en pantalla;
}

Código completo


#FUSES NOMCLR

#use i2c(Master,Fast, sda=PIN_D3, scl=PIN_D2, force_sw, stream=OLED_stream)//parametros I2C

//#define SH1106_128_64
//#define SSD1306_128_64
#define SSD1306_128_32 //DEFINE EL MODELO DE LA PANTALLA OLED

#include "OLED_I2C.c" //libreria oled I2C

#define CLK input(pin_b0)
#define DT input(pin_b1)
#define SW input(pin_b2)

int8 valor = 0;

#INT_EXT2
void Interrupt_LED()
{
   delay_ms(1);//antirrebote
   valor=0;
}

#INT_EXT
void Interrupt_CLK()
{
   delay_ms(2); //antirrebote
   if(CLK)
   {
       if(DT)
       {
         valor--;
       }else
       {
         valor++;
       }
   }
}

void mostrar()
{
   char texto[20];

   sprintf(texto,"Valor:%03u",valor);
   OLED_DrawText(1,1,texto,1);

   OLED_Display();//Muestra la información en pantalla;
}

void main()
{
   OLED_Begin();
   OLED_ClearDisplay();

   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_EXT2_H2L);

   while(TRUE)
   {
      mostrar();
   }

}
Scroll al inicio