RobotyPic son proyectos básicos de electrónica con microcontroladores PIC, de aplicación en el mundo de la robótica didáctica, con archivos fuente creados mediante el compilador CCS PIC C COMPILER en lenguajeC.

Transmisión variable tipo "float" por RS232

En esta ocasión se trata de transmitir una variable tipo float a través del bus RS232 entre dos PICs. Concretamente el proyecto consiste en la lectura de un valor analógico de tensión con signo y decimales a través del conversor AD del PIC emisor. El PIC receptor recibe este valor y lo muestra en la pantalla LCD.

Pulsa en la imagen para ampliarla

El procedimiento va a ser:

1º se obtiene la lectura y se guarda en una variable tipo float.
2º se transforma el valor numérico de la variable float en un valor tipo string o cadena de caracteres
3º se transmite por RS232 carácter a carácter toda la cadena de caracteres
4º se recibe carácter a carácter toda la cadena
5º finalizada la recepción de toda la cadena se convierte a su valor numérico tipo float.
6º se muestra este valor por el LCD
  
Almacenado el dato de la lectura en la variable “valor” de tipo float, se transforma a formato string en la variable “string” mediante el siguiente procedimiento :

sprintf(string,"%01.2f",valor);     

Ahora ya se puede enviar carácter a carácter por RS232:

for (i=0;i<=5;++i){
    putc(cadena[i]);
    delay_ms(150);
}

i establece el número de orden del carácter. En total serán 5; uno para el signo, otro para el valor entero, uno más para el punto decimal y dos para la parte decimal.

Cuando el valor float es negativo, el signo negativo aparece por defecto. Pero cuando es positivo, el signo está omitido. Para que en este caso el string mantenga el mismo formato de 5 caracteres, el signo habrá que añadirlo, o mejor dicho, al signo ‘+’ añadirle el “valor numérico”:

if (valor>0) {
    strcpy(cadena,"+");         //En "cadena" caracter +
    strcat (cadena,string);       //Al signo + se añade el valor numérico
}

La recepción en el otro PIC se produce por medio de la interrupción  #int_RDA.
  
Deberá recibir la misma cantidad de caracteres enviados por el PIC emisor, es decir, 5 caracteres organizados en el array cadena[ ]  por el valor i. 

cadena[i]=getc();     //Recepción del string         
++i;                  //Preparación para recibir el siguiente carácter

Recibidos todos los caracteres indicados por la variable i, se puede ya convertir la cadena de caracteres recibida a su valor numérico tipo float original y guardarla en la variable “valor”.  La certificación del valor recibido se establece por su representación en el LCD.

if (i==6) {                     //Todos los caracteres recibidos
   i=0;                         //Preparación para recibir el siguiente string
   valor = atof(cadena);        //Paso del string a su valor float
   printf(lcd_putc,"\fVoltage recibido"); //Muestra en display mensaje
   printf(lcd_putc,"\n%01.2fV",valor);    //Muestra en display valor float
}



[+/-] Ver / Ocultar programa PIC emisor completo en C


[+/-] Ver / Ocultar programa PIC receptor completo en C



En esta simulación bajo proteus se puede ver el funcionamiento:




Y en el siguiente enlace, la descarga de los archivos del proyecto:

Descargar archivos Transmisión float por RS232


El proyecto contenido en el artículo ha sido diseñado y probado con éxito utilizando las siguientes versiones de software:
- Windows xp y windows 7
- Proteus V7.7 SP2
- CCS PIC C COMPILER v4.084


13 comentarios:

dark dijo...

hola muy buen aporte estoy haciendo algo similiar con 3 pic quiero saber como hacer para q el primer pic mande dato y luego el otro para luego hacer una operacion con los datos recibidos si pudieras ayudarme como mandar el dota1 lyego el dota2 es lo q me detiene gracias!

Robotypic dijo...

Hola dark.
Si los dos valores salen del mismo PIC, podrías mandarlos juntos como una única cadena de datos separados por un caracter especial; por ejemplo # o cualquier otro. El PIC que los recibe identificar ese caracter para separar los dos valores como numeros diferentes.

Merlín dijo...

Hola Robotypic te cuento que yo también intento separar 3 variables con el método que comentas con un caracter (X,Y,Z) como identificador de cada una de las variables, eh estado probando código como loco pero no logro hacer que funcione, crees que podrías compartirme un ejemplo u orientarme de cómo se hace esto en la interrupción #int_RDA.

Lo que probé fue esto.
#int_rda
rda_isr()
{
dato=getc();

if(dato=='X')
EjeX=getc();
else if(dato=='Y')
EjeY=getc();
else if(dato=='Z')
EjeZ=getc();
}
Pero con esto solo puedo recibir un caracter luego del identificador, además me muestra el decimal ASCII no el número que mando es decir si mando "X5" recibo en la variable EjeX "53" que es el ASCII del número 5 que mande, y yo necesito 3 números ya que pretendo recibir valores de 0-255.

Resumiendo tengo dos problemas.

1.- poder recibir un 1 si mando 1 ó 5 si mando 5.
2.- poder recibir 3 números en cada variable eliminando el identificador.

Robotypic dijo...

Hola Merlin.

Una opción:
- Envía la variable como una cadena de caracteres; por ejemplo X214.
- En el receptor recibe la cadena carácter a carácter guardandolos en un array...
cadena[i] = getc();
i++;
...hasta que i=4
- Identifica el primer caracter del array. (X) para saber de que coordenada se trata, guardalo en una variable y acontinuación eliminalo del array.
i=i+1
- Te queda un array con el valor 214.
- Coge el primer carácter (2), pásalo a su valor numérico con la función atoi() y multiplicalo por 100. Guardalo en una variable. Tendrás en esa variable el número 200
- lo mismo para el siguiente caracter pero multiplicandolo por 10.
- Y el último solo con la función atoi().
- Suma las tres variables y te quedará el número 214
- Te habrá quedado por un lado una variable con la coordenada (X) y por otro otra variable con el valor (214)

Merlín dijo...

Hola Robotypic, reacias por tu apoyo te cuento que intente hacer lo que me comentas pero tengo problemas, esto es lo que hice pero no logro obtener los tres números en decimal.

void RDA_isr(){

cadena[i]=getc(); // Recepción del string
printf("\n\rEste es el carcter %c",cadena[i]);
++i; // Preparación para recibir el siguiente caracter
ID=cadena[0]; // Identifica el primer caracter del array y lo guarda en ID
if (i==4) {
// Todos los caracteres recibidos separados

C1=cadena[1];
printf("\n\rC1 %c",C1);
C2=cadena[2];
printf("\n\rC2 %c",C2);
C3=cadena[3];
printf("\n\rC3 %c",C3);

C1f= atoi(C1);
printf("\n\rC1f %u",C1f);
C2f= atoi(C2);
printf("\n\rC2f %u",C2f);
C3f= atoi(C3);
printf("\n\rC3f %u",C3f);

i=0; // Preparación para recibir el siguiente string

C1f=(C1f*100);
C2f=(C2f*10);

val=C1f+C2f+C3f;
valor = atoi(val); // Paso del string a su valor float

printf("\n\rQueda %s",cadena);
printf("\n\rVal = %u",val);
printf("\n\rDecimal %u ID=%c ",valor,ID);
}

}

no se como eliminar el ID y dejar solo el valor de tres dígitos en una sola variable int, espero puedas orientarme un poco más gracias.

Robotypic dijo...

Merlin.

Según tu programa ya tienes separado el valor numérico decimal en la variable val y el identifiador en ID.

Merlín dijo...

Hola Robotypic, según yo así debería funcionar pero no me da el valor en “Val” cuando lo mando imprimir me da Val = 0, mira esto es lo que me muestra por el hyperterminal.

Este es el caracter Z
Este es el caracter Z
Este es el caracter Z
Este es el caracter Z
C1 1
C2 2
C3 3
C1f 0
C2f 0
C3f 0
Queda Z123
Val = 0
Decimal 0 ID=Z

Tampoco me da un valor en C1,C2,C3 en todos me da cero si estoy mandando Z123 en ID guardo Z eso ya está, pero en “Val” debería tener 123 pero me da Val = 0, y en C1f devería ser 1, C2f devería ser 2, C3f devería ser 3 que crees que esté haciendo mal ?

gracias por tu apoyo amigo.

Merlín dijo...

Olvide comentarte que solo me permite imprimir variables chart, si lo notas las variables C1f,C2f,C3f y Val son int y no muestra ningún caracter numerico.

Robotypic dijo...

Si solo te muestra Z en los primeros printf es que no recibes los valores. Los printf consumen mucho tiempo, es probable que te llegue el siguiente caracter antes de terminar toda la secuencia en el receptor. Dale suficiente tiempo al emisor para que el receptor gestione las instrucciones.

Merlín dijo...

Hola por fin pude hacerlo :D
este es el código:

void RDA_isr(){

cadena[i]=getc(); // Recepción del string
printf("\n\rEste es el carcter %c",cadena[i]);
++i; // Preparación para recibir el siguiente caracter
ID=cadena[0]; // Identifica el primer caracter del array y lo guarda en ID
if (i==4) {
// Todos los caracteres recibidos separados
delay_ms(10);
C1[2]=cadena[1];
printf("\n\rC1 %c",C1);
delay_ms(10);
C2[2]=cadena[2];
printf("\n\rC2 %c",C2);
delay_ms(10);
C3[2]=cadena[3];
printf("\n\rC3 %c",C3);
delay_ms(10);
C4[2]=cadena[4];
printf("\n\rC4 %c",C4);

C1f= atof(C1);
printf("\n\rC1f %f",C1f);
C2f= atof(C2);
printf("\n\rC2f %f",C2f);
C3f= atof(C3);
printf("\n\rC3f %f",C3f);
C4f= atof(C4);
printf("\n\rC4f %f",C4f);

i=0; // Preparación para recibir el siguiente string

val = C2f*100 + C3f*10 + C4f*1; // num = 123

if(ID=='A') {
Amarillo = val;
printf("\n\rAmarillo Valor de Variable A %u",Amarillo);
}
if(ID=='B') {
Azul = val;
printf("\n\rAzul Valor de Variable B %u",Azul);
}
if(ID=='C') {
Rosa = val;
printf("\n\rRosa Valor de Variable C %u",Rosa);
}
if(ID=='D') {
Verde = val;
printf("\n\rVerde Valor de Variable D %u",Verde);
}

printf("\n\rAmarillo Valor de Variable A %u",Amarillo);
printf("\n\rAzul Valor de Variable B %u",Azul);
printf("\n\rRosa Valor de Variable C %u",Rosa);
printf("\n\rVerde Valor de Variable D %u",Verde);

printf(lcd_putc,"\fValor de Variable"); //Muestra en display mensaje
printf(lcd_putc,"\nA%u B%u C%u D%u",Amarillo,Azul,Rosa,Verde);

}

}

Muchas gracias por tu ayuda, me costo un poco pero al final funciono espero que a alguien le sea útil.

Saludos cordiales. ;)

jose luis dijo...

HOLA ESTIMADO MERLIN
puedes subir tus 2 codigos completos para poder entenderlo mejor porfavor.
gracias de antemano.!

jose luis dijo...

hola Robotypic porfavor ayudeme estoy intentando hacer el mismo proyecto que usted iso pero quiero enviar 2 temperaturas y que se muestren ambas temepraturas independiente una de la otra en la lcd .. espero su respuesta mi estimado

Merlín dijo...

Hola jose luis puedes plantear cual es tu duda y publicar tus avances así te podemos ayudar mejor, no te ayudamos si te damos el programa resuelto la finalidad de compartir esto es enseñarte a que tu lo puedas hacer.

Comenta cual es tu duda en concreto o pon tu código y lo podemos checar todos así te brindamos una mejor ayuda.

Saludos cordiales

Related Posts Plugin for WordPress, Blogger...

CONTACTA - (Haz referencia del artículo sobre el que trata la consulta o comentario)