Autor Tema: Leer respuestas de comandos AT  (Leído 6460 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Leer respuestas de comandos AT
« en: 24 de Enero de 2013, 12:57:49 »
Hola amigos!! Como estan?
Estoy trabajando con un modem Quectel M95. Hice pruebas conectandolo a la PC y funciona perfecto. Ahora lo tengo conectado a un PIC, y quisiera saber que me recomiendan para interpretar las respuestas del modem a los comandos AT que le envio.
Por el momento estoy llenando un buffer con lo que me llega del modem, y luego hago un strcmp para ver si la respuesta es la que yo esperaba. Sin embargo, hay respuestas que son variables. Por ejemplo:

Código: [Seleccionar]
AT+QISACK
+QISACK: 20,20, 0
OK

Ese comando devuelve cuantos caracteres se enviaron, cuantos se trasmitieron exitosamente, y cuantos no se trasmitieron. Y luego hay un "OK".
Se me ocurre que puedo usar strstr para buscar el OK dentro de la cadena.


Este es el codigo que tengo por el momento, pongo en negrita todo lo que tenga que ver con el procesamiento del buffer:

Código: C
  1. #include <18F26J50.h>
  2. #FUSES NOWDT,INTRC_PLL_IO,NODEBUG,NOXINST,STVREN,NOPROTECT,NOFCMEN,IESO,NOIOL1WAY,NOCPUDIV,LPT1OSC,T1DIG,PLL2                
  3.  
  4. #use delay(clock=48M,INTERNAL)
  5.  
  6. #include "Hardware.h"   //definicion de pines y PPS
  7. #include <usb_cdc.h>
  8. #include <string.h>
  9.  
  10. #use rs232(UART2, baud = 9600, STREAM = M95_STREAM)
  11.  
  12.  
  13.  
  14. char in_buffer[32];
  15.  
  16.  
  17. #INT_RDA2
  18. void uart2_isr(){
  19.    int i=0;
  20.    while(kbhit(M95_STREAM) && i<32){
  21.       [b]in_buffer[i]=fgetc(M95_STREAM);[/b]
  22.       usb_cdc_putc(in_buffer[i]);
  23.       i++;
  24.    }
  25. }
  26.  
  27.  
  28.  
  29. void init(){
  30.    // Digital IO
  31.    set_tris_a(0b1110011);  //OSC2,NC,VREG,M95_ON,LED_R,NC,NC
  32.    set_tris_b(0b11000110); //PGD,PGC,SDO2,SCK2,CS,SDI2,RX2,TX2
  33.    set_tris_c(0b10111111); //RX1,TX1,D+,D-,VUSB,NC,T1OSI,T1OSO
  34.    
  35.    output_low(M95_PWRKEY);
  36.    output_low(LED);
  37.    setup_adc_ports(NO_ANALOGS);
  38.    setup_adc(ADC_OFF);
  39.    enable_interrupts(INT_RDA2);
  40.    enable_interrupts(GLOBAL);
  41.    
  42.    memset(in_buffer,0,sizeof(in_buffer));
  43. }
  44.  
  45.  
  46.  
  47.  
  48. void main(){
  49.    [b]char str_ok[]="\r\nOK\r\n";[/b]
  50.    
  51.    
  52.    delay_ms(100);
  53.    init();
  54.    
  55.    usb_cdc_init();
  56.    usb_init();
  57.    
  58.    while (!usb_cdc_connected());
  59.    delay_ms(10);
  60.    printf(usb_cdc_putc,"*USB conectado\r\n");
  61.    
  62.    
  63.    output_high(LED);
  64.    output_high(M95_PWRKEY);
  65.    delay_ms(2500);
  66.    output_low(LED);
  67.    output_low(M95_PWRKEY);
  68.    
  69.    do{
  70.       fputs("AT\r\n",M95_STREAM);
  71.       printf(usb_cdc_putc,"*AT\r\n");
  72.    }[b]while(!strncmp(str_ok,in_buffer,sizeof(str_ok)));[/b]
  73.    
  74.    printf(usb_cdc_putc,"*El modem respondio OK\r\n");
  75.    
  76.    while(TRUE){
  77.       output_toggle(LED);
  78.       delay_ms(500);
  79.       while(usb_cdc_kbhit())
  80.          fputc(usb_cdc_getc(),M95_STREAM);
  81.    }
  82. }


No utilizo gets() porque el modem siempre responde con un <cr><lf>respuesta<cr><lf>. Lo que hace que la cadena termine en el primer <cr>.

Espero sus consejos. Gracias!!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Leer respuestas de comandos AT
« Respuesta #1 en: 24 de Enero de 2013, 17:31:50 »
yo también quiero hacer lo mismo (aunque con otro módem)  :mrgreen:

el problema es que el pic sepa a partir de que posición del buffer debe leer la respuesta, porque el modem devolverá un valor diferente a partir del carácter n+k

sería cuestión de crear una tablita donde almacenar el ancho de las respuesta de los comandos at que usemos

en mi caso, quiero leer el famoso +creg 0,1
La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: Leer respuestas de comandos AT
« Respuesta #2 en: 24 de Enero de 2013, 18:04:59 »
Perdon PalitroqueZ, pero no te sigo. A que te referis con que devolvera un valor diferente a partir de n+k? Que es n y que es k?
El buffer que estoy usando yo no es circular, sino que con cada nueva respuesta, piso el contenido anterior. Tengo q tener la precaucion de que no queden datos basura para no confundir las respuestas (probablemente poniendo un caracter nulo al final)

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado vdiazg

  • PIC12
  • **
  • Mensajes: 68
Re: Leer respuestas de comandos AT
« Respuesta #3 en: 24 de Enero de 2013, 22:47:36 »
Les cuento mi caso, yo trabaje con el SIM900 y de igual forma tenia muchos comandos AT y la mayoria de respuestas eran de longitud variable, pero lo que siempre tenia en cada respuesta, eran los caracteres 0x0D y 0x0A, citando un ejemplo (para el sim900)

Al enviar el comando AT+CREG?
Se tiene que recibir     +CREG: 0,1
y luego se recibe un    OK

Este comando sirve para saber si el modulo se conecto a la RED
los valores en HEX de +creg: 0,1 OK

0D 0A 2B 43 52 45 47 3A 20 30 2C 31 0D 0A 0D 0A 4F 4B 0D 0A

si se dan cuenta cada frase esta encerrada entre 0D 0A, es por ello que en mi codigo recibo cada byte y lo comparo con 0A que justamente es el ultimo byte en recibir, y lo discrimino creando un registro (cnttrama), el cual tiene que tener el numero de cadenas que se tiene que recibir, ya que de antemano uno tiene que saber que espera recibir, en este caso en particular (la funcion CREG) se espera recibir 2 cadenas (+CREG: 0,1 y luego OK), cada vez que se reciba un 0A el cnttrama se decrementa, cuando se hace cero, se pone un flag (flagresp=1) para que al salir de la interrupcion se analize la respuesta recibida, el valor real que tiene que ser cargado en "cnttrama" es 4 (para este comando en particular), ya que se espera recibir 4 bytes de 0x0A y este valor se carga antes de lanzar el comando AT


Aqui pedazos del codigo

Código: [Seleccionar]
#INT_RDA
void recepcion_rxd(){

  if(kbhit()){ // Si hay algo pendiente de recibir ...

    add_2_cbuff(getc()); // lo descargo yañado al buffer y ...

  }
}


La funcion principal es "add_2_buff" que es la que recoge y une todo lo recibido

Código: [Seleccionar]
// Añade a cbuff -----------------------
void add_2_cbuff(char c){
  switch(c){
    case 0x0A: // Enter -> Habilita Flag para procesar comando
        cnttrama--;
        if(cnttrama==0){
            flagresp=1;}
    break;
    case 0x0D:
    break;
    case 0x3E: //simbolo ">" que es la habilitacion para escribir SMS
    break;
    default: // Añade caracter recibido al Buffer
        if (xbuff<=78){
            cbuff[xbuff++]=c;}
        else if ((xbuff>=79)&&(xbuff<=101)){
            smsbuff[(xbuff++)-79]=c;}
        else{
            smsbuff[18]=c;}
      CNTRXD++;
  }
}

algunos detalles: cbuff es el buffer de recepcion (80 bytes) si lo que se recibe sobrepasa esto (en el caso de recibir SMS) todos los bytes que se desbordan solo llegan a la ultima posicion

Aqui se hace la comparacion, como se daran cuenta con la funcion "add_2_cbuff" se unen las 2 cadenas y asi es mas facil el analisis

Código: [Seleccionar]
strcpy(xcommand,"+CREG: 0,1OK");
if(!strncmp(cbuff,xcommand,12)){
        // Aqui su codigo si recibieron la frase exacta.
}
else{
        // Aqui su codigo si hubo error.
}
}

Si desean mas detalles o los formatos de respuesta (SIM900) o algo del codigo que no entiendan me avisan  :-)
« Última modificación: 25 de Enero de 2013, 03:37:48 por vdiazg »
quiero construir un "Condensador de flujos"

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Leer respuestas de comandos AT
« Respuesta #4 en: 25 de Enero de 2013, 08:51:28 »
Por aquí hay un par de temas interesantes para leer:

http://www.embedded-exploited.com.ar/2012/12/administracion-de-modulos-gsm-en.html?utm_source=BP_recent
http://www.embedded-exploited.com.ar/2012/12/identificacion-de-respuestas-comandos.html?utm_source=BP_recent
http://sistemasembebidos.com.ar/foro/index.php?topic=1412.0
http://www.ucontrol.com.ar/forosmf/proyectos-con-pic/telecontrol-gsm-desarrollo-de-proyectos/

Lo conveniente, me parece, es hacer una maquina de estados y recibir la respuesta por interrupciones. En la interrupcion vas cargando lo que llega en un buffer para luego ser tratada. Generalmente con 0D 0A vas a saber determinar cuando termino de llegar una respuesta.


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: Leer respuestas de comandos AT
« Respuesta #5 en: 25 de Enero de 2013, 09:16:31 »
Excelente material muchachos!! Mil gracias!
Ahora tengo para entretenerme un rato jeje. Voy a leer todo de a poco y cualquier duda o comentario lo posteo ;)

Saludos!!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: Leer respuestas de comandos AT
« Respuesta #6 en: 25 de Enero de 2013, 09:22:23 »
Yo también voy a leer y seguir este post, pronto tengo que meterme de cabeza en el tema !! :mrgreen:
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Leer respuestas de comandos AT
« Respuesta #7 en: 25 de Enero de 2013, 12:17:18 »
Pegate una vuelta por este post.

http://sistemasembebidos.com.ar/foro/index.php?topic=1808.msg8068#msg8068

Desde mi punto de vista, la implementación va a depender de que ram y flash disponible tengas en el micro.

Saludos !

Desconectado Sat3llite5

  • PIC10
  • *
  • Mensajes: 8
Re: Leer respuestas de comandos AT
« Respuesta #8 en: 30 de Enero de 2013, 17:56:26 »
Yo tenia el mismo problema cuando comenze a usar el sim900, al recibir mensajes , la señal etc...  y mi solucion fue usar un strstr() que busque "parte de la cadena" para identificar de que se trata lo que llego, una vez identificado escribir una funcion que separe la cadena por ","(te daras cuenta que todo esta separado por ",")...bueno esa fue mi solucion rapida espero y te sirva ....

Saludos!!!

Desconectado fighter

  • PIC10
  • *
  • Mensajes: 14
Re: Leer respuestas de comandos AT
« Respuesta #9 en: 27 de Febrero de 2013, 15:09:46 »
Buena dia estimados

Estoy teniendo problema para leer los datos que llegan por la puerta UART del micro. Estoy usando un 18F26J50, CCS 4.104
Tengo certesa que el pic envia bien los comandos y el modem los ejecuta sin problema. El modem esta enviando las respuestas, las puedo ver y leer, pero tengo un problema con la interrupcion del micro para poder leerlas desde el micro. Cualquier ayuda sera bien recibida.


#include <stdlib.h>
#include <string.h>
#include "usb_cdc.h"                  // Descripción de funciones del USB.
#include "usb_desc_cdc.h"     // Descriptores del dispositivo USB.
#include <18F26J50.h>

#device adc=10
#FUSES PRIMARY                  //Primary clock is system clock when scs=00
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                    //Watch Dog Timer uses 1:128 Postscale
#FUSES HSPLL                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPROTECT            //Code not protected from reading
#FUSES PLLDIV3
#FUSES NOCPUDIV

#use delay(clock=48M,type=xtal)
#use rs232(UART1,baud=9600,parity=N,xmit=PIN_A1,rcv=PIN_A0,bits=8,stop=1,stream=gsm)

#use standard_io(a)
#use standard_io(b)
#use standard_io(c)
 
#define PIN_ON  output_high
#define PIN_OFF output_low
#define POWERKEYGSM  PIN_C1
#define PANIC  PIN_C0
#define LED  PIN_B2

#byte OSCCON = 0xFD3          //requerido por USB
#byte UCFG  = 0xF39                //requerido por USB
#byte OSCTUNE= 0xF9B          //requerido por USB




/*****************************************************************************
* RUTINA DE SERVICIO DE INTERRUPCION DEL PORT SERIE1 (MAQUINA DE ESTADO)         *
* EL MODEM RESPONDE CON UNA TRAMA DE LA FORMA <CR><LF> DATO <CR><LF>          *
* --------------------------------------------------------------------- ---------------------------------- *
*    TX ---> RA0   pin 2                                                                              *
*    RX <--- RA1   pin 3                                                                              *
* -------------------------------------------------------------------------------------                           *
*                                                                         *                                           
************************************************************************/

#int_RDA
void rx_serial_gsm (void)
{
char aux,SBUF;

clear_interrupt(INT_RDA);
disable_interrupts (GLOBAL);

printf (usb_cdc_putc, "C");    // como test de funcionamiento de la rutina

enable_interrupts (GLOBAL);

}



//*****************************************************************************
//   Programa Principal
//*****************************************************************************

void main()
{
   
   setup_adc_ports (NO_ANALOGS|VSS_VDD); //desactivo entradas analogicas
   setup_adc (ADC_OFF|ADC_TAD_MUL_0); //desactivo entradas analogicas
   setup_spi (SPI_SS_DISABLED);
   setup_spi2 (SPI_SS_DISABLED);
   setup_wdt (WDT_OFF);
   setup_timer_0 (RTCC_INTERNAL);
   setup_timer_1 (T1_DISABLED);
   setup_timer_2 (T2_DISABLED, 0, 1) ;
   setup_timer_3 (T3_DISABLED|T3_DIV_BY_1);
   setup_timer_4 (T4_DISABLED, 0, 1) ;
   setup_comparator (NC_NC_NC_NC);
   setup_vref (FALSE);
 
   
   set_tris_a (0b00101101);
   set_tris_b (0b00011011);
   set_tris_c (0b10000010);
   
   OSCTUNE = 0xC0;      //requerido por USB configuracion de osc
   OSCCON = 0xF0;        //requerido por USB config osc
   UCFG |= 0x4;               //requerido por USB config osc
   
   
   //-----------------MI PROGRAMA!!------------------------------------------
   
   usb_cdc_init ();      // Configuramos al puerto virtual.
   usb_init ();             // Inicializamos el stack USB.
     
   WHILE ( ! usb_cdc_connected () ){}      // espera a detectar una transmisión de la PC
   
   
   PIN_ON (POWERKEYGSM);                    //Enciendo modulo GSM
   inicializacionMODEM ();
   
   
   enable_interrupts (INT_RDA2);
   enable_interrupts (INT_RDA);
   enable_interrupts (GLOBAL);
   
   
   delay_ms(6500);
   fputs("atdt 1526541786;",gsm);   
   
   
   WHILE (TRUE)
      {
       usb_task();
       void tareas_usb ();
      }
     
   }

adjunte el circuito para mayor comprension


desde ya gracias


 

anything