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.
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.
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.
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
#include <SoftwareSerial.h> #include "tempo.h" bool first_loop_exec; unsigned long time_1=0; unsigned long time_2=0; #define GPS_INFO_BUFFER_SIZE 128 char GPS_info_char; char GPS_info_buffer[GPS_INFO_BUFFER_SIZE]; unsigned int received_char; int i; // counter bool message_started; SoftwareSerial mySerial_GPS(7, 8); // 7=RX, 8=TX (needed to communicate with GPS) // REAL TIME SCHEDULER PARAMETERS AND VARIABLES #define SCHEDULER_TIME 10000 // scheduler interrupt runs every 20000us = 20ms #define DIVIDER_STD 200 // logging message sent every 100 scheduler times (20ms) 1s #define DIVIDER_DELAY 500 // delay after forwarding meggages is 3s unsigned int divider=0; unsigned int divider_max=DIVIDER_DELAY; // SENDS THE POLLING MESSAGE TO GPS void scheduled_interrupt() { divider++; if (divider==divider_max) { divider=0; divider_max=DIVIDER_STD; time_1 = millis(); mySerial_GPS.println("$PUBX,00*33"); // data polling to the GPS } } void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } Serial.println("Connected"); mySerial_GPS.begin(9600); mySerial_GPS.println("Connected"); first_loop_exec=true; i=0; message_started=false; Timer1.initialize(); // initialize 10ms scheduler timer Timer1.setPeriod(SCHEDULER_TIME); // sets the main scheduler time in microseconds (10ms in this case) Timer1.attachInterrupt(scheduled_interrupt); // attaches the interrupt Timer1.start(); // starts the timer } void loop() { // run over and over if (first_loop_exec == true){ delay(2000); mySerial_GPS.println(F("$PUBX,40,RMC,0,0,0,0*47")); //RMC OFF delay(100); mySerial_GPS.println(F("$PUBX,40,VTG,0,0,0,0*5E")); //VTG OFF delay(100); mySerial_GPS.println(F("$PUBX,40,GGA,0,0,0,0*5A")); //CGA OFF delay(100); mySerial_GPS.println(F("$PUBX,40,GSA,0,0,0,0*4E")); //GSA OFF delay(100); mySerial_GPS.println(F("$PUBX,40,GSV,0,0,0,0*59")); //GSV OFF delay(100); mySerial_GPS.println(F("$PUBX,40,GLL,0,0,0,0*5C")); //GLL OFF delay(1000); first_loop_exec = false; } // MANAGES THE CHARACTERS RECEIVED BY GPS while (mySerial_GPS.available()) { GPS_info_char=mySerial_GPS.read(); if (GPS_info_char == '$'){ // start of message message_started=true; received_char=0; }else if (GPS_info_char == '*'){ // end of message time_2 = millis(); Serial.print("Time,"); Serial.print(time_1); Serial.print(","); Serial.print(time_2); Serial.println(","); for (i=0; i<received_char; i++){ Serial.write(GPS_info_buffer[i]); // writes the message to the PC once it has been completely received } Serial.println(); message_started=false; // ready for the new message }else if (message_started==true){ // the message is already started and I got a new character if (received_char<=GPS_INFO_BUFFER_SIZE){ // to avoid buffer overflow GPS_info_buffer[received_char]=GPS_info_char; received_char++; }else{ // resets everything (overflow happened) message_started=false; received_char=0; } } } while (Serial.available()) { mySerial_GPS.write(Serial.read()); } } |
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.
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.
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 😉
could you please tell how to identify my current location using the received data?
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.
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
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.
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.
I changed the antenna and got co-ordinates. But I didn't know how to enter this values to get position on Google maps
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.
could you explain the code please? especially tempo.h , sheduled_interrupt(), bool first_loop_exec
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.
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
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...
This code is not working when i use it with arduino pro mini
Hello. Thank you for your feedback. Could you please tell me why it is not working? Are sure that you connected the cables to the correct pins? Do you get any error message?
There no error while uploading the code. Just showing connected on serial monitor.
I'm using arduino pro mini 3.3v
Are you sure that you connected the Ublox Neo 6M to the proper pins of your Arduino Mini? Do the LED on the Ublox turn ON?
Can you please give more information?
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
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.
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?
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.
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.
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
Thank you very much. And sorry for my late answer. You can share the code, of course. It is "open source"... 😉
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
I am sorry but I have never used U-Center. Is that the official software for the Ublox Neo 6M?
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.
Hello,
Thanks for your share.
For the CRC procedure, you could find a good work here
http://engineeringnotes.blogspot.fr/2015/02/generate-crc-for-nmea-strings-arduino.html
Ciao Davide,
Thanks for posting this GPS tutorial. I tried it and works great! This really helps me getting started with the NEO6. I'm planning to use this for a UTC clock project.
hello, i am planning to buy a ublox gps neo 6m . and i was thinking, that can i use it in real time tracking.. aside from that sir.. i still wanted to know how fast it can get an update of long and lat from the satellite?
Hello sir, if you wont mind.. will you contact me . there's a lot of questions i want to ask you.. here is my email : santieevanz@yahoo.com.. sir, i will be waiting for you PMs.. i will 🙂 Thankyou
fatal error: avr/interrupt.h: No such file or directory please help me..
what can i do
Hi sir, is there anyway we can send these data like long and lat using esp8266 to send to web application?
How to print only Lat and Lon data
Thank's you , I'm not good at english .
sir, i used this code and i am getting "connected" written on the serial monitor. not getting any output.
i can see in serial monitor as connect only...could any body please help me
Hi
Can someone tell me how the gps-module gets the speedvalue. Is it comparing the coordinates or does it get the speedvalues on an other way
Hello. I am not sure, but I think that it calculates the speed by differentiating the position. But for additional info, please refer to the U-Blox GPS datasheet.
I want to get the speed of the vehicle using neo 6m gps receiver how can I get this . and anyone give code for this?????
hey i have a problem i need a simple code that acces values of lat and long from gps module after that i want to creat a URL for googlemap by using that values please help
hi sir i interfaced Neo 6M GPS U-blox NEO-6M GPS Module with node mcu and i get the data from gps module using local wifi but i cant get the latitude, longitude data in bike ride i don't know what the reason please tell any solution
Thank you
How to interface a GPS module (NEO-6M) with Arduino Mega. The data for longitude and latitude is displayed on the serial monitor.