Pages: [1]   Go Down
Author Topic: Comunicación Serial con Modem Enfora  (Read 1102 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola a todos Agradezco si me pueden colaborar con mi proyecto lo que deseo hacer es conectar mi arduino uno por los pines rx y tx a un modem ENFORA enviar un comando at recibir la info de respuesta del modem adjuntar un dato y devolver la info al modem con otro comando.
Lo que hago es enviar el comando
AT$MDMID? El modem me responde
$MDMID: "AAA001"
OK
Necesito tomar solo el dato AAA001. El primer problema que tengo es con la instrucción Seril.read() no puedo tomar todo el dato solo me toma el primer carácter y lo segundo como hago para tomar solo el dato AAA001?

Agradezco su colaboración
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 153
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola.

Que casualidad, llevo un tiempo haciendo lo mismo y no lo he conseguido, solo por ahora. Ya que su pouerto RS232 es d e3.3V.

Dejo un ejemplo de lo que he hecho hace semanas pero cn PIC, para que te hagas una idea.

Code:
; ZONA DE DATOS **********************************************************************


LIST P=16F88
INCLUDE <P16F88.INC>
__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _FOSC_EC
;_XT_OSC
     __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF

CBLOCK 0x20
ENDC

ENTER EQU .13 ; Código de tecla "Enter" o "Retorno de Carro".
CAMBIO_LINEA EQU .10 ; Código para el cambio de línea.

#DEFINE  Entrada0  PORTB,4 ; Define dónde se sitúan las entradas.
#DEFINE  Entrada1  PORTB,5
#DEFINE  Entrada2  PORTB,6
#DEFINE  Entrada3  PORTB,7

; ZONA DE CODIGOS ********************************************************************

ORG 0
goto Inicio
ORG 4 ; Aquí se sitúa el vector de interrupción para
goto LeeEntradasVisualiza ; atender las subrutinas de interrupción.

Mensajes ; Los mensajes no deben sobrepasar las 256
addwf PCL,F ; primeras posiciones de memoria de programa.
MensajeEntradas
DT ENTER, .1, .2, .3, .4, .5, ENTER, 0x00
MensajeWlanActive1
DT "wlan active 1", ENTER, 0x00
goto Salir
MensajeWlanActive0
DT "wlan active 0", ENTER, 0x00
Salir
call Retardo_5s
call Retardo_1s
DT "exit", ENTER, 0x00
call Retardo_1s

Inicio
call RS232_Inicializa
bsf STATUS,RP0 ; Configura como entrada las 4 líneas correspondientes
bsf Entrada0 ; del Puerto B respetando la configuración del
; bsf Entrada1 ; resto de las líneas.
; bsf Entrada2
; bsf Entrada3
bcf OPTION_REG,NOT_RBPU ; Activa las resistencias de Pull-Up del Puerto B.
bcf STATUS,RP0
bcf STATUS,RP1
call RS232_LineasBlanco ; Visualiza unas cuantas líneas en blanco
call RS232_LineasBlanco ; para limpiar la pantalla.
call LeeEntradasVisualiza ; Lee las entradas y visualiza por primera vez.
movlw b'10001000' ; Habilita la interrupción RBI y la general.
movwf INTCON
Principal
sleep ; Espera en modo de bajo consumo que se
goto Principal ; modifique una entrada.

; Subrutina de Servicio a la Interrupcion" ----------------------------------------------
;
; Lee el estado de las entradas y las monitoriza en la pantalla del HyperTerminal.

LeeEntradasVisualiza
call RS232_LineasBlanco
movlw MensajeEntradas ; Nombre de las entradas.
call RS232_Mensaje ; Lo visualiza en el ordenador.
;LeeEntrada3
; btfss Entrada3 ; ¿Entrada = 1?, ¿Entrada = Abierta?
; goto Entrada3Cerrado ; No, está cerrada.
; call VisualizaAbierto
; goto LeeEntrada2
;Entrada3Cerrado
; call VisualizaCerrado
;LeeEntrada2
; btfss Entrada2 ; Se repite el procedimiento para las
; goto Entrada2Cerrado ; demás entradas.
; call VisualizaAbierto
; goto LeeEntrada1
;Entrada2Cerrado
; call VisualizaCerrado
;LeeEntrada1
; btfss Entrada1
; goto Entrada1Cerrado
; call VisualizaAbierto
; goto LeeEntrada0
;Entrada1Cerrado
; call VisualizaCerrado
LeeEntrada0
btfss Entrada0
goto Entrada0Cerrado
call VisualizaAbierto
goto FinVisualiza
Entrada0Cerrado
call VisualizaCerrado
FinVisualiza
call RS232_LineasBlanco
bcf INTCON,RBIF ; Limpia el flag de reconocimiento de la
retfie ; interrupción.
;
VisualizaAbierto
movlw MensajeWlanActive1 ; Visualiza el mensaje "Abierto"
call RS232_Mensaje ; en el HyperTerminal.
return
VisualizaCerrado
movlw MensajeWlanActive0 ; Visualiza el mensaje "Cerrado"
call RS232_Mensaje ; en el HyperTerminal.
return

INCLUDE  <RS232.INC>
INCLUDE  <RS232MEN.INC>
INCLUDE  <RETARDOS.INC>
END

En esta parte se envía o recibe los comandos AT.
PAaa los comandos AT.
Code:
goto LeeEntradasVisualiza ; atender las subrutinas de interrupción.

Mensajes ; Los mensajes no deben sobrepasar las 256
addwf PCL,F ; primeras posiciones de memoria de programa.
MensajeEntradas
DT ENTER, .1, .2, .3, .4, .5, ENTER, 0x00
MensajeWlanActive1
DT "wlan active 1", ENTER, 0x00
goto Salir
MensajeWlanActive0
DT "wlan active 0", ENTER, 0x00
Salir
call Retardo_5s
call Retardo_1s
DT "exit", ENTER, 0x00
call Retardo_1s

Hace semansa compré Arduino UNo r3, haré pruebas con él si me sale te lo enseño.

El router tiene contraseña, ahy que indicarlo dentro del PIC o Arduino. Pulsas Entere, en realidad lo envías que es 0x13 y salto de línea que es 0x10 para mensajes.

Contraseña en mic aso de ejemplo, 12345, luego Enter. Cuando entres, enviarás comandos y lo leer con el serial terminal o una LCD que pusiste en ARduino.

Saludo.
« Last Edit: February 20, 2014, 12:09:51 pm by Metaconta » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hola Metaconta gracias por la info la voy a analizar y te agradesco si encuentras la solucion para arduino ya llevo varios dias en lo mismo y no lo he logrado
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 153
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola:

Lo que no se si se puede dejar el router sin contraseña, sería las pruebas más códomas. ¿Tienes un router ZyXEL?

Me he pegado más de un mes y hace menos me copré Arduino, parace ser más fácil. Por lo que tengo entendido, mi router tiene el puerto serie dentro para comunicarse por RS232, lo comunico al PC con HyperTerminal de Windows, el TerraTerm Pro e incluso el minicom de Linux. Ahora me toca comunicarlo con cualquier microcontrolador.

Como el PIC y Arduino funcionan a 5 V y el RS232 del router funcona a 3.3V, se necesita un convertidor de tensión como este:

Hoja de datos o datasheet:
74HC4050

También vale este otro y hay muchos más.
HEF4050BP

No se te ocurre añadirle 5V al pin de 3.3V porque lo quemas. Más bien no le conecté nada y no tuve éxito. Deja ver con Arduuino si me hace caso.

Los comandos mejor enviarlo tipo hexadecimal. Funcionan a la primera.

La idea es así:
Dejar el router que se inicie unos buenos menutos.
No debe tener contraseña, si la tienes, pues debes usarlo a travez de Arduinoy enviarlo como hexadecimal.
Recibirás comando desde el inicio y debes reflejarlo en algún LCD para que te des cuenta, aunque sea el 16x2, se le puede poner el de 20x4.
Envías 0x13 que en Enter.
Sale menús en la LCD o en el ordenador si lo tienes conectado ahí.
Tiene que ser paso por paso.

El ejemplo tonto que quiero hacer es activar y desactivar Wi.fi por ese puerto, si lo logro, ya hago lo que quiero.

Saludo.
« Last Edit: February 20, 2014, 01:28:09 pm by Metaconta » Logged

Palencia, Spain
Offline Offline
Sr. Member
****
Karma: 25
Posts: 479
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola. Deberías echar primero un vistazo a la referencia de Serial para entender cómo trabaja read y de paso ver otros comandos útiles.
Quizás te podría servir, tras enviar tu comando algo como:

Code:
char comando[21], respuesta[21];
void setup() {
        Serial.begin(9600);
  // put your setup code here, to run once:

}

void loop() {
        if (Serial.available() > 0) {
                comando[Serial.readBytesUntil(':', comando, 20)]=0;
                respuesta[Serial.readBytesUntil('\n', respuesta, 20)]=0;
                Serial.print("Comando: ");
                Serial.println(comando);
                Serial.print("Respuesta: ");
                Serial.println(respuesta);
        }
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hola noter gracias por la info y me funciona un poco mejor pero sigo con vario problemas soy bastante nuevo en esto y no entiendo bien la sintaxis de las comandos o mejor dicho este

respuesta[Serial.readBytesUntil('\n', respuesta, 20)]=0;

si pudieras explicarmelo me ayudarias mucho y eternamente agradecido jejej
Logged

Palencia, Spain
Offline Offline
Sr. Member
****
Karma: 25
Posts: 479
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Efectivamente, te he puesto una línea un poco críptica, que condensa varios comandos.
Te la desempaqueto a ver si es más legible:

char comando[21];  // un buffer de 21 caracteres para guardar el comando
int numCaracteresLeidos=Serial.readBytesUntil(':', comando, 20); // Lee caracteres hasta encontrar ':' y devuelve el número de caracteres leídos
comando[numCaracteresLeidos]=0; // agregamos a los caracteres leídos un terminador de cadena (caracter 0 o '\0'
Logged

Spain
Offline Offline
God Member
*****
Karma: 25
Posts: 956
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No has mirado este post que colgue hace un tiempo?
http://forum.arduino.cc/index.php?topic=176212.msg1313025#msg1313025
Logged

CUIDADO !! MIS POST NO SON APTOS PARA MENORES. SI ERES MENOR DE 14 AÑOS DEBES DE LEERLOS ACOMPAÑADO DE UN ADULTO

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

compañeros ante todo gracias por su colaboracion me ha sido muy util ya casi logro el mi objetivo les comento exactamente que es lo que etoy haciendo:

a un modem (equipo de rastreo satelital enfora) le meto el comando AT$GPSRS=10 a lo que el modem me responde:

$GPRMC,153852.00,A,0438.681488,N,07408.994629,W,0.0,0.0,260214,5.4,E,A*2B

de esa cadnea solo necesito el dato de velocidad que es el que esta despues de la W  que es la velocidad y devolverlo al modem por medio de otro comando;

aca dejo el codigo que use me funciona bien pero las primeras 6 veces luego me muestra datos raros lo que creo es que tengo que limpiar la varilabes char antes de usarlas nuevamente pero no se como hacer eso



int i = 0;
char GPS_RMC[100];
char *lck;          // Creamos un puntero de tipo char

void setup(){
  Serial.begin(9600);
  Serial.flush();
}

void loop (){
  Serial.flush();
  Serial.println("AT$GPSRD=10");  // envia comando al modem
  delay(2000);                                 // espera respuesta
  if(Serial.available()>0){
     Serial.readBytesUntil('$',GPS_RMC,80);  // lee los datos apartir de $
  }
    i=0;
    lck = strtok(GPS_RMC,",");                        // corta la cadena recibida por la comas
    if(strcmp(lck,"GPRMC")==0){                   //si es correcto
      while(lck != NULL)
      {
        lck = strtok (NULL,",");                             // pasa al siguiente tramo
        RMC=lck;
        i++;
 }
 
  Serial.print("AT$MSGSND=4,");                      //enviamos el dato nuevamente
  Serial.print('"');   // enviar caracter "              // al modem
  Serial.print(RMC[6]);                                       // mediante el comando envio de mensaje
  Serial.println('"');                                             
  delay(5000);
}
}
Logged

Palencia, Spain
Offline Offline
Sr. Member
****
Karma: 25
Posts: 479
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola.
Tu código me da un error de compilación, ya que RMC no aparece definido:
Quote
sketch_feb26a:23: error: 'RMC' was not declared in this scope
sketch_feb26a:29: error: 'RMC' was not declared in this scope
No sé si será por eso que no consigo entender el código de búsqueda del parámetro W.
No obstante, hay un par de cosillas que creo que deberías revisar. En primer lugar, donde lees el serial, lees hasta encontrar el carácter $, con lo que la primera vez te va a devolver sólo ese caracter, y hasta no volver a recibir el $ de la segunda trama (o salte un timeout), no va a salir del readBytesUntil con los datos de la primera trama. Yo utilizaría como carácter de final para readBytesUntil el último que envíe la trama, que supongo que sea salto de línea o retorno de carro (puedes analizar la trama para  cerciorarte).
En segundo lugar, ese delay de cinco segundos al final podría hacer que, si el modem sigue enviando datos, el buffer serial se llegue a llenar, con lo que vas a perder datos y podría ser la causa de que te empiece a dar valores extraños tras varias repeticiones de loop.
Saludos.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hola noter si ya lo corregi y me funciona bien ya tengo el dato y lo puedo trabajar pero ahora tengo otro problemita pequeñito ese dato tengo que convertirlo a Kilometros por hora me explico.

el dato bien en nudos y lo necesito en kilometros por hora para eso tengo que multiplicarlo por 1.8532 he leido pero no comprendo bien como manejar estas operaciones .

lo que hice fue definir unas variables

int vel = 0;
int  conv = 1.8532 ;
int  km =  0;

y luego de cortar la trama en pedasitos tomo el que contiene la velocidad para convertirlo

vel = atoi (RMC[6]);      // convertir a entero el RMC[6] que es la velocidad extraida de la trama
 km = vel*conv;            // lo multiplico por la varable de convercion a kilometros

pero la verdad no se si eso es correcto y pues no he podido pobarlo en movimiento para verificar si si da bein la convercion tu me podrias explicar si esta mal el porque?

el codigo final es este y me ha funcionado bien (despues de las dos primeras veces que se envia el comando jejeej)

int i = 0;           // variable acumulador
char TrazaGps[100];  // Array donde se almacenan los bytes leidos de la trama gps
char *RMC[15];       // array de punteros de tipo char
char *lck;           // Creamos un puntero de tipo char
int vel = 0;
int conv = 1.8532 ;
int km = 0;

void setup()
{
  Serial.begin(9600);
  Serial.flush();
}

void loop ()
{
  Serial.flush();
  Serial.println("AT$GPSRD=10");
   
    Serial.readBytesUntil('$',TrazaGps,80);
    i=0;
    lck = strtok(TrazaGps,",");
    if(strcmp(lck,"GPRMC")==0)        // verifica si si es la trama GPRMC
    {
      while(lck != NULL)
      {
        lck = strtok (NULL,",");                 // pasa al siguiente tramo
        RMC=lck;
        i++;
 }
 
 vel = atoi (RMC[6]);                        // convertir a entero el RMC[6] que es la velocidad extraida de la trama
 km = vel*conv;                                // pasarlo a kilometros 
  delay(2000);
  Serial.print("AT$MSGSND=4,");    //escribimos el comando
  Serial.print('"');                               // enviar caracter "
  Serial.print(km);                             // Escribimos la velocidad
  Serial.println('"');                          // enviar caracter " y enter
  delay(1000);
    }
   
}
Logged

Palencia, Spain
Offline Offline
Sr. Member
****
Karma: 25
Posts: 479
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola.
El problema es debido a que has definido las variables como int, por lo que estás multiplicando por 1 y no por 1.8532.
Tal vez te baste con declarar conv como float , y si no basta, tendrás que convertir también a flota vel.
Saludos.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

muchas gracias era eso ya me funciona perfecto
Logged

Pages: [1]   Go Up
Jump to: