Skip to content

GPS

NEO6MV2 GPS module Figure 1: NEO6MV2 GPS module

The NEO6MV2 stand-alone GPS module allows you to receive data from GPS satellites in order to calculate the location of your project. To work properly, the module needs a clear line of sight to the satellites and it may not work indoors.

The module uses a simple serial connection consisting of a transmit (tx) pin and a receive (rx) pin. The Particle Argon has only one UART and you need to connect the tx pin of the module to the rx pin of the Argon and vice versa as shown in Figure 2.

NEO6MV2 connection Figure 2: Breadboard layout

Some GPS libraries available through the Particle IDE only work with the Particle Photon. With the Argon, you need to choose the Particle-GPS library. You can use the example sketch all-data.ino (shown below) to test your hardware setup.

  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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright © 2016-2017 Daniel Porrey. All Rights Reserved.
//
// This file is part of the Particle.GPS library.
// 
// Particle.GPS library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// Particle.GPS library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Particle.GPS library. If not, 
// see http://www.gnu.org/licenses/.
//
#include "Gps.h"

Gps::Gps(USARTSerial* serial)
{
    this->_serial = serial;
};

void Gps::begin(uint32_t baud)
{
    // ***
    // *** Initialize the serial port.
    // ***
    this->_serial->begin(baud);
    this->_serial->blockOnOverrun(true);

    // ***
    // *** Initialize the GPS.
    // ***
    this->sendCommand(PMTK_SET_BAUD_9600);
    this->sendCommand(PMTK_SET_NMEA_UPDATE_200_MILLIHERTZ);
    this->sendCommand(PMTK_API_SET_FIX_CTL_1HZ);
    this->sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
    this->sendCommand(PMTK_ENABLE_WAAS);
    this->sendCommand(PGCMD_ANTENNA);
};

void Gps::end()
{
    this->_serial->end();
}

void Gps::sendCommand(const char* data)
{
    this->_serial->println(data);
    delay(250);
}


void Gps::onSerialData()
{
    if (this->_serial->available())
    {
        char c = this->_serial->read();

        if (!this->_synced && c == '$') this->_synced = true;

        if (this->_synced)
        {
            if (this->_bufferIndex > BUFFER_SIZE)
            {
                Serial.println("Buffer Overun: '");
                this->_bufferIndex = 0;
                this->_synced = false;
            }
            else if (c == '\r')
            {
                // ***
                // *** Replace this character will a NULL.
                // ***
                this->_buffer[this->_bufferIndex] =  0;
                this->_bufferIndex++;
            }
            else if (c == '\n')
            {
                // ***
                // *** Replace this character will a NULL.
                // ***
                this->_buffer[this->_bufferIndex] =  0;

                // ***
                // *** This is the end of a sentence. Copy the data to
                // *** a secondary backup buffer.
                // ***
                String tempBuffer = String((char*)this->_buffer);

                // ***
                // *** Check which sentence we have and copy it to the
                // *** correct buffer. Note the first buffer at index 0
                // *** is a discard buffer in case we get a sentence that
                // *** is not expected.
                // ***
                uint8_t index = this->msgIdToIndex(tempBuffer);
                this->data[index] = tempBuffer;

                // ***
                // *** Reset the buffer.
                // ***
                this->_bufferIndex = 0;
                this->_synced = false;
                this->clearBuffer();
            }
            else
            {
                this->_buffer[this->_bufferIndex] = c;
                this->_bufferIndex++;
            }
        }
    }
}

void Gps::clearBuffer()
{
    for(int i = 0; i < BUFFER_SIZE; i++)
    {
        this->_buffer[i] = 0;
    }
}

When the sketch is running, you can use the Particle CLI to monitor the serial communications. In a terminal window on your computer, type the following command.

1
particle serial monitor

If everything is working, you should see a series of data blocks like the one shown below which is made up of one National Marine Electronics Association (NMEA) sentence per line.

1
2
3
4
5
6
7
Data[0] = $GPGLL,,,,,,V,N*64
Data[1] = $GPGGA,,,,,,0,00,99.99,,,,,,*48
Data[2] = $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
Data[3] = $GPGSV,4,1,16,01,,,21,02,,,22,03,,,22,04,,,22*7C
Data[4] = $GPRMC,,V,,,,,,,,,,N*53
Data[5] = $GPVTG,,,,,,,,,N*30
Data[6] = 

Notes

$GPGLL: Geographic position, latitude / longitude
$GPGGA: Global Positioning System Fix Data
$GPGSA: GPS dilution of precision (DOP) and active satellites
$GPGSV: GPS satellites in view
$GPRMC: Recommended minimum specific GPS/Transit data
$GPVTG: Track Made Good and Ground Speed

The example above shows how the output looks before the GPS resolves the location. Line 4 shows that there are 16 satellites in view, but there is no location information in line 1. It may take up to a few minutes for the module to resolve the position at which point the displayed information will look more like that shown below.

1
2
3
4
5
6
7
Data[0] = $GPGLL,5558.14854,N,00309.70605,W,171248.00,A,A*7D
Data[1] = $GPGGA,171248.00,5558.14854,N,00309.70605,W,1,04,4.78,9.8,M,49.8,M,,*43
Data[2] = $GPGSA,A,3,23,24,10,12,,,,,,,,,5.35,4.78,2.42*0B
Data[3] = $GPGSV,2,2,05,24,61,260,44*49
Data[4] = $GPRMC,171248.00,A,5558.14854,N,00309.70605,W,0.224,,031121,,,A*60
Data[5] = $GPVTG,,T,,M,0.224,N,0.416,K,A*24
Data[6] = 

In this example, the $GPGLL sentence can be interpreted as follows:

Element Value Meaning
Sentence identifier $GPGLL Geographic Position, Latitude / Longitude and time
Latitude 5558.14854 55 degrees, 58.14854 minutes
North/South N North
Longitude 00309.70605 3 degrees, 9.70605 minutes
East/West W West
Timestamp 171248.00 17:12:48 UTC
Validity A Valid
Checksum A*7D Error check

The behaviour of the module can be disconcerting when it first starts. The on-board LED only starts to flash once a fix has been obtained. Until then, there is no visible sign that the board is working. If you are looking for reassurance that everything is working correctly, it is therefore better to rely on the data output rather than on the hardware itself.

Fritzing part Fritzing part

Interpreting NMEA sentences Interpreting NMEA sentences

NMEA Reference Manual NMEA Reference Manual