Autor Tema: Trama de datos por RS485 a RS232 con Pic y Display  (Leído 11460 veces)

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #15 en: 16 de Enero de 2014, 21:11:24 »
Haz asi (lo que dice Rivale):

Código: C
  1. char cadena[5]={0,0,0,0,0};
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado BINARIO

  • PIC16
  • ***
  • Mensajes: 156
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #16 en: 20 de Enero de 2014, 14:04:25 »
Gracias gente, voy a probar aumentar la longitud de la cadena.
Ahora me surge una duda, si yo declaro una cadena de tipo CHAR cada elemento de la cadena deberia ser de tipo char, siendo asi, cuando yo reciba la trama ASCII no deberia ser un char por caracter ascii ??? si no es asi tengo un error de concepto importante
000101111 101110000011110 00010 11101 110 1 000111 00010010011010111100 101101001 11110000 001 00 10110 111 00001 01110 0010101 01011110 00 00011111111 0011111 011110001111111111 1011111111101100000000

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #17 en: 20 de Enero de 2014, 14:08:58 »
Gracias gente, voy a probar aumentar la longitud de la cadena.
Ahora me surge una duda, si yo declaro una cadena de tipo CHAR cada elemento de la cadena deberia ser de tipo char, siendo asi, cuando yo reciba la trama ASCII no deberia ser un char por caracter ascii ??? si no es asi tengo un error de concepto importante

  Sí, cada elemento de la cadena es de tipo char.  Cada caracter recibido ocupara un lugar de tu cadena, por lo tanto es un char por cada caracter recibido.
  Así, si necesitas recibir 13 caracteres, deberás definir tu cadena con una longitud mínima de 14 ya que el último espacio será ocupado por el caracter nulo que indica el fin de la cadena.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #18 en: 20 de Enero de 2014, 14:16:16 »
Gracias gente, voy a probar aumentar la longitud de la cadena.
Ahora me surge una duda, si yo declaro una cadena de tipo CHAR cada elemento de la cadena deberia ser de tipo char, siendo asi, cuando yo reciba la trama ASCII no deberia ser un char por caracter ascii ??? si no es asi tengo un error de concepto importante


un tipo char es realmente un entero de 8 bits, en cuanto a lo que comentas, tienes razon, cuando recibes una cadena, cada elemento es del tipo char, sin embargo, para una cadena de caracteres siempre necesitas un espacio mas debido a que las cadenas al final siempre tiene un 0

es decir, si tu cadena es "123" para cada caracter en representado en ascci tienes su número de la siguiente forma

0x31  0x32  0x33  0x00

como ves, al final tienes un 0x00, el cual no se ve cuando tienes la cadena representada en ascii no es imprimible

el caracter 0x00 indica que la cadena terminó, y este caracter se agrega cada que tu pones una cadena entre ""

espero te sirva

Saludos
"Nada es imposible, no si puedes imaginarlo"

Desconectado BINARIO

  • PIC16
  • ***
  • Mensajes: 156
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #19 en: 21 de Febrero de 2014, 14:27:12 »
Gracias gente, voy a probar aumentar la longitud de la cadena.
Ahora me surge una duda, si yo declaro una cadena de tipo CHAR cada elemento de la cadena deberia ser de tipo char, siendo asi, cuando yo reciba la trama ASCII no deberia ser un char por caracter ascii ??? si no es asi tengo un error de concepto importante


un tipo char es realmente un entero de 8 bits, en cuanto a lo que comentas, tienes razon, cuando recibes una cadena, cada elemento es del tipo char, sin embargo, para una cadena de caracteres siempre necesitas un espacio mas debido a que las cadenas al final siempre tiene un 0

es decir, si tu cadena es "123" para cada caracter en representado en ascci tienes su número de la siguiente forma

0x31  0x32  0x33  0x00

como ves, al final tienes un 0x00, el cual no se ve cuando tienes la cadena representada en ascii no es imprimible

el caracter 0x00 indica que la cadena terminó, y este caracter se agrega cada que tu pones una cadena entre ""

espero te sirva

Saludos

Segun lo que me decis, debo dejar solo un espacio para mi cadena de caracteres, pero en este sensor un trama tipica es asi:

004+26.2,+79.1,+0.217,+0.944,+0.034,+13.218,+13.552,+12.478,+12.273,+0.035,+26.2,<CR><LF>

                           HUM                             RD

esos son mis datos utiles.

Es por ello que no se, si deberia dejarle un espacio de fin de cadena, o dos, pero en cualquier caso a mi lo que me interesa es el primer caracter de fin de cadena que es el <CR> que en hexa seria "0xD"

El problema que me surje ahora es el manejo de las cadenas, la metodologia seria asi:


MICRO --------------------------- SENSOR

TR                                           Realizar lectura de parametros
esperar 2 segundos
T3                                           El sensor devuelve la cadena de caracteres con la informacion separada por comas


Bueno ahora, mi problema es que no me oriento bien como manejar las cadenas de caracteres.
Por una parte yo deberia mandarle al sensor como primer valor en ascii: (TR0xD0X10) que seria TR<CR><LF>
Con eso le pido que haga una lectura, si bien se como colocar ese valore en el puerto serie, no se como evaluarlo en una sentencia como por ejemplo un switch, implemente esto y aun no lo probe:

********************************************
  switch ( cadena )
 
  case 1:  //TR\n\r         ascii: TR0xD0x10
 
  printf(lcd_putc, "\fMEDIR....>");
  delay_ms(1000);
  break;
 
 
  case 2:   //T3\n\r        ascii:  T30xD0x10
  printf(lcd_putc, "\fMEDICION <....");
  printf("004+26.2,+79.1,+0.217,+0.944,+0.034,+13.218,+13.552,+12.478,+12.273,+0.035,+26.2,\n\r");
  break;

***********************************

ese seria mi pic trabajando como sensor, lo que no se es:

1- como hacer para evaluar el caso TR0xD0x10 en el case del switch?
2- Como trabajar la cadena de caracteres cuando la reciba en mi pic?


Espero poder resolverlo, un poco avance me demore, porque me dieron otras tareas y este proyecto se aprobo por fin.

SAludos
000101111 101110000011110 00010 11101 110 1 000111 00010010011010111100 101101001 11110000 001 00 10110 111 00001 01110 0010101 01011110 00 00011111111 0011111 011110001111111111 1011111111101100000000

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #20 en: 21 de Febrero de 2014, 14:49:25 »
los caracteres CR y LF son retorno de carro y salto de linea.

cuando usas la funcion gets esta lee byte por byte hasta que encuentra un salto de linea, todo lo demas lo guarda en un arreglo que tu le indiques

para trabajar con tu cadena primero tienes que descomponerla y tomar los datos que quieres.

para esto primero guarda lo que recibes de tu sensor en un vector y posteriormente puedes hacer una funcion que vaya recorriendo uno a uno los bytes de tu cadena hasta encontrar un separador, que en este caso es un + y la subcadena que generes la conviertes a un flotante usando atof() y asi obtienes el valor que desees.

espero haberme explicado, si no, con gusto trato de explicarlo de una mejor manera
"Nada es imposible, no si puedes imaginarlo"

Desconectado BINARIO

  • PIC16
  • ***
  • Mensajes: 156
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #21 en: 10 de Marzo de 2014, 14:04:56 »
los caracteres CR y LF son retorno de carro y salto de linea.

cuando usas la funcion gets esta lee byte por byte hasta que encuentra un salto de linea, todo lo demas lo guarda en un arreglo que tu le indiques

para trabajar con tu cadena primero tienes que descomponerla y tomar los datos que quieres.

para esto primero guarda lo que recibes de tu sensor en un vector y posteriormente puedes hacer una funcion que vaya recorriendo uno a uno los bytes de tu cadena hasta encontrar un separador, que en este caso es un + y la subcadena que generes la conviertes a un flotante usando atof() y asi obtienes el valor que desees.

espero haberme explicado, si no, con gusto trato de explicarlo de una mejor manera


Perdon la demora, he estado rindiendo examenes de la universidad.
Mira voy a probar esto que me decis, aunque antes intente guardar los valores en un vector y recorrerlo, pero no me resulto.
Ahora el Dr. que trabaja conmigo me recomendo la funcion strncpy(char *s1, const char *s2, size_t tam)
Lo que haces es copiar no mas de n caracteres de la cadena apuntada por S2 a la cadena apuntada por s1, pero lo que me propones me parece mas sencillo, comienzo la prueba.

000101111 101110000011110 00010 11101 110 1 000111 00010010011010111100 101101001 11110000 001 00 10110 111 00001 01110 0010101 01011110 00 00011111111 0011111 011110001111111111 1011111111101100000000

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #22 en: 10 de Marzo de 2014, 14:33:50 »
el strncpy te puede funcionar, solo que debes de tener en cuenta que esta instrucción no agrega el 0 al final de la cadena, tu lo tendrías que agregar manualmente si piensas usar algún atoi
"Nada es imposible, no si puedes imaginarlo"

Desconectado BINARIO

  • PIC16
  • ***
  • Mensajes: 156
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #23 en: 10 de Marzo de 2014, 15:19:34 »
EUREKA !!!

Hice algo mucho mas sencillo tal como me indicaron uds compañeros.
Bueno antes que nada el codigo que implemente.

///////////////////////////////////////////////////////////Definiciones Standart
#include <16F873A.h>
#device adc=10
#FUSES XT,NOWDT
#use delay(clock=4000000)

#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7))
#include <LCD420.C>


char cadena[5];
int1 flag=0;

#int_rda
void serial_isr()
{
 gets(cadena);
 flag=1;
}

void main()
{
 int16 q;
 float p;

 
 setup_adc_ports(AN0);                     //Canal 0 analógico
 setup_adc(ADC_CLOCK_INTERNAL); //Fuente de reloj RC
 
 enable_interrupts(global);
 enable_interrupts(int_rda);

 lcd_init();
 enable_interrupts(global);
 enable_interrupts(int_rda);
 set_adc_channel(0);             //Habilitación canal0

 
 while(true)
 {
 //delay_us(10);
 //q = read_adc(); //Lectura canal0
 //p = 5.0 * (float)q / 1024.0; //Conversión a tensión
 //printf(lcd_putc, "\fADC = %4ld", q);
 //printf(lcd_putc, "\nVoltage = %01.2fV", p);
 delay_ms(10);
 printf("\fADC = %4ld \r", q);
 printf("Voltage = %01.2fV", p);
 
if (flag == 1)
    {
     printf(lcd_putc, "\fDATO = %s", cadena);
     delay_ms(4);
     flag = 0;
    }
 }
}
//////////////////////////////////////////////////////////////

Mi error yacia en que tenia el concepto errado de que debia recorrer una cadena como un vector para imprimirlo, es decir que habia declarado una variable 'i' como indice para el vector y lo reccorria por cada vez que llegaba la interrupcion, nada que ver lo que hice lo se, recien ahora lo veo. Bueno ahora si cuando le doy imprimir cadena me imprime todo el contenido de la cadena, comenzare ahora las pruebas recorriendo si la cadena con alguna funcion o simplemente buscando los caracteres que preciso, para ello ya implemente un programa que transmite una trama similar a la que les habia mostrado antes, lo unico que quiero contarles es que hoy el CCS me tiro error de memoria RAM, me decia que no alcanzaba la RAM para todas las variables, la cadena que preciso es de mas o menos 82 elementos, que seria el total de caracteres de una trama Hydra clasica, si bien puedo truncar estos datos porque los ultimos 5 valores no los necesito, me gustaria saber porque el CCS no me dejo declarar una variable char cadena[100] de cien elementos, existe alguna otra tecnica cuando tenes un vector de muchos elementos? de momento no se me ocurre ninguna, pero voy a empezar implementando un programa de busqueda de los valores que preciso y luego imprimirlos en el LCD de mi circuito.

Muy agradecido me despido hasta pronto.
000101111 101110000011110 00010 11101 110 1 000111 00010010011010111100 101101001 11110000 001 00 10110 111 00001 01110 0010101 01011110 00 00011111111 0011111 011110001111111111 1011111111101100000000

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #24 en: 10 de Marzo de 2014, 16:44:11 »
  Tal vez el error de la cantidad de elementos del array sea debido que que dicho PIC no tiene esa cantidad de bytes seguidos en una misma página de memoria.
  Fíjate en el datasheet que indica que el tamaño de memoria de datos es 96 bytes en el banco 0 y 96 bytes en el banco 1
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado BINARIO

  • PIC16
  • ***
  • Mensajes: 156
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #25 en: 14 de Marzo de 2014, 15:52:25 »
Buenas como estan?

Segui trabajando sobre este desarrollo complejizandolo un poco mas, el siguiente paso que di despues de poder ver la cadena que me enviaba el micro que se comporta como el sensor, es poder seleccionar determinados elementos de esa cadena

Les recuerdo que la cadena era asi, y los datois utiles eran:

004+26.2,+79.1,+0.217,+0.944,+0.034,+13.218,+13.552,+12.478,+12.273,+0.035,+26.2,
                 HUM                                       RD

La idea era asi, tomar los datos que me devuelve el sensor en esa cadena de caracteres, para ello implemente las siguientes funciones de cadenas de CCS o mejor dicho de C++, aunque esto implico que cambie un micro de 4K de flash por uno de 8K


strncpy : Esta funcion lo que hace es copiar n caracteres de una cadena en otra cadena

              sintaxis: strncpy( cad1, cad2, 5) --------->  Lo que hace aca es copiar los 5 primeros caracteres de cad2 en cad1

strchr : Esta funcion lo que hace es localizar el primer caracter especificado en una cadena
              sintaxis: strchr ( cad1, ',') ------------> localiza la primer coma dentro de la cadena cad1 y devuelve esa posicion dentro de la cadena.



yo implemente asi:

1-    strncpy (cad_hum, strchr(cadena, ',')+1,  31);
      
       lo que hago aqui es buscar una coma y copiar la cadena en cad_hum a partir de esa coma incluida.

2-    strncpy (humedad, strchr(cad_hum, ',')+2, 5);

       lo que hago aqui es tomar la cadena auxiliar y desde la coma mas dos caracteres (de esta forma elimino el +) copio los 5 caracteres siguientes.


Esto funciono muy bien para la humedad que esta en la posición tres de la cadena que me devuelve el sensor, pero no logro hacerlo funcionar para la posición 5 de la cadena, sigo probando con estas funciones de cadenas, me parece que voy a tener que revisar el Deitel&Deitel.

En el programa ejemplo que dejo, muestro la posicion 2 y 3 de la cadena, pero la que necesito mostrar es la 2 y la 5...

Saludos, por lo menos algo anduvo de lo que quiero hacer jeje  :lol: :lol: :lol: :lol: :lol:



************************************************************************************************
#include <16F873.h>
#device adc=10
#FUSES XT,NOWDT
#use delay(clock=4000000)

#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7))
#include <string.h>
#include <LCD420.C>



char cadena[50];
int1 flag=0;

#int_rda
void serial_isr()
{
 gets(cadena);
 flag=1;
}

void main()
{
 int16 q;
 int i,j;
 float p;
 char humedad[7], RD[8], cad_hum[31], cad_RD[25];

 
 setup_adc_ports(AN0); //Canal 0 analógico
 setup_adc(ADC_CLOCK_INTERNAL); //Fuente de reloj RC
 
 enable_interrupts(global);
 enable_interrupts(int_rda);

 lcd_init();
 
 /*printf(lcd_putc,"\f   HERACLES V1.0");
 delay_ms(300);  
 printf(lcd_putc,"\f");*/
 
 set_adc_channel(0); //Habilitación canal0

 
 while(true)
 {
  

  if (flag == 1)
    {
            
            
             strncpy (cad_hum, strchr(cadena, ',')+1,  31);
             strncpy (humedad, strchr(cad_hum, ',')+2, 5);
            
             strncpy (cad_RD, strchr(cad_hum ',')+3, 20);            
             strncpy (RD, strchr(cad_RD, ',')+2, 5);
            
             //strncpy (cad_hum, strchr(cad_RD, ',')+3,  10);            
             //strncpy (RD, strchr(cad_hum, ',')+2, 5);
            
             delay_ms(500);
             printf(lcd_putc, "\fHumedad = %s ", humedad);
             printf(lcd_putc, "\nRD      = %s", RD);
                          
             flag = 0;
      
      
      
    }
   }
  
 }
 
« Última modificación: 14 de Marzo de 2014, 15:58:01 por BINARIO »
000101111 101110000011110 00010 11101 110 1 000111 00010010011010111100 101101001 11110000 001 00 10110 111 00001 01110 0010101 01011110 00 00011111111 0011111 011110001111111111 1011111111101100000000

Desconectado BINARIO

  • PIC16
  • ***
  • Mensajes: 156
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #26 en: 19 de Marzo de 2014, 14:41:03 »
me quede solo con esto???  :?
000101111 101110000011110 00010 11101 110 1 000111 00010010011010111100 101101001 11110000 001 00 10110 111 00001 01110 0010101 01011110 00 00011111111 0011111 011110001111111111 1011111111101100000000

Desconectado BINARIO

  • PIC16
  • ***
  • Mensajes: 156
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #27 en: 19 de Marzo de 2014, 17:20:26 »
 :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/

JEJE renegando un poco mas y usando mi instinto de ingeniero, pude dar solucion por lo menos a la parte que me habia planteado del problema. Aca cuelgo el programa y una foto de la simulación

----------------------------------------------------------------------------------------------------------------------------------------------

#include <16F876.h>
#device adc=10
#FUSES XT,NOWDT
#use delay(clock=4000000)

#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7))
#include <string.h>
#include <LCD420.C>



char cadena[50];
int1 flag=0;

#int_rda
void serial_isr()
{
 gets(cadena);
 flag=1;
}

void main()
{
 int16 q;
 int i,j, len=0;
 float p;
 char humedad[7], RD[8], cad_hum[45], cad_RD[45];

 
 setup_adc_ports(AN0); //Canal 0 analógico
 setup_adc(ADC_CLOCK_INTERNAL); //Fuente de reloj RC
 
 enable_interrupts(global);
 enable_interrupts(int_rda);

 lcd_init();
 
 /*printf(lcd_putc,"\f   HERACLES V1.0");
 delay_ms(300); 
 printf(lcd_putc,"\f");*/
 
 set_adc_channel(0); //Habilitación canal0

 
 while(true)
 {
 

  if (flag == 1)
    {

//Cadena
//004+26.2,+79.1,+0.217,+0.944,+0.034,+13.218,+13.552,+12.478,+12.273,+0.035,+26.2,


             strncpy (cad_hum, strchr(cadena, ',')+1, 45);
             strncpy (humedad, strchr(cad_hum, ',')+2, 5);
             
             printf(lcd_putc, "\fHumedad = %s ", humedad);
             
             strncpy (cad_RD, strchr(cad_hum, ',')+2, 45);
             strncpy (cad_hum, strchr(cad_RD, ',')+1, 45);
             strncpy (cad_RD, strchr(cad_hum, ',')+2, 45);
             strncpy (RD, strchr(cad_RD, ',')+2, 6);
             
             printf(lcd_putc, "\nRD      = %s", RD);
             
             //strncpy (cad_RD, strchr(cad_hum ',')+3, 20);             
             //strncpy (RD, strchr(cad_RD, ',')+2, 5);
             
             //strncpy (cad_hum, strchr(cad_RD, ',')+3,  10);             
             //strncpy (RD, strchr(cad_hum, ',')+2, 5);
             
             delay_ms(500);
             //printf(lcd_putc, "\fHum = %s ", cad_hum);
             
             
                           
             flag = 0;
     
     
     
    }
   }
   
 }
 
000101111 101110000011110 00010 11101 110 1 000111 00010010011010111100 101101001 11110000 001 00 10110 111 00001 01110 0010101 01011110 00 00011111111 0011111 011110001111111111 1011111111101100000000

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #28 en: 19 de Marzo de 2014, 17:47:05 »
Que bueno que quedó sulucionado  :-)
"Nada es imposible, no si puedes imaginarlo"

Desconectado BINARIO

  • PIC16
  • ***
  • Mensajes: 156
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #29 en: 20 de Marzo de 2014, 11:07:57 »
En realidad solo es la primera parte del problema... :shock: :shock: :shock:

Lo que sigue es enviarle un comando al pic que actua como sensor esperar un tiempo, aproximadamente 1 seg. y luego enviar otro comando para que el pic sensor me devuelva la trama completa, ese seria el funcionamiento completo, y por supuesto algunos retoques esteticos una vez implementada la aplicacion, ademas que debo lidiar aun cuando la RD es de una cifra, dado que me copiaria un caracter mas en la cadena RD, pero eso creo que puedo solucionarlo con if anidados.
El funcionamiento final seria asi:

PIC                                          SENSOR

T0 --------------------------------->  Realizar una medicion
Delay_ms(1000)
T3----------------------------------> Devolver medicion
  <----------------------------------- Cadena: 004+26.2,+79.1,+0.217,+0.944,+0.034,+13.218,+13.552,+12.478,...,CR,LF,NULL
OK !
Mostrar Datos en Display.
000101111 101110000011110 00010 11101 110 1 000111 00010010011010111100 101101001 11110000 001 00 10110 111 00001 01110 0010101 01011110 00 00011111111 0011111 011110001111111111 1011111111101100000000