Rotary Encoders

Objetivos

 

  • Entender su modo de operación.
  • Presentar un programa que lo lea.
  •  

    Material requerido.

     

    Vista frontal Arduino UNO
    Vista Lateral Rotary Encoder

    Empezando con los Encoders

     

    No estoy muy seguro de como traducir Rotary Encoder del inglés. Tal vez ¿Codificador giratorio? De cualquier modo estos Encoders son cada vez más populares porque son bastante fácil usar y nos dan bastantes ventajas con relación a otros componentes como los potenciometros, y por alguna razón que se me escapa no se suelen usar mucho en proyectos DIY. A ver si podemos hacer un pequeño aporte al asunto y cambiar eso.

    Un Rotary Encoder es un dispositivo electro mecánico que convierte el movimiento de giro de un eje en una señal (Que puede ser analógica o digital dependiendo del tipo)  y genera una señal proporcional al giro de dicho eje. Se parece mucho a un potenciómetro, pero a diferencia de este, puede girar indefinidamente tanto en sentido del reloj como al contrario.

    En principio un Rotary encoder puede ser de varios tipos básicos como absolutos e incrementales. Los primeros proporcionan información absoluta con respecto a la marca de base del encoder, mientras que los segundos simplemente indican el giro con respecto a la posición anterior sin preocuparse de la referencia.

    Naturalmente los segundo son más baratos y nos vamos a centrar en ellos porque suelen ser más fáciles de conseguir (Y más accesibles)

    Un típico Rotary Encoder digital incremental, como el que nos ocupa, es un eje que gira sin límite y provoca, con unos pequeños micro interruptores una señal digital por cada muesca que gira(Un tren de pulsos cuadrados) similar al diagrama que os pongo aquí abajo:

    Detalle de pines

     

    Ejemplo de pulsos

    Dependiendo de la separación entre muescas, se producen más o menos pulsos por cada vuelta (Típicamente 20 como el que os mostramos) y además producen un ruidito de click muy agradable al girar además de producir un tacto de lo más simpático en los dedos, y encima dispone de un botón que podemos pulsar cuando queramos producir una señal (De fijado por ejemplo)

    Un modelo típico como el que tenemos en la tienda necesita alimentación y GND, y dispone de 3 salidas: Output A, Output B y Boton.

    ¿Por qué dos señales de salida en lugar de una? ¿No bastaría con una sola? Pues me temo que no, porque en ese caso no podríamos saber en dirección hemos girado el Encoder.

    Al disponer de dos salidas mecánicas similares, obtenemos dos pulsos diferentes que debidamente estudiados nos indican el sentido de giro además del número de pulsos que se ha girado, porque la señal de una salida estará necesariamente desfasada con respecto a la otra ya que primero pasamos por una muesca y luego por la otra. ¿Inteligente no? Fíjate en este gráfico en detalle que he pillado por ahí:

    Decalaje de los pulsos de salida

    Comprobando la secuencia de las dos señales podemos decidir en qué sentido estamos girando el Encoder, y contando los pulsos de cualquiera de las dos señales podemos calcular el número de clics girados una vez que conocemos el numero de clicks por vuelta completa.

    Pero es importante que sepas que necesitas conectar AMBAS señales de salida a tu Arduino y no creer que basta con una (Porque no sabrás en qué sentido gira el Encoder). Una vez puestas las bases vamos a ver las conexiones.

    Montando y programando

     

    La conexión de los elementos es trivial:

    Diagrama de conexiones

    Se trata simplemente de conectar las dos señales del Encoder a los pines 6 y 7 por ejemplo y el botón al 8 para poder leer el pulsador cuando sea preciso.

    En principio contar los pulsos que nos entrega el Encoder parece bastante fácil, pero aquí el truco esta en comprender como saber si está girando a la derecha o la izquierda y que es el desfase de las señales es la clave.  Volvamos a la imagen que os ponía arriba:

    Ejemplo de pulsos

    Supón que usamos dos variables llamadas aState y aLastState que la primera lee la situación actual del pulso en el output A y la siguiente registra el ultimo valor que leímos. Si son diferentes es que se ha girado el encoder.

    Si primero leemos el valor de aState para la salida A y la encontramos en HIGH, y si  ahora leemos el Output B y este está en LOW, significa que hemos girado en el sentido del reloj, porque A se ha levantado mientras B sigue en LOW. Más adelante A y B tomaran el mismo valor cuando la rueda alcance el switch B, pero por ahora solo nos interesa fijarnos en el primer momento en que ambos son diferentes.

    Si por el contrario cuando la salida en A y B son diferentes pero la salida B se ha activado antes es que giramos a contra reloj. Esta parte es fácil de entender. Pero ahora viene cuando la matan… ¿Cómo pasamos esto a código? Pues como siempre sin dificultad y mucha elegancia. Aquí tenemos el programa completo:

    Rotary_encoder_1

    y pasemos a verlo en un poco detalle.

    Empecemos definiendo algunas variables para controlar las dos salidas del encoder más el pulsador:

    #define outputA 6
    #define outputB 7
    #define boton 8

    Además necesitamos las variables que ya acabamos de mencionar:

    int counter = 0;
    int aState;
    int aLastState;

    Y vamos con el setup():

    void setup()
       {
           pinMode (outputA,INPUT);
           pinMode (outputB,INPUT);
           pinMode (boton, INPUT_PULLUP);
           Serial.begin (9600);
           aLastState = digitalRead(outputA);   //Leemos el valor incial
       }

    Definimos output A y B como entradas tranquilamente y como el pulsador es un botón con todos sus problemas pedimos a Arduino que monte una resistencia de  pullup para leerlo (Nos hemos hartado a hablar de esto). Activamos la puerta serie para sacar las lecturas del contador y leemos la situación de A cuando iniciamos.

    aState = digitalRead(outputA); // Leemos el ouputA
    if (aState != aLastState)
        { // Han girado el encoder         
        }

    Si la lectura actual y la guardada son diferentes es que ha llegado un pulso y ahora tenemos que comprobar si ha girado a favor o en contra del reloj:

    if (digitalRead(outputB) != aState)
        counter ++;
    else
        counter --;

    Solo llegamos a estas instrucciones cuando Ouput A esta en HIGH pero la última vez estaba en LOW. Por eso comparamos la lectura de la salida de B con la lectura de A. Si son diferentes B = LOW o sea aún no ha llegado el giro por lo que estamos girando a favor del reloj e incrementamos el contador.

    En caso contrario es que giramos al revés, disminuimos el contador y listo. El código montado queda así:

    aState = digitalRead(outputA);
    if (aState != aLastState)
       {
          if (digitalRead(outputB) != aState) 
              counter ++;
          else
              counter --;
    
          Serial.print("Position: ");
          Serial.println(counter);
       }
    aLastState = aState; // Guardamos el ultimo valor

    E imprimimos al final el valor del Contador. Solo nos queda recoger el pulsador y por ejemplo poner a cero el contador cuando se active

    bool B = digitalRead(boton);
    if ( !B )
        { Serial.println("Boton pulsado: Contador a 0");
          Counter = 0 ;
          delay(200);
        }

    Como hemos puesto un pullup en la entrada del botón este leerá un LOW cuando se pulse y por eso la condición es que se dispare cuando sea LOW.

    Lo del delay viene porque recordad que lo interruptores no son las maquinas ideales que nos gusta imaginar sino que sufren rebotes que conviene eliminar para evitar errores y una forma sencilla es meter un retraso antes de leer de nuevo el botón (Lo suyo sería un filtro RC resistencia condensador que igualase la caída de tensión al rebotar el botón, pero hoy no queremos nota)

    Ruido producido en la señal de un pulsador

    El resultado puede ser algo como esto cuando giras el Encoder en ambos sentidos. El contador se va incrementando o disminuyendo de forma consistente:

    Mensajes producidos al girar el rotary encoder

    Y cuando pulsas el botón central el contador se va a 0:

    Muestra de salida a consola

    Resumen de la sesión

     

  • Hemos visto lo ques un Rotary Encoder y para que sirve.
  • Presentamos una promera aproximacion a su modo de funcionamiento.
  • Escribimos un programa que lee en bucle su funcionamiento . [/three-fourth][margin value=»5″ /]
  •  

    Deja una respuesta