Go Down

Topic: How to use Venus838FLPx GPS module with Arduino Uno (Read 596 times) previous topic - next topic

fmemon

I just got a hold of a Venus838FLPX GPS breakout board from this site. I got the basic hookup connected and was able to get GPS NMEA data to show up on my serial monitor as well, but I was unable to change any of the settings on the GPS itself, like the baud rate, update rate, etc. Here is my connections scheme that I used: image

Just to explain what's going on in the picture, these are the connections that I made:
  • Uno <-USB-> PC
  • GPS Power -> 3.3V
  • GPS GND -> GND
  • Uno pin 10 -> Bi-directional Logic Shifter -> GPS TX
  • Uno pin 11 -> Bi-directional Logic Shifter -> GPS RX


I used the application notes found here to determine what my binary commands should be. Based on that I created some code for my Uno which I've included below. The code below should update the GPS to update at 2Hz, but I've yet to have success with it.
Any ideas what I should change up to get my commands to register with the GPS board?

Code: [Select]
#include <SoftwareSerial.h>

SoftwareSerial gpsSerial(10, 11);

void setup() {
 // put your setup code here, to run once:
 Serial.begin(9600);
 gpsSerial.begin(9600);

 byte updateRate[] = {0xA0, 0xA1, 0x00, 0x03, 0x0E, 0x02, 0x00, 0x0C, 0x0D, 0x0A};
 gpsSerial.write(updateRate, sizeof(updateRate));
 gpsSerial.flush();
}

void loop() {
 // put your main code here, to run repeatedly:
 if (gpsSerial.available()) {
   Serial.write(gpsSerial.read());
 }
 if (Serial.available()) {
   gpsSerial.write(Serial.read());
 }
}

pert

Please explain exactly what you mean by "I've yet to have success with it."

Try different line ending settings in the menu near the bottom right corner of the Serial Monitor.

fmemon

I meant that I have not been able to change the GPS refresh rate to 2Hz by sending the binary code that I had in my sketch.

From what I can see, the connections have all been done correctly.

fmemon

Bump, any ideas why I can't get the update rate to change on the GPS? This is the code that I'm using:

Code: [Select]
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);

  mySerial.begin(9600);

  char updateRateCmd[] = {0xA0, 0xA1, 0x00, 0x03, 0x0E, 0x02, 0x00, 0x0C, 0x0D, 0x0A};
  mySerial.write( updateRateCmd ); // tell GPS to change update rate
}

void loop() { // run over and over
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
    if (Serial.available()) {
      mySerial.write(Serial.read());
    }
}

-dev

The bytes are correct, but you are not declaring and sending it correctly.  Do this instead:

Code: [Select]
  uint8_t updateRateCmd[] = {0xA0, 0xA1, 0x00, 0x03, 0x0E, 0x02, 0x00, 0x0C, 0x0D, 0x0A};  
  mySerial.write( updateRateCmd, sizeof( updateRateCmd ) );

When you write a char type (one argument), it thinks you are sending a plain C string.  C strings mark the end with a NUL character (zero byte), so it was only sending the first two bytes.

Writing the uint8_t type requires two arguments so it can also send zero bytes (and all the rest).

That's how you did it in the first post, but I don't know why that one didn't work.
Really, I used to be /dev.  :(

fmemon

Thanks for the catch on the char thing, that was something I was messing around with and didn't realize I hadn't changed back.

I tried doing the uint8_t instead as well, but the GPS still doesn't want to update to the new update rate, so I'm not sure what's going on. Is there some way to directly communicate with these kinds of GPS units instead of going through the Arduino?

This is the latest set of code that I've used so far.

Code: [Select]

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);

  mySerial.begin(9600);

  uint8_t updateRateCmd[] = {0xA0, 0xA1, 0x00, 0x03, 0x0E, 0x02, 0x00, 0x0C, 0x0D, 0x0A};
  mySerial.write(updateRateCmd, sizeof(updateRateCmd)); // tell GPS to change update rate
}

void loop() { // run over and over
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }
}


EDIT:
Just for reference, I'm looking at sifting through just the RMC sentences in the NMEA output and all I'm seeing is the data increasing in 1 second increments.

Is it possible that the unit I have is defective?

-dev

Quote
Is there some way to directly communicate with these kinds of GPS units instead of going through the Arduino?
Yes, use a Serial-to-USB converter (aka FTDI USB converter, RS232 TTL-to-USB, etc.), at 3.3V logic levels.   Some converters are 5V, some have selectable voltage.

Sending the binary command from a Terminal Emulator program is a little awkward, though.  You would see the NMEA data.

Make sure the GPS RX pin is at ~3V (shifted down from Arduino TX pin).

Did you ever directly connect the Arduino to the GPS RX pin with a wire, not the level-shifter?  It could have damaged the GPS RX pin.
Really, I used to be /dev.  :(

fmemon

I don't recall ever doing a direct connection to the module with the Arduino.

Would this serial to USB converter work for a direct connection? https://www.amazon.com/gp/product/B00IJXZQ7C/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1

I found a GPS program on the site I got the GPS breakout from, which states it can change all the settings of the GPS, but the program is unable to get any kind of responses sent to the GPS through the Arduino, so I'm assuming a direct connection to the computer may work.

-dev

Quote
Would this serial to USB converter work
Yes, it has a jumper block to select 3.3V.
Really, I used to be /dev.  :(

fmemon

Just wanted to provide an update to this issue, since I was able to get this resolved.

I was able to get the updates made to the GPS after I got the USB serial converter. I'm still unsure why I couldn't get the Arduino Uno to send the commands, but using the USB serial converter and the GPS utility tool on the GPS seller's website, I was able to successfully get everything updated.

OhSoCurious


This is the latest set of code that I've used so far.

Code: [Select]

#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);

  mySerial.begin(9600);

  uint8_t updateRateCmd[] = {0xA0, 0xA1, 0x00, 0x03, 0x0E, 0x02, 0x00, 0x0C, 0x0D, 0x0A};
  mySerial.write(updateRateCmd, sizeof(updateRateCmd)); // tell GPS to change update rate
}

void loop() { // run over and over
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }
}


Hey, so I tried this code, except I changed mySerial to Serial2 since I am reading from an ATMega2560. I then read the next 9 bytes to see its sequence and it came out to 0xA0, 0xA1, 0x00, 0x02, 0x83, 0x0E, 0x8D, 0x0D, 0x0A which is the ACK signal. This means that the code actually DID work.


Now here's the weird thing. My code is set-up in a loop:
Code: [Select]
void setup() {
  Serial.begin(9600);
  Serial2.begin(9600); 
}

void loop() {
 
  uint8_t updateRateCmd[] = {0xA0, 0xA1, 0x00, 0x03, 0x0E, 0x04, 0x00, 0x0A, 0x0D, 0x0A};
  Serial2.write(updateRateCmd, sizeof(updateRateCmd)); // tell GPS to change update rate
  delay(30);

  Serial.println("=================");
  Serial.println(Serial2.read(),HEX);
  Serial.println(Serial2.read(),HEX);
  Serial.println(Serial2.read(),HEX);
  Serial.println(Serial2.read(),HEX);
  Serial.println(Serial2.read(),HEX);
  Serial.println(Serial2.read(),HEX);
  Serial.println(Serial2.read(),HEX);
  Serial.println(Serial2.read(),HEX);
  Serial.println(Serial2.read(),HEX);
  Serial.println("=================");
  delay(3000);
}


So it should be reading the same Acknowledge sequence with every loop but its not. So with that, I'm deducing that maybe there's something else that needs to be sent ahead to let the chip know that a command is coming? Otherwise it'll only work at start-up. 

Now Here's My Issue With This:
That only works with 1 and 2 Hz. If I update it to 4 Hz or higher I get the NACK signal back. Which is annoying because I'm shooting for 20 Hz. I'm going to try and figure it out and report back because I'd like my chip to start up every time with it sending the desired refresh rate.

I'd say it's because the faster refresh rate requires a higher baud rate but then I wouldn't be able to read the NACK signal at 9600 bps because it would have switched to sending in the faster baud rate. 

With that, does anybody have an idea of how to switch Baud Rates mid program? It's still the same Serial2.begin(115200); ?

Also, I think it's cool that we're working on the same project. Except I'm throwing it on my car and you on your motorcycle

fmemon

With that, does anybody have an idea of how to switch Baud Rates mid program? It's still the same Serial2.begin(115200); ?
Maybe do a Serial2.end() and then a Serial2.begin(115200) right after?

OhSoCurious

Just updating this for future users of this GPS. I shelved the project for a while and just got back to it this morning and figured out the issue. All it required was patience LOL.

Code: [Select]

/***************************************************
 *  This code turns updates the refresh rate of the
 *  Venus838FLPx GPS from 1 Hz to 20 Hz. I would
 *  like to thank -dev from the Arduino.org forums
 *  for the code he uploaded here:
 * 
 *  https://forum.arduino.cc/index.php?topic=438394.0
 *  Post #1
 * 
 *  This code that I have written just adds a few
 *  things and parses the data
 * 
 *  There is no error checking in the set-up. I may
 *  add that later. As of now, it assumes no error
 *  will occur and everything will work flawless.
 * 
 *                              11/23/17 DGrullon
 *                       
 *  PS. I know the code is sloppy
 ***************************************************/

// Include ////////////////////////////////////////////
#include <TinyGPS++.h>

// Definitions ////////////////////////////////////////
#define GPS_PORT        Serial2
#define SERIAL_BAUDRATE 9600
#define NEW_BAUDRATE    115200


// Function Prototypes ////////////////////////////////
void sendCommand(uint8_t*, uint8_t);
void readUpdate(void);


// Venus Commands /////////////////////////////////////
uint8_t refreshRateCmd[10] = {0xA0, 0xA1, 0x00, 0x03, 0x0E, 0x14, 0x00, 0x1A, 0x0D, 0x0A};    // 20 Hz Refresh Rate
uint8_t baudRateCmd[11] = {0xA0, 0xA1, 0x00, 0x04, 0x05, 0x00, 0x05, 0x00, 0x00, 0x0D, 0x0A}; // 115200 Baud Rate

// Objects ////////////////////////////////////////////
TinyGPSPlus gps;

// Initalizer /////////////////////////////////////////
void setup()
{
  // Start serial ports
  Serial.begin(NEW_BAUDRATE);
  GPS_PORT.begin(SERIAL_BAUDRATE); 

  // Update Venus838FLPx baud rate to 115200
  sendCommand(baudRateCmd, sizeof(baudRateCmd));
  GPS_PORT.begin(NEW_BAUDRATE);
   
  // Send Update Refresh Rate Command
  sendCommand(refreshRateCmd, sizeof(refreshRateCmd));

  return;
}


// Main Loop /////////////////////////////////////////
void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  while (GPS_PORT.available() > 0)
    if ( gps.encode( GPS_PORT.read() ) )
      displayInfo();

  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    while(true);
  }

  return;
}


// Functions /////////////////////////////////////////
void sendCommand(uint8_t* Command, uint8_t sizeOfArray)
{
  GPS_PORT.write(Command, sizeOfArray);
  GPS_PORT.flush();
  delay(10);
 
  return;
}

void displayInfo()
{
  Serial.print(F("Location: "));
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
    Serial.print(F(","));
    Serial.print(gps.altitude.meters(),6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.println();
}


The "displayInfo()" function is from the TinyGPS examples. I copied and pasted it just to test it super fast. Anyway, for those curious, it works for the Mega. All credit goes to the user named "-dev" of this forum.

Go Up