En el apartado Encoder por Software se explicó cómo hacer que un microcontrolador (PIC) cuente pulsos, ahora vamos a concentrarnos en el control del motor. El PIC va a hacer tres cosas a la vez. La primera es leer los pulsos y transformarlo en la "posición actual del motor"; la segunda es cargar la posición final, que es la posición a la que queremos llevar el motor (número de vueltas o fracciones de ésta); y la tercera es el control del motor y avisar cuando esté posicionado.
Aunque veas muchas líneas en el esquema en realidad es muy sencillo de montar porque dos bits son para leer el encoder [RA0 y RA1], otros dos para controlar el motor [RA2 y RA3], un bit para un led [RA4] y todos los demás son los bits en paralelo de entrada de datos [RB0..RB7=D0..D7] y [RC0..RC7=D8..D15]. Como puedes comprobar todo va seguido y con un orden lógico.
El control del motor es muy simple. Se trata de comparar la posición actual (es la posición que está el motor en ese instante) con la posición final. Entonces podemos tener tres resultados: Puede ser mayor, menor o igual. Si la posición actual es mayor que la posición final el motor ha de girar en un sentido; si fuera menor ha de girar en sentido contrario; y si es igual el motor ha de parar. Para el control del motor sólo vamos a usar dos bits, el que indica "menor que" (RA2) y "mayor que" (RA3). El bit de "igual" (RA4) de momento le vamos a poner un LED para indicar que el motor ya ha llegado a la posición final.
Observa el programa:
Haz clic aquí para ver el código en versión Proton IDE.
Código fuente en CCS C.
#include <16F876A.h>
#FUSES NOWDT, XT, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=4000000)
#byte porta = 0x05 // Asignamos PortA.
#byte portb = 0x06 // Asignamos PortB.
#byte portc = 0x07 // Asignamos PortC.
void main()
{
port_b_pullups(false); // Configuramos todo digital.
setup_adc_ports(NO_ANALOGS);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_tris_a(0b100011);
set_tris_b(0b11111111);
set_tris_c(0b11111111);
signed int32 x=0; // Declaramos el valor de X con 32 bits, posición actual.
signed int32 p=0; // Declaramos el valor de P con 32 bits, posición final.
int8 aux=0; // Se almacenará el valor anterior de RA0 y RA1, hasta la siguiente
comparación.
int8 enc=0; // Se almacenará el valor actual de RA0 y RA1, hasta la siguiente
comparación.
while(true) // Bucle infinito.
{
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 && enc == 3) {x++;} // Si en la comparación hay flanco de subida, incrementamos X.
if(aux == 3 && enc == 2) {x--;} // Si en la comparación hay flanco de bajada, decrementamos X.
// ---------------- Comparación para el control del Motor. ----------------
if(x == p) // Si X=P, motor parado.
{
output_low (PIN_A2); // Motor parado.
output_low (PIN_A3);
p=make16(portc,portb); // Carga PortC como byte alto y PortB como byte bajo en la
variable P.
output_low (PIN_A4); // Apaga el LED indicando que ya ha llegado.
}
output_high (PIN_A4); // Enciende el LED indicando que se está posicionando.
if(x > p) // Si x>p, motor hacia atrás.
{
output_high (PIN_A2); // Motor hacia atrás.
output_low (PIN_A3);
}
if(x < p) // Si x<p, motor hacia adelante.
{
output_low (PIN_A2); // Motor hacia adelante.
output_high (PIN_A3);
}
}
}
Habrás observado que las variables que intervienen para contar y posicionar (x y p) están declaradas con 32 bits (con signo) en vez de 16. Esto es así para que el contador pueda contabilizar un poco más allá de 65535 (última posición posible con 16 bits) porque por inercia el motor siempre cuenta unos pulsos de más y necesitamos que pueda corregirse para alcanzar esa última posición. Por otra parte, están declaradas con signo para que pueda parar en la posición cero.
En la etapa de potencia uso un L293, pero puedes usar cualquier puente en H que se corresponda con la potencia del motor que vayas a usar. Lo único que has de tener presente es que cuando le entre un "11" tenga protección para evitar que se auto-cortocircuite. En puentes en H con protección, un "11" actúa como un "00", es decir, motor parado. El L293 tiene esta protección, al menos con la construcción que presento. Tiene dos puentes en H y uso los dos para un solo motor poniéndolos en paralelo, de esta forma soporta el doble de corriente.