This post shows how to interface the NEO-6M GPS module to a PIC.
I recently purchased a NEO-6M GPS module made by u-blox from eBay. The module is manufactured by u-blox and a datasheet is downloadable on the company website. It looks like the following, with connection header for UART output and antenna:
Since my computer does not have a dedicated serial port, I connected the module’s serial output pins to a cheap USB to TTL that uses the Prolific PL-2303HXA chipset and converted it into a USB GPS module:
NMEA Output
Using Tera-Term Web 3.1 to communicate with the module at 9600bps, 8 data bit, 1 stop bit and no parity, I was quickly able to see that the module is indeed returning NMEA data:
The next task is to find an NMEA viewer to make sense of the returned data. For this purpose, I use the NMEA Monitor application, although Visual GPS is also a good alternative. With a clear view of the sky, the GPS module is able to acquire a fix in less than a minute:
That’s it, I have made a USB GPS module for less than $10! However, to do something more useful with this, I decided to attempt to interface it to the PIC24 microcontroller. If the GPS module is mounted on an RC helicopter, for example, I can program the microcontroller to read the current GPS position and transmit it remotely via RF for other processing purposes.
Interfacing with PIC24
Within hours, I was able to port the Arduino-based NMEA parser library from Adafruit to Microchip C30, ready to be tested with my PIC24. The ported library contains the following exported functions:
void GPS_common_init(void);
char *GPS_lastNMEA(void);
void GPS_pause(boolean b);
boolean is_GPS_paused();
boolean GPS_parse(char *);
char GPS_read(void);
boolean GPS_newNMEAreceived(void);
GPS_DATE_INFO GPS_getDateInfo();
GPS_SIGNAL_INFO GPS_getSignalInfo();
GPS_LOCATION_INFO GPS_getLocationInfo();
Among these functions, of note is the GPS_read()
function which updates the internal buffer whenever a byte is received from the GPS module. Once the internal buffer is updated, other GPS functions will be able to parse the NMEA data and return the associated information. To ensure timeline update of position, GPS_read()
should preferably be called from a UART data receive interrupt. This is done on the PIC24 using the following code:
IPC7bits.U2RXIP0 = 1;
IPC7bits.U2RXIP1 = 1;
IPC7bits.U2RXIP2 = 1;
IEC1bits.U2RXIE = 1;
IFS1bits.U2RXIF = 0;
void __attribute__((interrupt, no_auto_psv, shadow)) _U2RXInterrupt(void) {
if (U2STAbits.OERR == 1) {
U2STAbits.OERR = 0;
} else {
GPS_read();
}
IFS1bits.U2RXIF = 0;
}
GPS signal information, location and UTC time can be retrieved using the following code snippet:
if (GPS_newNMEAreceived())
{
char *nmea = GPS_lastNMEA();
boolean isOK = GPS_parse(nmea);
if (isOK)
{
GPS_SIGNAL_INFO info = GPS_getSignalInfo();
if (info.fix)
{
if (currentMode == MODE_GPS_LOCATION_INFO)
{
GPS_LOCATION_INFO loc = GPS_getLocationInfo();
GPS_DATE_INFO date = GPS_getDateInfo();
...
}
}
}
}
Since GPS only works outdoor with clear view of the sky, to test this indoor during development, I used the .NET Framework SerialPort control to write a simple program that will output a fixed set of NMEA data to a serial port on the PC connected to the micro-controller. The PIC would parse the received NMEA data as if it comes from the GPS module. The test application can be downloaded here.
Simple Test Board
Using a Nokia 5110 LCD module, I made a portable GPS receiver that is able to display the current GPS coordinates and UTC time:
The completed circuit, with a PIC24FJ64GA002, a Nokia 5110 LCD and the GPS module consumes 80mA-100mA during operation, with approximately 80% of the power being consumed by the GPS module. A 9V battery will therefore not last long with this circuit. To make it into a permanent and portable solution will probably require batteries with more capacity, for example, Lipo batteries used in RC helicopters.
The completed MPLAB 8 project for the GPS receiver can be found here.