En cuanto pueda subiré unas fotos de como va la placa que gestiona los motores y si me da tiempo algun video. Por ahora os voy a comentar el programa en c que he creado en el PICC para recibir datos desde el puerto serie (rs232) y transformarlo en señales para los motores.
Lo primero que queria comentar es que el codigo me he basado en uno que hay hecho por Internet. Y he ido modificando cosas para poder aplicarlo a mi caso (que ha sido bastantes modificaciones).
Basicamente hay una funcion principal que activa los dos pwm(RC1 y RC2):
setup_ccp1(CCP_PWM); //ccp1 modo PWM
setup_ccp2(CCP_PWM); //ccp2 modo PWM
Inicializamos el TIMER2 y activamos dos interrupciones, las interrupciones globales y la de RDA que es cuando recibe datos por el puerto serie.
Despues el programa se queda en un bucle infinito esperando que hayan datos que procesar.
La interrupcion de rda (serial_isr();) se activa cuando llega algo por el puerto serie, conforme va recibiendo datos los va acumulando en un buffer para despues procesarlos.
Por funciones tenemos:
Inicializa --> que inicializa todas las variables globales de nuestro programa.
inicbuffer --> inicializa el buffer de caracteres leidos y lo pone todo a 0x00. Indispensable limpiarlo despues de usarlo, ya que se puede quedar basura que haga un funcionamiento anomalo.
addcbuffer --> Va añadiendo caracteres al buffer, en el caso de que un caracter sea un intro (0x0D) o un espacio (0x20) se corta la ejecucion para procesar los comandos.
aentero --> Convierte la cifra obtenida en caracteres a numero entero, aqui tambien vemos si el valor es negativo, en dicho caso el motor irá en sentido contrario.
procesa_comando --> Una vez que se han introducido los comandos esta funcion es la encargada de sacar los valores (iluminar leds) correspondientes que más adelante moverán los motores.
La forma de usar el programa es pasando valores por el puerto serie de la siguiente forma:
valor1 (espacio) valor2 (intro)
Por ejemplo para mover los motores hacia adelante de una forma continua podria ser:
50 50
Para mover un motor hacia adelante despacio y otro hacia atras muy rapido sería:
8 -100
A continuacion os pego el codigo entero del pic:
//-----------------------------------------------------------------
#include <16f876a.h> // Definiciones del PIC 16F876A
#include <
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT // Los Fuses de siempre
#use delay(clock=4000000) // Oscilador a 4 Mhz
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)// RS232 Estándar
// CONSTANTES /////////////////////////////////////////////////////////////////
int const lenbuff=5; // Longitud de buffer, Ajustar
// a lo que desees (o te sea posible)
// VARIABLES EN RAM ///////////////////////////////////////////////////////////
int motder,motizq;
int sentido, sentidoder, sentidoizq;
int xbuff=0x00; // Índice: siguiente char en cbuff
char cbuff[lenbuff]; // Buffer
char rcvchar=0x00; // último carácter recibido
int1 flagcommand=0; // Flag para indicar comando disponible
char arg[lenbuff]; // para pasar el negativo
// Declaración de Funciones ///////////////////////////////////////////////////
void inicializa(void);
void inicbuff(void); // Borra buffer
int addcbuff(char c); // añade carácter recibido al buffer
void procesa_comando(void); // Procesa comando
int aentero(void); // Pasa el buffer a un entero
// INTERRUPCIONES /////////////////////////////////////////////////////////////
#int_rda
void serial_isr() { // Interrupción recepción serie USART
rcvchar=0x00; // Inicializo carácter recibido
if(kbhit())
{ // Si hay algo pendiente de recibir ...
rcvchar=getc(); // lo descargo y ...
addcbuff(rcvchar); // lo añado al buffer y ...
printf("Recibo: %c ",rcvchar);
}
}
// Desarrollo de Funciones ////////////////////////////////////////////////////
void inicializa()
{
motder=motizq=0;
sentido=sentidoder=sentidoizq=0;
xbuff=0x00; // Índice: siguiente char en cbuff
inicbuff(); //char cbuff[lenbuff]; // Buffer
rcvchar=0x00; // último carácter recibido
flagcommand=0; // Flag para indicar comando disponible
}
void inicbuff(void) // Inicia a \0 cbuff -------------------
{
int i;
for(i=0;i
flagcommand=1; // Comando en Main
motizq=aentero(); // Paso a entero
sentidoizq=sentido;// Cambio sentido
inicbuff(); // Borra buffer
break;
case 0x20: // Espacio
motder=aentero(); // Paso a entero
sentidoder=sentido;// Cambio sentido
inicbuff(); // Borra buffer
break;
default:
cbuff[xbuff++]=c; // Añade carácter recibido al Buffer
}
}
int aentero () //pasa el buffer a un entero
{
int retorno,i;
if(cbuff[0]=='-')
{
sentido=0;
i=1;
do{ // Extraemos argumento del buffer
arg[i-1]=cbuff[i]; // copiamos a arg sin el '-'
}while(cbuff[++i ]!=0x00);
retorno=atoi(arg);
}
else
{
sentido=1;
retorno=atoi(cbuff);
}
printf("A entero: %d\n",retorno);
return retorno;
}
// Programa Principal /////////////////////////////////////////////////////////
void main()
{
setup_ccp1(CCP_PWM); //ccp1 modo PWM
setup_ccp2(CCP_PWM); //ccp2 modo PWM
setup_timer_2(T2_DIV_BY_16, 127, 1); // 488Hz (con XT=4MHz) esta frecuencia la podes variar cambiando los valores, fijate en el datasheet del micro que uses, que vienen las relaciones para calcular lo inherente a la frecuencia y al duty.
inicbuff(); // Borra buffer al inicio
printf("Soy el Pic y estoy activo\n");
enable_interrupts(int_rda); // Habilita Interrupción RDA
enable_interrupts(global); // Habilita interrupciones
do {
if(flagcommand) procesa_comando(); // Si hay comando pendiente
// de procesar ... lo procesa.
} while (TRUE);
}
// Procesador de Comandos /////////////////////////////////////////////////////
void procesa_comando(void)
{
flagcommand=0; // Desactivo flag de comando pendiente.
printf ("procesa comando: %d\n",motder);
printf ("procesa comando: %d\n",motizq);
if(sentidoder!=0)
{
printf ("Enciende DER\n");
output_high(PIN_C3);
}
else
{
printf ("Apaga DER\n");
output_low(PIN_C3);
}
set_pwm1_duty(motder); // Se cambia el ancho con el valor obtenido en canal 0.
if(sentidoizq!=0)
{
printf ("Enciende IZQ\n");
output_high(PIN_C4);
output_high(PIN_C5);
}
else
{
printf ("Apaga IZQ\n");
output_low(PIN_C4);
output_low(PIN_C5);
}
set_pwm2_duty(motizq); // Se cambia el ancho con el valor obtenido en canal 0.
inicializa(); // Borra buffer
}
--------------------------------
Espero que os sea de ayuda.
UN SALUDO
No hay comentarios:
Publicar un comentario