Programa Proton IDE PIC Encoder con un 16F876A, 16 bits de resolución, por bucle.

Device=16F876A
REMINDERS = FALSE
     Config XT_OSC, PWRTE_ON, CPD_OFF, WDT_OFF, BODEN_OFF, LVP_OFF
REMINDERS = TRUE
ALL_DIGITAL = TRUE 
TRISA  = %100011
TRISB  = %11111111
TRISC  = %11111111
PORTA.2 = 0        ' Motor parado.
PORTA.3 = 0
PORTA.4 = 0        ' Apaga el LED.
' ------------------------------------------------------------------------------------------------
Dim P    As  DWord ' Declaramos el valor de P como DWord (32 bits), posición final. 
Dim X    As  DWord ' Declaramos el valor de X como DWord (32 bits), posición actual.
Dim Aux  As  Byte  ' Se almacenará el valor anterior de RA0 y RA1, hasta la siguiente comparación.
Dim Enc  As  Byte  ' Se almacenará el valor actual de RA0 y RA1, hasta la siguiente comparación.
P=0                ' Ponemos todas las variables a cero.               
X=0
Aux=0              
Enc=0    
'------------------------------------------------------
Bucle:               ' Bucle infinito.
    ' ---------------- Decodificación del encoder. ----------------                   
     
    Aux = Enc        ' Igualamos 'AUX' y 'ENC' para luego comparar cuando cambie 'ENC'.               
    Enc = PORTA & 3  ' Aislamos RA0 y RA1 como un número de 2 bits y se carga en la variable 'ENC'.
    
    If Aux = 2 And Enc = 3 Then Inc X ' Si en la comparación hay flanco de subida, incrementamos X.                                    
    If Aux = 3 And Enc = 2 Then Dec X ' Si en la comparación hay flanco de bajada, decrementamos X.
    
    ' ---------------- Comparación para el control del Motor. ----------------
    
    If X = P Then
       PORTA.2 = 0     ' Motor Parado.
       PORTA.3 = 0
       
       P.BYTE0=PORTB   ' Carga Posición de 16 bits.
       P.BYTE1=PORTC
       
       PORTA.4 = 0     ' Apaga el LED indicando que ya ha llegado.
       GoTo Bucle
    EndIf
    
    PORTA.4 = 1        ' Enciende el LED indicando que se está posicionando.
    
    If X > 70000 Then  ' Si x<0, Motor hacia delante.
       PORTA.2 = 1
       PORTA.3 = 0
       GoTo Bucle
    EndIf
    
    If X > P Then      ' Si x>p, motor hacia atrás. 
       PORTA.2 = 0
       PORTA.3 = 1  
       GoTo Bucle
    EndIf
     
    If X < P Then      ' Si x<p, motor hacia delante.
       PORTA.2 = 1
       PORTA.3 = 0   
       GoTo Bucle
    EndIf
GoTo Bucle
End

Cuando programaba en Proton IDE no se podía utilizar números negativos, al menos con el compilador que tenía. Por esta razón hago un truco. Hoy en día ya no lo uso, y el programa tiene muchos años, es recopilado de aquella época cuando controlaba motores con este lenguaje de programación.

Jerarquía en las Comparaciones.

El orden de las comparaciones para controlar el motor es jerárquico. Si alteras ese orden podría no funcionar correctamente, especialmente cuando le pides al PIC que el motor vaya a la posición cero. La primera comparación ha de ser siempre la de -igual-: "If X = P Then...". La comparación -menor de cero-: "If X > 70000 Then..." ha de estar antes de -mayor que- "If X > P Then..." y de -menor que- "If X < P Then...". Esto es importante.

Una vez que el motor se pone en marcha adquiere inercia:

  • Imagina que queremos que el motor vaya a la posición 65.535. El PIC se pondrá a contar pulsos, comparará la posición actual con la posición final y hará que se dirija en un sentido. Cuando llega a la posición 65.535, el PIC le dice al motor que pare, pero el motor tiene una inercia y no lo hace de golpe, entonces sucede una cosa, y es que por esa inercia el motor da unas cuantas vueltas de más, por ejemplo, llega hasta la posición 65538. Cuando mires el programa verás que las variables X y P (posición actual y posición final respectivamente) se las declaran con 32 bits de resolución en vez de 16 y es por esta razón, para que el PIC pueda seguir contando más allá del límite 65.535.
  • Lo mismo sucede cuando le pedimos al PIC que el motor vaya hasta la posición cero. El PIC llevará al motor a esa posición, pero una vez que llega a cero, se pasará varias vueltas por la inercia. ¿Qué hay detrás de la posición cero? Podría comenzar con número negativos, pero existe otra forma de resolverlo y es la que aplico, siempre con números positivos. De la posición cero, si sigues restando, la siguiente es 4.294.967.295 (recuerda que declaramos las variables de posición actual y final con 32 bits de resolución) e imagina que por inercia llega hasta la posición 4.294.967.293. Necesitamos que el motor de la vuelta para ir hasta la posición cero. Entonces hacemos lo siguiente: Si Posición Actual es mayor de 70000 entonces hacer que gire el motor en sentido contrario. He puesto 70.000, pero puede ser cualquier número superior a 65.535 más las vueltas de inercia que pueda dar el motor. En la mayoría de los casos con 65.550 (en vez de 70.000) sería más que suficiente, pero como hay mucho margen he preferido 70.000 y me curo en salud. Si quieres modificar esta cifra, nunca uses números demasiado cercanos a 65.535 ni a 4.294.967.295.