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

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

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #30 en: 20 de Marzo de 2014, 11:34:17 »
porque necesitas ese delay para enviar los datos?
"Nada es imposible, no si puedes imaginarlo"

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Trama de datos por RS485 a RS232 con Pic y Display
« Respuesta #31 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.
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 #32 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.
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 #33 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.
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 #34 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. }
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 #35 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 !
000101111 101110000011110 00010 11101 110 1 000111 00010010011010111100 101101001 11110000 001 00 10110 111 00001 01110 0010101 01011110 00 00011111111 0011111 011110001111111111 1011111111101100000000