martes, 4 de diciembre de 2007

cambio comunicacion puerto serie

Hola a todos,

He cambiado el protocolo de comunicación del puerto serie. Lo he hecho mas que nada pensando en un mejor rendimiento de la comunicación. Antiguamente enviaba carácter a carácter desde el puerto serie del ordenado a la placa controladora de motores y el pic era el que daba confirmaciones de envío.


El esquema como recordatorio es algo así:


El cambio reside pues en la forma de envío. A partir de ahora no se hará de carácter a carácter, sino que se enviará una trama entera y es el pic el encargado de interpretarla, definiendo así nuestro propio protocolo.

La trama enviada tiene tres limitadores. Primero una "d" indicando que se refiere al motor derecho, despues va un numero (negativo o positivo) de 0 hasta 127 que indica la potencia del motor derecho. Luego hay un limitador "i" indicando que se refiere al motor izquierdo, al igual que antes después aparece un numero que indica la potencia de dicho motor. El ultimo carácter de la trama es el limitador "f", que indica que la trama ha finalizado.

Un ejemplo de trama:

d

2

5

i

-

6

4

f


Por supuesto que la longitud de la trama es variable, ponemos la máxima dimensión y la mínima:

d

-

1

1

5

i

-

1

2

7

f

d

5

i

7

f


Por ultimo y si por si es de ayuda os posteo el código del pic para recibir las tramas, interpretarlas y crear los impulsos necesarios para el control de los motores:


/*
----------------------------------------------------------------------
#include <16f876a.h> // Definiciones del PIC 16F876A
#include // Para el atoi
#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=12; // Longitud de buffer--> Ajustar



// 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
int cont=0; // contador de recibidos




// 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
int procesatrama(void); // Procesa una trama recibida


// INTERRUPCIONES /////////////////////////////////////////////////////////////


#int_rda

void serial_isr() // Interrupción recepción serie USART
{
while ( cbuff[cont-1]!='f' ) // entramos al bucle while
{
if ( kbhit () )
{
cbuff[cont]=getc(); // en la variable keypress se guardan los caracteres
cont++;
}
}
printf("Recibo: %s ",cbuff);
cont=0;
flagcommand=1; // Comando en Main
procesatrama(); //procesa la trama
inicbuff(); // Borra buffer
}




// 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 Recibo d: %c ",cbuff[contador]);

contador++; //1

if(cbuff[contador]=='-')
{
sentidoder=0;
contador++;
printf("PT--> Recibo negativo der");
}
else
sentidoder=1;

i=0;

do
{ // Extraemos argumento D del buffer
arg[i]=cbuff[contador];
i++;
printf("PT--> Recibo num der: %c ",cbuff[contador]);
}while(cbuff[++contador ]!='i'); // hasta que llegue I


motder=atoi(arg); //valor motor derecha

printf("PT--> Mot der: %d ",motder);

//inicbuff(); //iniciamos el buffer de arg

for(i=0;i Recibo i: %c ",cbuff[contador]);

contador++; //en izq

if(cbuff[contador]=='-')
{
printf("PT--> Recibo negativo izq");
sentidoizq=0;
contador++;
}
else
sentidoizq=1;

i=0;

do
{ // Extraemos argumento D del buffer
arg[i]=cbuff[contador];
i++;
printf("PT--> Recibo num izq: %c ",cbuff[contador]);
contador++;
}while(cbuff[contador]!='f' && cbuff[contador]!=0x00); // hasta que llegue F


motizq=atoi(arg); //valor motor derecha

printf("PT--> Mot izq: %d ",motizq);

retorno = 1;
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
}

----------------------------------------------------------------------
*/