TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: BINARIO en 29 de Noviembre de 2013, 15:22:11

Título: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 29 de Noviembre de 2013, 15:22:11
 :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/  :mrgreen: :mrgreen:

Estimados:
                Estoy comenzando un desarrollo con un sensor de humedad que tiene dentro de su circuito un micro que devuelve los datos por RS485, estoy un poco perdido. En realidad lo que quiero hacer es sencillo pero no tanto.
Es asi, yo tengo mi sensor de humedad de suelo es un Hydra probe II el mismo se puede comunicar con una PDA que tiene un programita que te permite ver los datos de la humedad del suelo y la constante dielectrica del mismo, asi como tambien la salinidad. Bien todos esos datos el sensor los devuelve en una trama que puedo conocer como es porque el fabricante me da esa informacion; mi idea es para no tener que comprar una pda usar un pic, ya que actualmente tomo los datos con una netbook y un conversor de RS485 a RS232.
Cuando conecto la netbook mediante el hercules le mando tres comandos al sensor SN - TR y TE

SN: me devuelve el numero de serie.
TR: le dice al sensor que realize una medicion.
TE: Me devuelve la medicion que realizo el sensor.

Mi idea es poder migrar todo esto a un PIC, quiero usar un PIC16F873 con un SN75176 que es un integrado que me convierte los niveles 485 directamente a RS232 con lo cual podria comunicarme directamente desde el pic al sensor sin demasiados problemas.

OK hasta aca todo bien, sin embargo mi problema radica en que no se leer tramas con el pic, usualmente he leido caracteres como 'R' o 'T' y con eso hacia que se active alguna cosa mediante el puerto serie.
Como yo conozco la trama que me envia el sensor querria saber como se lee una trama asi de toda esa info puedo seleccionar los datos que necesito.

Saludos y gracias por leer.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: AngelGris en 29 de Noviembre de 2013, 16:12:29
  Todo depende de como sea la trama. Si tiene algún caracter de inicio y alguno de final de trama es bien sencilla la lectura.

Básicamente es ir recibiendo y almacenando todos los caracteres hasta que aparezca el final de trama.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 02 de Diciembre de 2013, 10:00:43
El viernes charlando con un colega me dijo que puedo utilizar un vector e ir almacenando los datos si tiene caracter de fin de trama leer ese como condicion para salir, y si no puedo usar algo que el lama timeout, es decir que si paso un determinado tiempo sin recibir nada dar por terminada la transmision, ahora estoy leyendo los manuales a ver si sale algo pero mucho no me dice sobre la trama, tendre que investigar mas.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: AngelGris en 02 de Diciembre de 2013, 10:09:01
  Puedes subir la información de tu dispositivo, para ver si entre todos comprendemos como manejar la trama.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 02 de Diciembre de 2013, 10:53:33
Aca subo el folleto del sensor donde da detalles de la comunicacion que emplea.

http://www.stevenswater.com/catalog/products/soil_sensors/manual/Hydra%20Probe%20Manual%2092915%20June%202007.pdf
http://www.stevenswater.com/catalog/products/soil_sensors/datasheet/Hydra%20Probe%20II%20Spanish.pdf
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: AngelGris en 02 de Diciembre de 2013, 11:27:11
  Por lo que entiendo del datasheet, se pueden hacer varias operaciones sobre el dispositivo. Una muy importante es la configuración del Address si es que tienes varios dispositivos similares conformando una red. Así como también la lectura del address.

  ¿Tienes varios dispositivos en paralelo? ¿Sabes cuál es el address del mismo?

  Por lo visto cada una de las tramas termina con los caracteres <CR><LF> que son los decimales 13 y 10 respectivamente.

  Entiendo que para leer cierta información hay que mandar el comando T<set> y va a devolver la lectura e el formato <readings> que son valores separados por una coma ",". Según el T que se solicite será la información recibida.

  Imagino que si se envía un T0, se recibe toda la información correspondiente a dicha petición y que, según el datasheet, son 9 parámetros, y por lo tanto <readings> constará de 9 "valores" separados por una coma.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 02 de Diciembre de 2013, 16:02:05
LA idea es colocar solo un dispositivo, dado que son realmente caros, y de hecho es para hacer un medidor portatil de humedad del suelo, o sea que solo se maneja un dispositivo RS485 con el micro
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 16 de Diciembre de 2013, 13:12:42
Bueno perfecto, el protocolo SDI12 es solo para algunos de estos sensores, pero tambien vienen RS-485 aca traduje una parte de la hoja de datos del sensor donde explica en buen detalle como manejar los comandos los voy a colocar a continucacion:

 :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow:

Apéndice B – Comunicación RS-485

La sonda Hydra RS-485 es también digital y usa formato de comunicación RS-485. La sonda Hydra RS-485 usa 4 cables: un cable de tierra, un cable de alimentación de 12V y dos cables de datos. LA sonda Hydra Rs-485 se comunica por 2 cables de dato y puede conectarse a un puerto RS485 en un Logger. Se puede conectar a un conjunto de terminales como la versión SDI-12, pero con 4 cables en vez de 2. La ventaja  del RS485 sobre el SDI12 es que la versión RS485 puede trabajar a más de 3000 pies. La desventaja es que consume más potencia.

Requerimientos de potencia   9 a 20 VDC  (12VDC ideal)

Cable rojo           Tensión de alimentación
Cable negro   Tierra
Cable azul           Señal de datos A – señal no invertida
Cable verde   Señal de datos B – señal invertida
Tasa de Baudios   9600 8N1
Consumo            <10 mA  Idle / 30 mA en modo Activo

Sonda Stevens Hydra RS485 Especificaciones de comando.

Formato de comandos
AAACC<CR><LF>      Ejecutar
AAACC=?<CR><LF>      Consulta la configuración actual
AAACC=XXX…<CR><LF>   Asigna un nuevo valor
AAA:                              Dirección de 3byte
                              Caracteres ASCII, 0-9 A-Z a-z
                              Carácter comodín  ‘/’
                              Dirección de transmisión ‘///’

CC:                             Comando de 2 bytes
XXX…:                     Comandos de datos. Ver información de comandos para requerimientos específicos
<CR>                          Retorno de carro ASCII 13
<LF>                                  Carácter de retorno de línea ASCII 10

Otros Gramaticales

<d>:                            Dígitos, ASCII ‘0’ al ASCII ‘9’
<a>:                            ASCII ‘A’ al ASCII ‘D’, usado para la constante de agua personalizada
<serial>:                         Numero serial, 8 dígitos <d><d><d><d><d><d><d><d>
<soil>:                         Tipo de suelo, 1 carácter { ‘1’ |‘2’ |‘3’ |‘4’ |‘C’ |‘D’ }
<quick>:                         Modo Rápido, 1 carácter { ‘1’  - ‘6’, ‘X’ }
<warump>:                 tiempo de calentamiento, 1-5 dígitos, 0-65535
<bool>:                         Valor booleano, 1 carácter { ‘0’ | ‘1’ }
<firmware>                 Firmware, 3 o 4 bytes, formateado como “2.7” o “R.2.7” o “2S7”
<text>:                         Texto ASCII imprimible
<float>:                         Numero decimal, opcionalmente usado en forma de notación científica.
                     
                                                 Ej. “+23.54, 0.001, -123.0E5, 45E-3”

<readings>:                 Cadena de flotantes, delimitadas por comas. Ej. “+23.54, -42.532, +2342.12”


Especificaciones Sonda Hydra  comandos RS485

Información de comandos


Numero serial

Descripción:      Retorna el número de serie de fábrica.
Nivel de acceso:    Solo lectura.
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>SN=?<CR><LF>
Respuesta de lectura:   <addr><serial><CR><LF>

Versión de Firmware
Descripción:      Devuelve el número de versión de firmware.
Nivel de acceso:    Solo lectura.
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>FV=?<CR><LF>
Respuesta de lectura:   <addr><firmware><CR><LF>


Comandos de configuración Estándar


Dirección
Descripción:      Captura y establece la dirección de la sonda
Nivel de acceso:           Lectura/Escritura
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>AD=?<CR><LF>
Respuesta de lectura:   <addr><CR><LF>
Dirección de escritura:   Exact
Comando de escritura:   <addr>AD=<serial><new_addr><CR><LF>
Respuesta de escritura:    <new_addr><CR><LF>

Tipo de suelo
Descripción:      Captura y establece el tipo de suelo de la sonda
Nivel de acceso:    Lectura/Escritura
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>ST=?<CR><LF>
Respuesta de lectura:   <addr><CR><LF>
Dirección de escritura: Broadcast, Exact , Wildcard
Comando de escritura: <addr>ST=<soil><CR><LF>
Respuesta de escritura: <soil><CR><LF>   (no hay respuesta en la dirección comodín)



Comandos de configuración avanzada.


Ubicación
Descripción:      Captura y establece la ubicación de la sonda
Nivel de acceso:    Lectura/Escritura
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>LO=?<CR><LF>
Respuesta de lectura:   <addr><text><CR><LF>
Dirección de escritura: Exact
Comando de escritura: <addr>LO=<text><CR><LF>
Respuesta de escritura:  <addr><text><CR><LF>   

Descripción
Descripción:      Captura y establece la descripción de sonda
Nivel de acceso:    Lectura/Escritura
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>DS=?<CR><LF>
Respuesta de lectura:   <addr><text><CR><LF>
Dirección de escritura: Exact
Comando de escritura: <addr>DS=<text><CR><LF>
Respuesta de escritura: <addr><text><CR><LF>   

Constante Hídrica personalizada
Descripción:      Captura y establece la constante hídrica de la sonda
Nivel de acceso:    Lectura/Escritura
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>X<a>=?<CR><LF>
Respuesta de lectura:   <addr><float><CR><LF>
Dirección de escritura: Exact
Comando de escritura: <addr>X<a>=<float><soil><CR><LF>
Respuesta de escritura: <addr><float><CR><LF>

Modo rápido
Descripción:      Captura y establece la constante hídrica de la sonda
Nivel de acceso:    Lectura/Escritura
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>QM=?<CR><LF>
Respuesta de lectura:   <addr><quick><CR><LF>
Dirección de escritura: Exact
Comando de escritura: <addr>QM=<quick><CR><LF>
Respuesta de escritura:  <addr><float><CR><LF>


Comandos del Debug


Warmup time

Descripción:      Captura y establece el tiempo de calentamiento
                                           personalizado de la sonda
Nivel de acceso:    Lectura/Escritura
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>WT=?<CR><LF>
Respuesta de lectura:   <addr><warump><CR><LF>
Dirección de escritura: Exact
Comando de escritura: <addr>WT=<warmup><CR><LF>
Respuesta de escritura:  <addr><warmup><CR><LF>

Sonda habilitada
Descripción:                    Captura y establece si el circuito de la sonda está
                                           habilitado
Nivel de acceso:                  Lectura/Escritura
Dirección de lectura:          Broadcast, Exact
Comando de lectura:         <addr>PE=?<CR><LF>
Respuesta de lectura:         <addr><bool><CR><LF>
Dirección de escritura:   Exact
Comando de escritura:   <addr>PE=<bool><CR><LF>
Respuesta de escritura:    <addr><bool><CR><LF>



Comandos de medición

//Comandos fundamentales para la lectura de la humedad de suelo

Tomar Lectura
Descripción:      Indica a una sonda o un grupo de sondas tomar una lectura
Nivel de acceso:    Lectura/Escritura
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>TR<CR><LF>
Respuesta de lectura:   (ninguna)

Transmitir Conjunto leído
Descripción:      Indica a una sonda transmitir una lectura especifica
Nivel de acceso:           Lectura/Escritura
Dirección de lectura:   Broadcast, Exact
Comando de lectura:   <addr>TR<CR><LF>
Respuesta de lectura:   (ninguna)


RS485 Conjuntos Transmitidos
(tc) indica valores que deben ser corregidos por temperatura

T0 – Conjunto transmisión 0:
H) Humedad
J) Conductividad eléctrica del suelo (tc)
F) Temperatura °C
G) Temperatura °F
O) Conductividad eléctrica del suelo
K) Permitividad Dieléctrica real.
M) Permitividad Dieléctrica Imaginaria.
L) Permitividad Dieléctrica real (tc).
N) Permitividad Dieléctrica imaginaria (tc)

T1 – Conjunto de transmisión 1:
F) Temperatura °C
G) Temperatura °F
I) Tangente de perdida

T2 – Conjunto de transmisión 2:
F) Temperatura °C
G) Temperatura °F
H) Humedad
O) Conductividad eléctrica
J) Conductividad eléctrica (tc)
I) Tangente de perdida

T3 – Conjunto de transmisión 3:
F) Temperatura °C
G) Temperatura °F
H) Humedad
I) Tangente de perdida
J) Conductividad eléctrica del suelo (tc)
K) Permitividad dieléctrica real
L) Permitividad dieléctrica real (tc)
M) Permitividad dieléctrica imaginaria
N) Permitividad dieléctrica imaginaria (tc)
O) Conductividad eléctrica del suelo
P) Temperatura de diodo
Q) Vacío

T4 – Conjunto de transmisión 4:
A) V1 (Volts)
B) V2 (Volts)
C) V3 (Volts)
D) V4 (Volts)
E) V5 (Volts)

T5 – Conjunto de transmisión 5:
R) V1 ADC en bruto
S) V2 ADC en bruto
T) V3 ADC en bruto
U) V4 ADC en bruto
V) V5 ADC en bruto


 :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow: :arrow:

Ahora comienzo con algunas simulaciones en proteus ocupando el hyperterminal para ver como mandar los comandos y armar la comunicacion propiamente dicha, el hardware es sencillo, ya que solo necesito un pic, un sn75175 y un lcd para visualizar las respuestas y configurar, como veran el hard es simple, mas aun cuando necesito hacer un dispositivo portatil. Saludos les voy contando como sale.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 18 de Diciembre de 2013, 10:00:39
Hasta ahora e implementado lo siguiente con dos pics como para probar uno de ellos seria quien simula a la hydra pero de momento los dos hacen lo mismo, como primera prueba de transmision intente que cuando uno transmite algo al otro lo publique en el lcd por interrupcion de la USART, pero hasta ahora solo me funciono una vez, en el compilador me dio mensaje de que las interrupciones se deshabilitan para prevenir una re entrada, asi que en el ciclo iterativo le puse que active nuevamente las interrupciones de la USART les muestro el programa a continuacion:

------------------------------------------------------------------------------------------------------------------------------------------------------
#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>

int ch;

#int_rda
void serial_isr()
{
 ch=getchar();
 printf("Recibido = %c", ch);
 
 printf(lcd_putc, "\fANDUVO = %c", ch);
 delay_ms(100);
}

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();
 
 for ( ; ; ) {
 enable_interrupts(global);
 enable_interrupts(int_rda);
 set_adc_channel(0); //Habilitación canal0
 delay_us(10);
 q = read_adc(); //Lectura canal0
 p = 5.0 * q / 1024.0; //Conversión a tensión
 printf(lcd_putc, "\fADC = %4ld", q);
 printf(lcd_putc, "\nVoltage = %01.2fV", p);
 delay_ms(100);
 printf("\fADC = %4ld \r", q);
 printf("Voltage = %01.2fV", p);
 
 }
}
----------------------------------------------------------------------------------------------------------------------------------------------------

Les adjunto el circuito de prueba en proteus, acepto sugerencias sobre como hacer una transmision de caracteres ascii con la usart, hasta ahora logre eso sigo renegando mientras.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: AngelGris en 18 de Diciembre de 2013, 10:48:54
  La instrucción printf consume muchísimos ciclos de instrucción (en asm) por lo tanto demora mucho tiempo. Nunca es recomendable tardar mucho dentro de la interrupción. Será mejor que utilices un flag indicativo de que hay datos y luego evalues dicho flag en el main del programa. Justamente si hay datos los muestras en el LCD.

  A su vez, quizá sería recomendable hacer funcionar al PIC a una mayor frecuencia, para tener más ciclos de instrucción para hacer cosas.

La sintaxis básica de la utilización de un flag sería algo así....

Código: C
  1. unsigned char caracter; // donde se almacenara un byte llegado del UART
  2. unsigned char flag; // flag para saber si hay datos
  3.  
  4. interrupcion
  5. {
  6.   caracter = getchar();
  7.   flag = 1;
  8. }
  9.  
  10. main
  11. {
  12.   while (1)
  13.   {
  14.     if (flag == 1)
  15.     {
  16.       mostrar en LCD
  17.       flag = 0;
  18.     }
  19.     todo el resto de tu programa
  20.   }
  21. }

  No utilizo CCS como compilador así que puse una especie de pseudocodigo para que se entienda la idea
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 09 de Enero de 2014, 14:34:28
Tengo un problemita ahora.

Implemente dos pics para simular la trama de datos, por ahora lo que hago es leer el valor de un potenciometro con el adc y enviarlo por puerto serie de un pic al otro, ok funciona, pero lo que le llega al otro pic es otra cosa yo hice asi:

en un display pongo lo que lee el adc y por ejemplo es 1.25, en el otro pic leo ese valor en un vector que es char y segun yo lee caracter por caracter y lo almacena en cada posicion del vector, luego muestro ese vecto pero me sale por ejemplo asi:

< > < 1 > < 1 >

En lugar de mostrarme el valor < 1 > < . > < 4 >

no se porque es, y ademas cuando yo cambio el valor del potenciometro mantiene esa lectura y no la actualiza como si la interrupcion del puerto serie no volviese a ocurrir...

 :5] :5] :5] :5] :5] :5] :5] :5]
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: rivale en 09 de Enero de 2014, 17:47:58
Algunas correcciones a tu codigo:

Código: [Seleccionar]
#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>

int ch;
char cadena[30];
int1 flag=0;

#int_rda
void serial_isr()
{
 cadena=gets;
 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(100);
 printf("\fADC = %4ld \r", q);
 printf("Voltage = %01.2fV", p);
  if(flag)
  {
      printf("Recibido = %c", ch);
 
         printf(lcd_putc, "\fANDUVO = %c", ch);
      delay_ms(100);
      flag=0;
  }
 }
}


Si estas usando printf para enviar datos puedes usar gets para leer la cadena completa, tambien cambie algunas lineas que no necesitan ir dentro de tu ciclo infinito

espero te ayude

Saludos
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 16 de Enero de 2014, 14:22:27
HOLA RIVALE!!!

muchas gracias por tu ayuda, hasta ahora el codigo que implementaste como correccion parece dar resultado, sin embargo hay un error en proteus, este seria el codigo

#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>

int i=0;
char cadena[3]={0,0,0};
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(40);
     flag = 0;
     i++;
     if (i==3)
     i=0;
    }
 }
}

Funciona, muestra el valor pero hace un error como veraz en estas imagenes como si fuese un desplazamiento, he adjuntado el error que me da en proteus, no se bien porque lo genera hoy le dedique la mañana a esto si logro algun avance lo publico

saludos y gracias por leer
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: rivale en 16 de Enero de 2014, 15:07:06
incrementa la longitud de tu variale cadena, si estas enviando 4 caractares necesitas que su longitud sea de al menos 5
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: rivale en 16 de Enero de 2014, 15:11:43
no se si entendí bien el problema

tu envias 2.34 desde un pic, y en el pic que recibes solo ves 35

si es eso creo que es por lo que comenté arriba, en tu cadena no caben los 4 caracteres por eso te lo corta

si lo entendí mal por favor corrígeme para que pueda ayudarte  :-)
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: MGLSOFT 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};
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO 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
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: AngelGris 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.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: rivale 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
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO 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
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: rivale 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
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO 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.

Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: rivale 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
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO 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.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: AngelGris 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
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO 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;
      
      
      
    }
   }
  
 }
 
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 19 de Marzo de 2014, 14:41:03
me quede solo con esto???  :?
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO 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;
     
     
     
    }
   }
   
 }
 
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: rivale en 19 de Marzo de 2014, 17:47:05
Que bueno que quedó sulucionado  :-)
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO 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.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: rivale en 20 de Marzo de 2014, 11:34:17
porque necesitas ese delay para enviar los datos?
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: AngelGris en 20 de Marzo de 2014, 12:27:35
  Viendo en el manual, entiendo que el comando T3 devolverá 12 valores separados por ',' (coma).

Para leer, digamos el primer valor de "Real Dielectric", que sería el parámetro K se podría intentar algo como....

ir recorriendo la cadena original hasta encontrar el caracter ',' e ir almacenando en alguna variable las posiciones de las ',' encontradas. Luego nos interesará copiar desde la 5º hasta la 6º ',' que sería el parámetro K
Supongo que se podría utilizar un array para almacenar dicha información.

Código: C
  1. unsigned char posicionDeComa[15];
  2.  
  3. void encontrarComas(unsigned char *cadena)
  4. {
  5.   unsigned char indiceDecoma;
  6.   unsigned char indiceDeCadena;
  7.  
  8.   indiceDeComa = 0;
  9.   indiceDeCadena = 0;
  10.   while (*cadena != 0)  // mientras haya caracteres en la cadena
  11.   {
  12.     if (*cadena == ',')
  13.     {
  14.       posicionDeComa[indiceDeComa] = indiceDeCadena;
  15.       indiceDeComa++;
  16.     }
  17.     indiceDeCadena++;
  18.     cadena++;
  19.   }
  20. }

  Ése código almacenaría en una array todos los índices de las comas y por lo tanto ese array se lo podría utilizar para copiar las cadenas.
  No lo probé, e imagino que será mejorable el código... pero puede servir como punto de partida.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 20 de Marzo de 2014, 14:02:50
porque necesitas ese delay para enviar los datos?

Rivale: Ese tiempo necesita el sensor entre cada comando para poder realizar y almacenar la medicion en su memoria interna., luego de eso envia los datos, lo hemos probado varias veces con el hyperterminal y siempres es por lo menos 1 segundo entre comando y comando.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 20 de Marzo de 2014, 14:09:03
  Viendo en el manual, entiendo que el comando T3 devolverá 12 valores separados por ',' (coma).

Para leer, digamos el primer valor de "Real Dielectric", que sería el parámetro K se podría intentar algo como....

ir recorriendo la cadena original hasta encontrar el caracter ',' e ir almacenando en alguna variable las posiciones de las ',' encontradas. Luego nos interesará copiar desde la 5º hasta la 6º ',' que sería el parámetro K
Supongo que se podría utilizar un array para almacenar dicha información.

Código: C
  1. unsigned char posicionDeComa[15];
  2.  
  3. void encontrarComas(unsigned char *cadena)
  4. {
  5.   unsigned char indiceDecoma;
  6.   unsigned char indiceDeCadena;
  7.  
  8.   indiceDeComa = 0;
  9.   indiceDeCadena = 0;
  10.   while (*cadena != 0)  // mientras haya caracteres en la cadena
  11.   {
  12.     if (*cadena == ',')
  13.     {
  14.       posicionDeComa[indiceDeComa] = indiceDeCadena;
  15.       indiceDeComa++;
  16.     }
  17.     indiceDeCadena++;
  18.     cadena++;
  19.   }
  20. }

  Ése código almacenaría en una array todos los índices de las comas y por lo tanto ese array se lo podría utilizar para copiar las cadenas.
  No lo probé, e imagino que será mejorable el código... pero puede servir como punto de partida.

AngelGris:

               Yo intente algo similar, tratando a la cadena como un array y buscando dentro de la cadena como si fuese un array, pero no funciono, es decir, de algun modo no ve a la cadena como un array, por eso lo resolvi con instrucciones de cadena, por ahora esa implementacion que use funciona bien, lo que tengo que modificar es cuando la RD tiene una sola cifra significativa antes del punto, en ese caso tendria menos de una decena y me mostraria en vez de:

+13.258  .........................> +1.258,

Porque como el tamaño que le di a RD es fijo, siempre me va a mostrar 6 caracteres, sin importar lo que sea, ahora estaba implementando if anidados, hasta encontrar la coma siguiente, para delimitar mi cadena RD.
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: AngelGris en 20 de Marzo de 2014, 18:37:23
  Acá te muestro un ejemplo en XC8. Utilizo una trama emulada (son los datos que tu pusiste aquí) y luego utilizo una función para encontrar la tercer y cuarta coma (',') y por último una función para copiar en una cadena temporal los datos de la cadena principal que se encuentran entre las comas encontradas anteriormente.

Código: C
  1. #include <xc.h>
  2. #include <stdint.h>
  3.  
  4. /* Trama emulada */
  5.  uint8_t cadena[] = {"004+26.2,+79.1,+0.217,+0.944,+0.034,+13.218"
  6.                             "+13.552,+12.478,+12.273,+0.035,+26.2"};
  7.  
  8.  
  9.  
  10.  
  11. /*
  12.  * Devuelve el indice de la coma buscada
  13.  */
  14. uint8_t encontrarComa(uint8_t *str, uint8_t posicion);
  15.  
  16. /*
  17.  * Copia un fragmento de la cadena str2 en str1,
  18.  * comenzando en start y terminando en end
  19.  */
  20. uint8_t *copiarCadena(uint8_t *str, uint8_t *str2, uint8_t start, uint8_t end);
  21.  
  22. void main(void)
  23. {
  24.     uint8_t indiceComasInicio;
  25.     uint8_t indiceComasFinal;
  26.     uint8_t temporal[10];
  27.  
  28.  
  29.     indiceComasInicio = encontrarComa(cadena, 3);
  30.     indiceComasFinal = encontrarComa(cadena, 4);
  31.    
  32.     copiarCadena(temporal, cadena, indiceComasInicio, indiceComasFinal);
  33.  
  34.     while(1);
  35. }
  36.  
  37. uint8_t encontrarComa(uint8_t *str, uint8_t position)
  38. {
  39.     uint8_t indiceComa;
  40.     uint8_t indiceCadena;
  41.  
  42.     indiceComa = 0;
  43.     indiceCadena = 0;
  44.     while((*str != 0) && (indiceComa < position))
  45.     {
  46.         if (*str == ',')
  47.         {
  48.             indiceComa++;
  49.         }
  50.         str++;
  51.         indiceCadena++;
  52.     }
  53.     return indiceCadena - 1;
  54. }
  55.  
  56. uint8_t *copiarCadena(uint8_t *str, uint8_t *str2, uint8_t start, uint8_t end)
  57. {
  58.     uint8_t *localStr;
  59.     uint8_t indice;
  60.  
  61.     localStr = str;
  62.     indice = start + 1;;
  63.     while ((*str2 != 0) && (indice < end))
  64.     {
  65.         *localStr = str2[indice];
  66.         indice++;
  67.         localStr++;
  68.     }
  69.     return str;
  70. }
Título: Re: Trama de datos por RS485 a RS232 con Pic y Display
Publicado por: BINARIO en 05 de Septiembre de 2014, 12:16:58
Hasta acá viene funcionando todo bien en la simulación de RS232, pero tengo que pasarme al 485, para ello voy a emplear un SN75179BP o algún MAX.
El problema lo tengo con el código de la función para manejar el RS485, lo estoy empezando a ver, pero aun no entiendo bien como funciona, lo estuve estudiando de un tutorial que subio red pic, en breve estare actualizando la informacion, creo que es todo problema de como manejar las funciones para RS485, pero por ahora no lo saque andando, subo la ultima version que tengo del codigo que viene funcionando bien con RS232.

//****************************************************************************
//EL TRANSMISOR O SENSOR PROPIAMENTE DICHO
//
//*****************************************************************************
//Esta unidad emula a la transmision de datos de una Hydraprobe II
 //*****************************************************************************
 
 
 
///////////////////////////////////////////////////////////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>
#include <string.h>

int flag=0;
char comando[7];


#int_rda
void serial_isr()
{
 while(comando!=0x0D)
      {     // mientras que buffer sea diferente de 0x0A
         gets(comando);
      }

 //
 
}


void main()
{
 float p,q, qq, pp;
 int i, j, k;
 
 char triplebarra [7] = "OK";
 char T0[7] = "T0";
 char T3[7] = "T3";
 
 
 setup_adc_ports(AN0_AN1_AN3); //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, "   HERACLES V1.00   ");
 delay_ms(1000);
 
 /*printf(lcd_putc, "\f");
 printf(lcd_putc, "///TO\r\n");
 delay_ms(1000);
 printf("///TO\r\n");
 delay_ms(1000);
 printf(lcd_putc, "r");
 delay_ms(1000);
 printf("r");
 delay_ms(10000);*/  //Rutina de prueba de impresion


 
  enable_interrupts(global);
  enable_interrupts(int_rda);
   
  //case 1:  //TR\n\r         ascii: TR0xD0x10   
  //               

  //printf(lcd_putc, "\fMEDIR....>");
  //delay_ms(100);
  //break;

  //case 2:   //T3\n\r        ascii:  T30xD0x10
 
 
 
  while (TRUE)
  {
   i = strncmp (comando, triplebarra, 4);
   while(i != 0)
   {
    while (TRUE)
    {
     j = strcmp (comando, T0);
     while (j != 0)
     {
      while (TRUE)
      {
         k = strcmp (comando, T3);
         while (k != 0)
         {
            set_adc_channel(0);
            delay_us(20);
            q = read_adc();
            p = (5 * q/512)/10+0.003;
 
            set_adc_channel(1);
            delay_us(20);
            qq = read_adc();
            pp = (5 * qq/512)*10+0.003;
 
           printf(lcd_putc, "\fMEDICION ....\n");
            printf(lcd_putc, "%.3f", p);
            delay_ms(100);
            printf("004+26.2,+79.1,+%.3f,+0.944,+0.034,+%.3f,+13.552\n\r", p, pp);
         } 
      } 
     }
    }
   }
  }

 
 
 
 
 
}

//**********************************************************************************



//**********************************************************************************
// EL RECEPTOR O MICRO.
//**********************************************************************************
//
///////////////////////////////////////////////////////////Definiciones Standart

#include <16F876A.h>
#use delay(clock=4000000)  //Reloj en 4Mhz

#FUSES XT,NOWDT         //Cristal XT sin Watchdog


#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7))
                        //Configuro la uart del pic con:
                        //9600 Kbaudios
                        //8N1
                        //TX: RC6 RX: RC7
                       

#include <string.h>     //Con esta libreria puedo manejar cadenas.
#include <LCD420.C>     //Para manejar un LCD de 4x20

#BYTE PORTC = 0x07      //Defino la posicion del puerto C
#BYTE TRISC = 0x0F      //Defino la posicion de configuracion del puerto C
#BYTE PIR1  = 0x0C      //Defino la posicion del registro de interrupciones


char cadena[];        //Cadena que se utiliza para almacenar el contenido
                        //del puerto serie de la UART.

int1 flag=0;            //bandera auxiliar

#int_rda
void serial_isr()       //Servicio de interrupcion del puerto serie.
{
 gets(cadena);          //se almacena el contenido del puerto serie en el vector
                        //cadena[50]
 flag=1;                //se actualiza el valor de flag con 1.
}



void main()
{
 
 
 
 char humedad[7], RD[8], cad_hum[45], cad_RD[45];
 
 // humedad:
 // RD:
 // cad_hum:
 // cad_RD:

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

 lcd_init();                     //Funcion que inicializa el LCD
 
 
 //----------------------------- INTRO -----------------------------------------
 

 
 
 printf(lcd_putc, "\f   HERACLES V1.00   ");
 delay_ms(100);
 lcd_gotoxy(1,2);
 printf(lcd_putc, " Sistema manual de  ");
 lcd_gotoxy(1,3);
 printf(lcd_putc, "    medicion de     ");
 lcd_gotoxy(1,4);
 printf(lcd_putc, "  humedad de suelo  ");
 delay_ms(1000);
 
 
//------------------------------------------------------------------------------ 
 
 
 printf(lcd_putc, "\fPresione un boton...");
 
 
 while(TRUE)
 {
 
//La siguiente condicion impone que para comenzar se presione cualquier boton 
 
  if (bit_test(portc,0)==1 || bit_test(portc,1)==1)
  {   
     delay_ms(200);
     if (bit_test(portc,0)==1 || bit_test(portc,1)==1)
     
      {
        while (TRUE)
        {
         printf(lcd_putc, "\fPresione TR ...");
         
            delay_ms(100);     
            if (bit_test(portc,0)==1 )
            {
             delay_ms(100);
             if (bit_test(portc,0)==1 )
             {
               printf(lcd_putc, "\nOK!");
               delay_ms (1000);
               printf(lcd_putc, "\nPresione T3...");
               delay_ms (500);
               
               
               
               while (bit_test(portc,2)!=1)
               {
                if (bit_test(portc,1)==1 )
                {
                 delay_ms(100);
                 if (bit_test(portc,1)==1 )
                 {
                     
                     printf(lcd_putc, "\n.");
                     delay_ms (400);
                     printf(lcd_putc, ".");
                     delay_ms (400);
                     printf(lcd_putc, ".");
                     delay_ms (400);
                     printf(lcd_putc, "OK!");
                     delay_ms (500);
               
                     //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);
                 
                  }  //Cierre if anidado antirrebote
                }    //Cierre if anidado 
             
               }           
               flag = 0;
     
     
     
      }  //Cierre del ciclo while anidado
     
     }   //Cierre de primer if
    }    //Cierre de segundo if despues del antirrebote
   
   }     //Cierre del while
 
  }
 }

}       //Cierre del MAIN

 
//***********************************************************************************




Eso es lo que tengo andando ahora en el ISIS, la idea es pasarlo a RS485 para comunicarme de una con el sensor que requiere algunos comandos especificos para poder entrar en confianza jeje.
Esta tarde subo mis avances saludos !