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.
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
//////////////////////////////////////////////////////////////////////////////// // // // TRANSMISIÓN FLOAT RS232 ENTRE DOS PIC // // // // PIC EMISOR // // // // (c) RobotyPic 2012 // // // //////////////////////////////////////////////////////////////////////////////// #include <16F876a.h> #device adc=10 //Configuración conversor AD a 10 bits #fuses XT, NOWDT #use delay(clock=4000000) //Frecuencia del reloj #use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7) #define use_portb_lcd TRUE //Puerto B para el LCD #include <lcd.c> //Librería para el LCD #include <stdio.h> /******************************************************************************/ /************************ FUNCIÓN PRINCIPAL *********************************/ void main () { float32 valor; //Dato a transmitir en float char cadena[6]; //Dato a transmitir en string char string[6]; //Guarda el valor float como string int i=0; //Número de caracteres del string int16 lectura; //Lectura del conversor AD setup_adc_ports(AN0_vref_vref); //Canal de entrada analógico AN0 setup_adc(ADC_CLOCK_INTERNAL); //Fuente de reloj RC lcd_init(); //Inicialización del display delay_ms(500); while(1){ set_adc_channel(0); delay_us(20); lectura=read_adc(); //Lectura canal analógico valor=(-2.5)+(5*lectura/1024.0); //Valor analógico de la lectura //Muestra por el LCD los valores digital y analógico de la lectura AD printf(lcd_putc, "\fADC = %4lx", lectura); printf(lcd_putc, "\nVoltage = %01.2fV", valor); sprintf(string,"%01.2f",valor); //Paso a string el valor float // Si el valor es positivo le añado signo + if (valor>0) { strcpy(cadena,"+"); //En "cadena" caracter + strcat (cadena,string); //Al signo + se añade el valor numérico } //Si el valor es negativo le dejo el signo - else { strcpy(cadena,""); strcat (cadena,string); }
//Envío por RS232 del valor float como string for (i=0;i<=5;++i){ putc(cadena[i]); delay_ms(150); } } }
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
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!
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.
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.
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)
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
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 ?
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.
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.
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);
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.
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
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.
13 comentarios:
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!
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.
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.
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)
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.
Merlin.
Según tu programa ya tienes separado el valor numérico decimal en la variable val y el identifiador en ID.
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.
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.
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.
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. ;)
HOLA ESTIMADO MERLIN
puedes subir tus 2 codigos completos para poder entenderlo mejor porfavor.
gracias de antemano.!
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
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
Publicar un comentario