GPS (uBlox) a través de BLUETOOTH HC-05

Hola, estoy intentando enviar los datos del GPS a través del bluetooth.

Por un lado, recibo los datos del GPS bien, y por otro, la comunicación con el BT también me funciona bien.

Lo que intento hacer es enviar un comando al BT "START GPS" o "STOP GPS" para que empiece a enviar los datos los del GPS o pare de hacerlo.

El caso es que cuando "junto todo", sí que me envía los datos del GPS pero los comandos del BT que le envío no llegan. Si comento la línea de GPS.begin(38400), el BT recibe perfectamente los comandos.

Se trata algún tipo de interferencia al usar la librería SoftwareSerial? O algo del baudrate? El GPS está a 38400 y el BT a 115200.

Gracias de antemano.

#include <SoftwareSerial.h>

SoftwareSerial BTSerial(10, 11); // RX | TX
SoftwareSerial GPS(2, 3); // RX | TX

String buffer;

char command[200];
char commandId[10];
byte commandIndex;

boolean sendGPS = true;


void setup()
{
  Serial.begin(38400);
  BTSerial.begin(115200);
  delay(100);
  GPS.begin(38400);   // Si comento esta línea recibo los comandos bien.
  delay(100);

  Serial.println("Enter commands:");
}

void loop()
{
  readBluetooth();
  
  if(GPS.available())
  {
    char recv = GPS.read();
    buffer.concat(recv);
    if(recv == '\n')
    {
      if(sendGPS)
      {
        Serial.print(buffer);
        BTSerial.print(buffer);
      }
      buffer = "";
    }
  }
  
}


void readBluetooth()
{
  char charRecv;
  while (BTSerial.available()) 
  {
    Serial.println("sfgssds");    Serial.println("sfgssds");    Serial.println("sfgssds");    Serial.println("sfgssds");    Serial.println("sfgssds");    Serial.println("sfgssds");
    charRecv = BTSerial.read();
    if(charRecv == '\n')
    {
      // Termino el string
      command[commandIndex] = '\0'; 
      processCommand(command);

      //Inicializo el string
      commandIndex = 0;
      command[0] = '\0';
    }
    else
    {
      command[commandIndex] = charRecv;
      commandIndex++;
    }
  }
}

void processCommand(char* command)
{
  Serial.println(command);

  //SPEED 0 700
  char* commandSplit = strtok(command, " ");
  char* param1;
  char *param2;
 
  while(commandSplit != 0)
  {
    
    if(strcmp(commandSplit, "START") == 0)
    {
      commandSplit = strtok(0, " ");
      param1 = commandSplit;
      commandSplit = strtok(0, " ");
      param2 = commandSplit;

      if(strcmp(param1, "GPS") == 0)
      {
        sendGPS = true;
      }
    }
    else if(strcmp(commandSplit, "STOP") == 0)
    {
      commandSplit = strtok(0, " ");
      param1 = commandSplit;
      
      if(strcmp(param1, "GPS") == 0)
      {
        sendGPS = false;
      }
    }

    commandSplit = strtok(0, " ");
  }
}

Por lo visto con el Arduino UNO / Mini / Nano no se puede hacer ya que solo tiene un puerto UART.

El Arduino Mega sin embargo tiene cuatro por los que sí que se podría hacer.

Todo lo puedes hacer usando SoftwareSerial que es una libreria que te permite usar dos pines del arduino creando una UART Virtual.
La nueva libreria se llama NewSoftwareSerial

Intentado usar la de NewSoftwareSerial me dice que está obsoleta, que se reemplaza por SoftwareSerial.

Se ve que el problema es la hora de recibir, a la hora de enviar no hay problemas... De echo, recibo bien tanto el GPS como el BT si envío datos... Pero lo que intento es enviar un comando y se queda "perdido", nunca lo recibe el BT, o si lo recibe, recibe parte de él...

He probado con el listen() y tampoco parece funcionar bien... Sigo trasteando...

Gracias.

De echo, en el link que me pones:

Limitations

The library has the following known limitations:

  • If using multiple software serial ports, only one can receive data at a time.

No estoy seguro si con el listen() y comprobando el isListening() se podría hacer.

Tienes alguna experiencia con esto surbyte?

Ahora lo que estoy intentando hacer es durante 30 segundos recibir del GPS y durante 5 segundos parar de recibir de este dándole tiempo al BT a q reciba algún comando...

Va algo mejor pero todavía no acabo de cogerlo...

Gracias.

Por mi experiencia personal en el uso de GPS con Arduino, he podido comprobar que el SoftwareSerial, no se comporta muy bien a velocidades superiores a 9600, de forma que cuando tengo que conectar un GPS a velocidades altas, lo hago en el puerto serie normal y programo el Arduino con un programador ISP.

noooo espera.. NewSoftwareSerial es la última.
Me ha costado bajarla ahora, intenta con este nuevo link

Cuanta razón tiene carmeloco para que esto?

  BTSerial.begin(115200);
  delay(100);
  GPS.begin(38400);   // Si comento esta línea recibo los comandos bien.

comprate un MEGA para usar esas velocidades.

Voy a volver a explicar un poco mejor lo que quiero hacer, quizá me expliqué mal.

Lo que quiero hacer es tener la posibilidad de enviar con el móvil el comando "START GPS" a través del BT y que el módulo BT HC-05 lo reciba y sea entonces cuando empiece a enviar los datos que recibo del GPS.

Luego, mientras recibo datos del GPS a través del BT, enviarle otro comando "STOP GPS" y que deje de enviar los datos.

Como ambos dispositivos se conectan a través de conexiones de UART (entiendo), he intentado usar el SoftwareSerial para ello.

Cuando he conectado todo (GPS al 8,9 y BT al 10,11), el recibir los datos del GPS funciona OK, y el transmitirlos a través del BT HC-05 al BT del móvil también, pero cuando envío desde el móvil el comando, la condición del BT.available() nunca se cumple, y si se cumple, viene solo parte del comando.

Si comento la línea del GPS.begin(), el BT recibe y envía datos/comandos sin problemas.

Se puede hacer lo que quiero con el Arduino Uno / Pro / Mini?

carmeloco, por lo q me dices, aunque conectase el GPS a los pines RX/TX directamente, el BT lo tendría que hacer también con SoftwareSerial, pasaría lo mismo?

surbyte, esa librería me falla también:

In file included from TwoNSSTest.pde:1:
C:\Program Files (x86)\Arduino\libraries\NewSoftSerial/NewSoftSerial.h:71: error: conflicting return type specified for 'virtual void NewSoftSerial::write(uint8_t)'
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/Print.h:48: error: overriding 'virtual size_t Print::write(uint8_t)'

Conflicto con Print.h?

Tenía entendido que la de SoftwareSerial ya tenía integrado esto del NewSoftwareSerial

He bajado el baudrate del GPS yd el BT a 38400 y parece que ya funciona.

No entiendo muy bien en que afecta el baudrate... intentaré informarme mejor.

Gracias por vuestra ayuda.

Baudrate tasa de baudios o bits por segundos. La velocidad con que te devuelve datos el/los dispositivos.
Ahora dime si tu puedes ver datos mas rápido que 9600 presentados en la pantalla me avisas.
38400 es una barbaridad aún.

Pues sigo teniendo problemas.

Si conecto el GPS con el USB-Serial y mirando la consola en el UBlox Center, a 38400, los datos del GPS son estos

$GPRMC,205417.40,V,,,,,,,230115,,,N*78
$GPVTG,,,,,,,,,N*30
$GPGGA,205417.40,,,,,0,00,99.99,,,,,,*67
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,02,17,01,033,,18,05,234,*75
$GPGLL,,,,,205417.40,V,N*4B
$GPRMC,205417.60,V,,,,,,,230115,,,N*7A
$GPVTG,,,,,,,,,N*30
$GPGGA,205417.60,,,,,0,00,99.99,,,,,,*65
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,02,17,01,033,,18,05,234,*75
$GPGLL,,,,,205417.60,V,N*49

Con un codigo súper simple

#include <SoftwareSerial.h>

SoftwareSerial GPS(8, 9);

void setup()
{
  Serial.begin(38400);
  GPS.begin(38400);

}

void loop()
{
  if (GPS.available() > 0) 
  {
    Serial.write(GPS.read()); 
  }
}

Me da estos datos:

$GPRMC,,V,,,,,,,,,,N*53
$GB$GPDTM,W84,,0.0,N,0.0,E,0.0,W84*6F
$GPRMC,,V,,,,,,,,,,N*53
$G
$GPDTM,W84,,0.0,N,0.0,E,0.0,W84*6F
$GPRMC,,V,,,,,,,,,,N*53
$G,$GPDTM,W84,,0.0,N,0.0,E,0.0,W84*6F
$GPRMC,,V,,,,,,,,,,N*53
$GG$GPDTM,W84,,0.0,N,0.0,E,0.0,W84*6F
$GPRMC,,V,,,,,,,,,,N*53
$G9$GPDTM,W84,,0.0,N,0.0,E,0.0,W84*6F
$GPRMC,,V,,,,,,,,,,N*53
$GP$GPDTM,W84,,0.0,N,0.0,E,0.0,W84*6F
$GPRMC,,V,,,,,,,,,,N*53
$G5$GPDTM,W84,,0.0,N,0.0,E,0.0,W84*6F
$GPRMC,,V,,,,,,,,,,N*53

Hay saltos de línea que no son, carácteres que se cuelan...

He probado bajándolo a 9600 y se queda "colgado" de lo lento que va... a 19200 también parece que va mal...

Alguna idea del porqué de una forma va y de otra no?

A eso me refería yo. Surbyte, si usas un gps a 10Hz, hay que poner el baudrate por encima de 9600, aunque te parezca una barbaridad, a 9600, no funciona. El gps a 10 Hz, se usa para tener precisión a alta velocidad de movimiento, por ejemplo, en competición, para obtener el trazado del circuito y los tiempos por vuelta.

Jotastar, la única solución posible, conectarlo al serie físico. El problema que se plantea aquí, es que necesitas usar dos puertos serie rápidos. La única solución posible que veo, es usar un mega, que tiene 4.

Bueno, no lo sabía, hay muchas cosas que no he experimentado.
El tema es que cuando yo uso algo leo la hoja de datos, no pruebo a tontas y a locas.
Veo que algunos como tu carmeloco tienes formación electrónica y tienes mi criterio pero no todos lo hacen.
Cuando sugiero algo no siempre lo hago desde la experiencia, a veces es sentido común pero en este caso no era correcto.
Lo correcto hubiera sido que YO hubiera leído la hoja de datos, cosa que no hice.

Disculpas por el error cometido.
Yo creo que dos software serials son demasiado en este caso y a este requerimiento de velocidad.
La alternativa es obvia.

No creo que este caso sea cuestión de hoja de datos o ir probando a tontas y a locas, que por cierto, es una forma de ir aprendiendo, pero en fin...

Sabéis pq puede ser que se coma parte de datos? al final el baudrate es la velocidad de transmisión de la información, puede ir más a pedales o menos, pero la información debería ser coherente.

He probado todos los baudrates y devuelve la misma info, sin embargo a través del FTDI, la misma prueba (con baudrate más alto o más bajo) siempre me devuelve la info bien.

Voy a probar a hacerle un factory reset al GPS, aunq dudo q solucione algo ya que realmente con el FTDI directamente va bien.

Yo supongo que el problema está en que el softwareserial, aunque en la documentación de la librería dice que puede hacerlo, creo que no es capaz de trabajar lo suficientemente rápido. Se me ocurre que, solo por curiosidad, se podría probar en un due, que lleva un chip más rápido.

Saludos
Dice que no recibe el "comando" de inicio o stop pero que comandos son esos? Si el arduino recibe una cadena muy larga mientras tiene que atender otras cosas puede estar perdiendo datos. No veo el código para revisar pero creo que los comandos deben ser de un byte de longitud

Buenas,

Sí carmeloco, va a ser que el SoftwareSerial ese no va muy fino.

He estado leyendo más en profundidad, otro tipo de proyectos que no tienen mucho que ver con lo q yo hago pero que han tenido problemas parecidos.

Al final hablan de la librería AltSoftSerial, no es flexible pues usa los pines 8 y 9 fijos (aunque imagino que metiéndote en el código podrías cambiarlo) y limita algunas cosas como perder el PWN 10 y tal... pero bueno, probándolo ha mejorado MUCHISIMO la recepción de los datos.

Gracias!

Hola max_saeta.

Sí, lo pensé, reducir el comando a un byte en concreto... Es otra opción.

Gracias.

Porque no ensayas un cambio. Usa el Serial del Arduino para conectarse al GPS a la velocidad que desees (ya que ese es el mas critico) y softwareSerial para lo demas y te quedas sin monitor Serie o si lo necesitas, tendras que armar una salida desde SoftwareSerial via una interfaz FTDI a USB.
Siempre es mas simple todo con MEGA pero sino ese es el camino con lo que tienes