Reading GPS data using Arduino and a U-blox NEO-6M GPS receiver

Arduino GPS serial

It is possible to read, and log GPS data, such as time, position, speed, and so on, using an Arduino microcontroller plus an U-blox NEO-6M GPS receiver.

For my test, I used an Arduino Ethernet and a U-blox NEO-6M GPS, which I bought on Amazon Japan for 2,580Yen (about 17 Euro), a very cheap price.

In order to interface the Arduino with the GPS receiver, you have to connect the following pins: power supply VCC (5V), GND (0V), and serial RX and TX. You need to connect the GPS receiver TX to the Arduino RX, and RX with TX. Actually, the NEO-6M GPS serial communication works with 3.3V voltage signal, while Arduino works with 5V voltage signals. However, it is possible to connect the Arduino serial pins directly to the NEO-6M pins without any problem.

U-blox NEO-6M GPS
U-blox NEO-6M GPS

On Arduino side, I used the pins 7 (RX) and 8 (TX) and the Software Serial Library. In fact, the Arduino built-in serial port (0=RX, 1=TX) was already used for the communication with the PC. In the picture below, pins 3, 5 and 6 are also connected to an other Arduino Micro, but these pins are not used in this sketch.

U-blox NEO-6M GPS Arduino Ethernet
U-blox NEO-6M GPS Arduino Ethernet

The following Arduino sketch is continuously polling, once in a second, data from the GPS receiver. In order to poll GPS data, the command PUBX,00 is used (this is a proprietary command of U-blox). The received data is then forwarded to the PC serial connection, and visualized on the screen.

GPS_data_screenshot_2
GPS_data_screenshot_2

I removed part of the information, for privacy (otherwise you would know exactly the coordinates of the place where I live). The message forwarded to the PC is as below (instead of "xxxx" and "yyyy", the latitude, longitude and height positions were received). The original message received by the GPS receiver has a "$" at the beginning, and a "*" at the end (before the checksum). I used these 2 character to understand when the message starts and when it ends. The data which Arduino sends to the PC is only the characters between "$" and "*" (I did not implement any checksum check at the moment).

PUBX,00,131309.00,aaaaa.bbbbb,N,ccccc.ddddd,E,xxx.yyy,G3,28,22,1.757,8.60,0.032,,1.86,2.76,1.99,6,0,0

The sketch that I used is as following, and can be downloaded here: GPS_serial_test. In order to run this sketch, you will also need the "Tempo" library which uses Timer1 and can be downloaded here: tempo_library_v1. I used Timer1 in to create a 10ms scheduler, and manage the polling request every 100 scheduler tasks (10ms x 100 = 1s).

By default, the NEO-6M outputs RMC, VTG, CGA, GSA, GSV, GLL messages once a second (these are standard NMEA messages). Since I wanted to receive the info by polling message (i.e. not automatically, to avoid Arduino sofware serial reception overloading), I first had to disable the automatic sending of the messages (for example, for RMC, this can be done by sending to the GPS receiver the command: $PUBX,40,RMC,0,0,0,0*47). This configuration is performed at the first loop execution. The software then polls the info (time, position, speed) by using the proprietary $PUBX,00*33 request.

The complete protocol explanation for the NEO-6M GPS receiver can be downloaded here: u-blox6 Receiver Description Protocol Specification. The official manual explains which are the NMEA standard messages (ASCII codification) supported, and also the details of the proprietary UBX protocol (binary codification). The explanation of the message $PUBX,00 can be found at pages 68-70. In the next article, I will show how you can use Arduino Ethernet to log GPS data on the SD memory, and then transfer it to the PC.

Author: Davide Cavaliere

I am an Italian Electrical Engineer graduated at Politecnico di Milano. My interests are motorcycles and cars, electronics, programming, Internet of Things, and Japanese culture.

28 thoughts on “Reading GPS data using Arduino and a U-blox NEO-6M GPS receiver”

  1. Hi, i have tried with the above code for NEO 6M GPS and it works well. But, the value read for position and altitude is displayed as zero and there is no match to the time displayed in real time....Please help me in tackling this problem.

  2. Hello! Thanks for you message. Can you please copy and paste the message that you visualize on Serial Monitor?
    Also, did you make sure that the GPS is properly connected to the satellites? If you are in a room, that might require several minutes 😉

  3. The fastest way to identify your location, is to copy-paste latitude and longitude on Google Maps, and press Enter.
    You can write in a format such as: "lat, lon", or "lat lon", Google Maps automatically understands the format.

  4. I have tried the above code But, the values corresponding to 'lat' and 'lon' is displayed as zero.

    Time,5001,5532,
    PUBX,00,090728.00,0000.00000,N,00000.00000,E,0.000,NF,5316349,3759226,0.000,0.00,0.000,,99.99,99.99,99.99,0,0,0
    Time,6988,7519,
    PUBX,00,090730.00,0000.00000,N,00000.00000,E,0.000,NF,5316353,3759229,0.000,0.00,0.000,,99.99,99.99,99.99,0,0,0

    1. Ah, sorry, I forgot to add one thing to the previous message. If you check the contents of your message, you can notice that "NF" is written inside the "Navigation Status" field. "NF" stands for "Not Fix", so it means that your GPS is not connected to the satellites. Please make sure that you are outside of your house, and that the antenna is properly connected, and that you turn it ON for at least some minutes. Usually 30 seconds - 1 minute should be enough.

  5. Please have a look at the data-sheet, which explains the protocol.
    If you check there, you can see that the message called "PUBX,00" corresponds to: "Lat/Long Position Data".
    At least you receive messages from the Ublox Neo 6M, so it means that at least Serial Communication is working properly. However, inside the message, the longitude and latitude are both 0.0 so I think that it cannot properly connect to GPS satellites. Are you sure that the antenna is working properly?
    By the way, in order to decode the message, the structure of its data is: "$PUBX,00,hhmmss.ss,Latitude,N,Longitude,E,AltRef,NavStat,Hacc,Vacc,SOG,COG,Vvel,ageC,HDOP,VDOP,TDOP,GU,RU,DR,*cs"
    If you copy the string above on Google, you will find the Ublox Neo 6M manual, which explains in detail the meaning of all fields.

    1. Good news. Now, you can check your position using Google Maps. First of all, you should extract, from your message, the portion which contains the info about Latitude and Longitude.
      The Latitude is the number before "N" or "S" (North or South), it must be a number between 0.0 and 90.0 (degrees).
      The Longitude is the number before "E" o "W" (East or West), it must be a number between 0.0 and 180.0.
      You just need to take both numbers and copy them in Google Maps.
      For example: in case you visualize: "17.0,N,30.0,E", it means that your position is 17 degrees North and 30 degrees East. In Google Maps, you can either write one of the following:
      17.0N 30.0E
      17.0 -30.0
      Both formats should be understood by Google Maps. Please try. In case it does not work, please post me the message that you get from Arduino. I can help you.

    1. Hello. "tempo.h" is a custom library which I implemented. I used it to schedule a function "scheduled_interrupt()" once every 10ms (10000us). This is done by using the Timer1.
      Basically, the scheduled interrupt function is called every 10ms, and each time, a counter increased. When the counter reaches its max (200 in this case), the Arduino sends a polling message PUBX to the Ublox Neo 6M.
      Then, inside the main loop(), Arduino is checking for any message received from Ublox GPS. The message characters are stored into a buffer. Once the complete message is received, Arduino forwards it to the PC, which is connected on the USB serial.
      Regarding the flag "bool first_loop_exec", it is a boolean flag which is "true" when executing the loop for the first time, and then becomes false. It has the purpose to configure the GPS module at the first time that loop() is executed. Once the loop is executed the second time and so on, the configuration of the Ublox GPs is not done anymore, since "bool first_loop_exec" is false.

  6. Hello David ...First OF All Thanks For This Good Tutorial About GPS
    Second I want To Know
    My Readings That I Had From This Code Above Give Me Always That 0000.000E That Means There is No East Or SomeThing Like That ...
    And There Is a North Readings
    I want to Know What is The Wrong Here
    Thanks in Advance

    1. Hello Ahmed!
      It is strange that it shows North position, but not East position.
      Could you please kindly copy-paste the message that you receive from Arduino IDE, on Serial Monitor?
      Actually, what this sketch does is just forwarding the message received from Ublox Neo 6M, to the PC. No data change is done. So if the message content is strange, it means that the problem is somewhere inside Ublox. Are you sure that the satellites are properly connecting? What about the antenna connection?
      Please post a message and I can help you more...

  7. This is the output I get on the Arduino serial monitor.
    I have the led on the neo-6 module blinking, the N and E data fields change only in the last four digits by a few numbers. G3 is in the NF data field. After that is a number around 14 to 21 which changes with orientation of antenna.
    Of course the degrees values cannot be right. If the decimal place is shifted left, around 52 N and 1.3 E would be 30km south and west of my location, but that is maybe just coincidence.
    After the E data is another field. If this is the height above sea level, then this is correct for my location.
    These are the last N and E values taken (and they are saved on the neo-6 module exactly as I saw them last when outside) then I have to go back inside to connect to the internet and send this comment, so the other fields have reverted to the 'no fix' states.
    I know it is so much to ask you, but what do you think could be going on?
    Anyone else have this problem? Pro mini 5v with FTDI USB adaptor. On board neo-6 is 3.3v regulator and logic level shift resistors.
    Everything seems connected fine and your software is doing its thing. But N, E data is garbled somehow.
    Connected
    Time,5002,6084,
    PUBX,00,120612.00,5220.67431,N,00131.24339,E,69.967,NF,20429,6244,0.000,0.00,0.000,,99.99,99.99,99.99,0,0,0

    1. Please check the Ublox Neo 6M "protocol manual" (search in Google). For "PUBX,00" messages, the format is:
      $PUBX,00,hhmmss.ss,Latitude,N,Longitude,E,AltRef,NavStat,Hacc,Vacc,SOG,COG,Vvel,ageC,HDOP,VDOP,TDOP,GU,RU,DR,*cs
      As you can see in your message, the field "NavStat" has value "NF", which means "No Fix". Basically, it means that the Ublox Neo 6M cannot connect to the satellites. However, it is running properly, and properly connected to Arduino (otherwise you would not see any message on Serial Monitor!).
      Therefore, you need to find the root cause why the Ublox Neo 6M cannot connect to satellites.
      According to my experience, and also other people who left messages here below, the reason might be: antenna not good, antenna not properly connected, you are testing inside a building, and so on... Please notice that GPS cannot connect well from inside a building. In my house (2 floors) I can connect because my PC is close to the window, but still it takes a quite long time, such as 1-2 minutes.
      Try to test your Ublox from outside your building, and let me know. In case you still get "NF" (Not Fix), I think that the problem is the antenna. You can try to change. Or, if cheaper, try to buy another Ublox. Last year I could find one on Ebay for just 8 Euro, from Spain.

    2. Sorry. I understood now your problem. As stated in the "Protocol Manual" of Ublox Neo 6M, the format for latitude and longitude values is "dddmm.mmmm".
      Therefore, it means that:
      5220.67431 -> 52 degrees and 20.67431 minutes
      00131.24339 -> 1 degree and 31.24339
      The reason why you get a location 30 km far from your house, is that you need to convert minutes in degrees decimals (deg=min/60), and sum.
      I am not 100% sure about that, but I think that 60 minutes is 1 degrees. Therefore, your GPS location in degrees becomes:
      52.34457183N 1.52072317E
      Copy paste in Google Maps and check. Is it correct?

      1. Many thanks. Yes, you are correct. The minutes and the decimal part of the minutes must be converted to degrees!
        I was just about to post the same solution to my own comment, I have just been outside leaving the GPS to run for an hour.
        Accurate results now which agree with Google.
        You have done a great service to everyone trying to quickly test and get ideas on sketches to use these neo-6 modules. Mine with tiny G165 (linear polorisation) ceramic antenna was only £4, about 5 euro. I will use this as a free IPEX lead and plug and make a proper bifilar helix, which is much lighter than the 25mm square ceramic antennas as well as having collecting more signal.
        The ublox u-centre is now only available for the latest operating systems. I googled and found a version 7.01, which allows configuration (be careful, my baud rate suddenly changed to 57200 on trying a 'reset to default settings') but no fancy display or NEMA data. With a pro mini and FTDI, u-centre will ignore all serial gps input except some debug info which is just mainly ???. This may be because ublox have outwitted the manufacturers of ebay fake FTDI chips which don't have a valid internal serial number.

        1. I encourage anyone who relies on one of these modules to hold a quadcopter position to make a lightweight 'back-fire bifilar helix' antenna.
          I am getting 25 satellites visible on the satellite stats field, indoors! Picking the best and most consistent the Ublox Neo-6 is giving me divergence of only 0.3 metres over an hour.
          I used 1mm enamelled copper wire and a section from an old transistor radio telescoping aerial. Fed the original ceramic G165 IPEX wire down the middle with a 68pF cap to avoid shorting the antenna power feed. Soldered the bottom end of the brass tube into ground plane of the nearest mounting hole on the neo-6 module. I could be lucky with my soldering and dimensions, but this combination is going to be a rock solid fix position on the drone.
          The tiny 6x4x20mm ceramic G165 antennas are already hi-tech, I mean there are a lot of components under the shielding can to match impedance and maybe a bit of gain. But that tiny patch with the logo is the entire collector part of the thing. The same weight of copper as a helix wins hands down. From nothing at all to 25 satellites is a big jump.

  8. Davide,
    First of all,...thank you for taking the time to write the code and posting all of this on the web.
    Your work is the only piece of code, I have managed to find that works with an Arduino Nano
    and a Ublox NEO M8N module.
    I will be posting this fantastic information for the Arduino community on the Arduino.cc site
    All credit will be in your name (of course)...
    Salutations from Shawinigan Canada
    Perry

  9. Hi
    im using NEO6 GPS with arduino uno and im getting the result, so im using u-ceter to detect my location, but the ports option not working.
    so please help me if you can
    bar.aa10@@hotmail.com

  10. Dear David,

    I haven't implemented this yet, just researching for a bike theft tracking system that I am building, but I wanted to thank you for your patience in answering the questions.

    If you are interested in working collaboratively on IoT stuff at some point, let me know.

Leave a Reply

Your email address will not be published. Required fields are marked *