Cinco Encoders y un sólo PIC

Vamos a controlar varios encoders con un sólo PIC y veremos los datos en un LCD estándar. Usaré encoders mecánicos o también llamados "tipo potenciómetro", en el que además tiene la peculiaridad de que si pulsas el eje (en vez de girar, pulsar) activas un pulsador que está integrado en él. Esta última característica servirá para poner a cero individualmente el contador correspondiente. Uso el PIC 16F876A porque tiene suficientes entradas/salidas para este propósito.

Cuando queremos controlar más de un encoder con un sólo PIC el programa ha de ser por bucle infinito, o dicho de otro modo, ha de comprobar en todo momento lo que sucede en las entradas del PIC y mostrar resultados. Si el programa detecta un cambio se incrementará o decrementará el contador correspondiente y seguidamente lo representará en el LCD. Haciendo clic aquí te llevará a una introducción del método "bucle infinito". No es posible (al menos de forma sencilla) usar el método de interrupción externa para controlar más de un encoder a la vez.

Vídeo de muestra de funcionamiento.

Uso un LCD de dos líneas y cada línea puede contener hasta 16 caracteres alfanuméricos (16X2). Es un LCD llamado HD44780 que compré en eBay por menos de tres euros con los gastos de envío incluido en el precio.

Los encoders mecánicos que uso dan una resolución de 20 pulsos por vuelta. En la imagen de abajo puedes ver un encoder por dentro. El brillo se debe a una grasilla que sirve para minimizar el rozamiento de las escobillas con los contactos. Tiene una bolita que hace que el encoder sólo pueda girar si le aplicas un poco de fuerza.

Interior de un encoder mecánico o "tipo potenciómetro".

Pasemos a ver el programa.

Haz clic aquí para ver el código en CCS C.

Programa cinco Encoder con un sólo PIC en Proton IDE:

The translation could modify the code. Use the code without translating.
Device = 16F876A
REMINDERS = FALSE
Config XT_OSC, PWRTE_ON, CPD_OFF, WDT_OFF, BODEN_OFF, LVP_OFF
REMINDERS = TRUE

XTAL = 4             ' Indicamos el cristal que vamos a usar.   
TRISA  = %000000     ' Todo el PortA como salidas.
TRISB  = %11111111   ' Todo el PortB como entradas.
TRISC  = %11111111   ' Todo el PortC como entradas.
ALL_DIGITAL = True   ' Todas las entradas/salidas son digitales.
LCD_TYPE = 0         ' Configurado como LCD alfanumérico.
LCD_INTERFACE = 4    ' Sólo 4 entradas de datos.
LCD_LINES = 2        ' Es de dos líneas.
LCD_DTPIN = PORTA.0  ' Indica el primer bit de datos, de los 4 que tiene, para el LCD.
LCD_RSPIN = PORTA.4  ' Indica qué bit del PIC se usará como RS para el LCD.
LCD_ENPIN = PORTA.5  ' Indica qué bit del PIC se usará como EN para el LCD.

Dim X1   As Word
Dim X2   As Word
Dim X3   As Word
Dim X4   As Word
Dim X5   As Word
Dim Q    As Word
Dim Aux1 As byte
Dim Aux2 As byte
Dim Aux3 As byte
Dim Aux4 As byte
Dim Aux5 As byte
Dim Enc1 As byte
Dim Enc2 As byte
Dim Enc3 As byte
Dim Enc4 As byte
Dim Enc5 As byte

X1  =0: X2  =0: X3  =0: X4  =0: X5  =0 ' Ponemos todas las varibales a cero.
Aux1=0: Aux2=0: Aux3=0: Aux4=0: Aux5=0
Enc1=0: Enc2=0: Enc3=0: Enc4=0: Enc5=0

Cls                                    ' Borra el contenido visual del LCD.
Print At 1, 6,  "Hola!"                ' Al comienzo veremos un saludo
DelayMS 2000                           ' durante dos segundos.
Cls
DelayMS 250
Print At 1, 1,  DEC4 X1, " ", DEC4 X2, " ", DEC4 X3 ' Inicialmente escribe el contenido
Print At 2, 1,  DEC4 X4, " ", DEC4 X5               ' de todos los contadores.
                    
While 1=1                                           ' Bucle infinito.
     
     Aux1 = Enc1                                    ' Igualamos para luego saber si hay cambios en
                                                    ' el encoder.   
     Enc1 = PORTB & 3                               ' Aislamos los dos primeros bits de PortB.
     Q=X1                                           ' Igualamos para luego saber si hay cambios en
                                                    ' el contador.
     If Aux1 = 2   And Enc1 = 3    Then Inc X1      ' Si hay flanco de subida, incrementa el
                                                    ' contador.
     If Aux1 = 3   And Enc1 = 2    Then Dec X1      ' Si hay flanco de bajada, decrementa el
                                                    ' contador.
     If X1=65535 Then X1=9999                       ' Si es menor de cero, cargar el valor máximo
                                                    ' 9999.
     If PORTC.7=0                  Then X1=0        ' Si se ha pulsado el encoder, poner a cero el
                                                    ' contador.
     If Q<>X1 Then Print At 1, 1,  DEC4 X1          ' Si hay cambios en el contador, visualizar la
                                                    ' cantidad en el LCD.
     
     Aux2 = Enc2                                    ' Todo lo demás es lo mismo. Sólo cambia los
                                                    ' nombres de las
     Enc2 = PORTB & 12                              ' variables y el aislamiento de pares de bits
                                                    ' que corresponde
     Q=X2                                           ' con el encoder de turno.
     If Aux2 = 8   And Enc2 = 12   Then Inc X2
     If Aux2 = 12  And Enc2 = 8    Then Dec X2
     If X2=65535 Then X2=9999
     If PORTC.6=0                  Then X2=0
     If Q<>X2 Then Print At 1, 6,  DEC4 X2
     
     Aux3 = Enc3
     Enc3 = PORTB & 48
     Q=X3
     If Aux3 = 32  And Enc3 = 48   Then Inc X3
     If Aux3 = 48  And Enc3 = 32   Then Dec X3
     If X3=65535 Then X3=9999
     If PORTC.5=0                  Then X3=0
     If Q<>X3 Then Print At 1, 11, DEC4 X3
     
     Aux4 = Enc4
     Enc4 = PORTB & 192
     Q=X4
     If Aux4 = 128 And Enc4 = 192  Then Inc X4
     If Aux4 = 192 And Enc4 = 128  Then Dec X4
     If X4=65535 Then X4=9999
     If PORTC.4=0                  Then X4=0
     If Q<>X4 Then Print At 2, 1,  DEC4 X4
     
     Aux5 = Enc5                                   
     Enc5 = PORTC & 3
     Q=X5
     If Aux5 = 2   And Enc5 = 3    Then Inc X5
     If Aux5 = 3   And Enc5 = 2    Then Dec X5
     If X5=65535 Then X5=9999
     If PORTC.3=0                  Then X5=0
     If Q<>X5 Then Print At 2, 6,  DEC4 X5
Wend

End

Como necesitamos dos entradas para poder leer un encoder, hemos de separar de dos en dos bits el puerto de entrada RB y usaremos los dos primeros bits de RC para añadir el quinto encoder. El resto de bits del puerto RC nos servirá para leer el reset correspondiente. Si no hubiera usado los bits de resets se podrían haber aprovechado para añadir más encoders. Con el PIC 16F876A podemos obtener hasta 8 encoders en total sin reset. Con los reset individuales para cada contador, he querido hacer un ejercicio más completo y práctico, sin añadir al programa demasiada dificultad.

La resolución de todos los encoders es de 10.000 posiciones posibles (de 0 a 9.999). Hubiese querido hacerlo con todo el rango de los 16 bits (65.536 posiciones posibles) pero no se puede en una LCD de 16x2 porque contendrían cinco dígitos cada contador y no cabrían, así que tuve que reducirles un dígito para poder representar los cinco contadores-encoders. Por esta razón en el programa verás que cuando el PIC pasa de cero (hacia atrás) a 65.535 (que es la resolución máxima) hemos de llevar esa resolución a 9.999 al instante:

If X1=65535 Then X1=9999

X1 es el contador del primer encoder, X2 del segundo y así sucesivamente. Por otra parte, observa que los bits de reset comienza en RC7; por ello RC7 se corresponde con el reset del primer contador (X1), RC6 con el segundo (X2), y así sucesivamente.

Si lo deseas, puedes montar el circuito parcialmente, para un sólo encoder o dos...; aquí está limitado hasta 5. La única condición es no dejar patillas del PIC sueltas al aire, es decir, que han de estar polarizadas con una resistencia a positivo. O bien, otra opción, si vas a usar menos de 5 encoders, eliminar las partes del programa que no serían usadas.

En el esquema verás dos redes de resistencias de 8 salidas cada una de ellas, el noveno pin es la que va a positivo. Son importantes estas resistencias. Las puedes construir tu mismo si lo deseas, o usar las que ya vienen integradas; son muy cómodas. Éstas llevan un puntito que indica cual es el pin que va directo a VCC.

La única patilla del PIC que queda sin uso y en el programa está configurada como entrada de datos es RC2.

Nota importante:

Si hablamos de precisión, este proyecto es sólo válido para movimientos lentos, en plan control de volumen del sonido. No es posible utilizarlo con precisión para contar a partir de ciertas velocidades por una sencilla razón: La utilización de un LCD hace que la ejecución del programa se ralentice notablemente. Para poder contar rápidamente usando una LCD se necesitaría utilizar la interrupción externa (RB0/Int) como contador, y los PICs normalmente sólo tienen una patilla de interrupción, por tanto sólo se podría utilizar un encoder y no cinco como en este caso.