Notes About Working with Various Arduino & Netduino Microcontroller Boards

Sunday, June 16, 2013

Adafruit Ultimate GPS Breakout & the Netduino Plus 2

I wrote yesterday about using the Adafruit Ultimate GPS Breakout (ver. 3) with an Arduino Due. This GPS module also works quite nicely with the Netduino. To get reception while working at my desk, this external GPS antenna and connector are a big help.

Connections 


GPS Breakout  Netduino Plus 2
TX            Digital 0 (COM1 RX)
RX            Digital 1 (COM1 TX)
GND           GND
VIN           3V3

Code


This code reads the latitude and longitude from the GPRMC NMEA sentence. It converts them to degrees, minutes, and seconds, and then prints them to the debug console. 

namespace GPS
{
    public class Program
    {
        public static void Main()
        {
            SerialPort serial = new SerialPort(SerialPorts.COM1, 9600, Parity.None, 8, 
                StopBits.One);
            serial.ReadTimeout = 1000;
            serial.WriteTimeout = 1000;
            serial.Open();
            String sentence = "";
            while (true)
            {
                if (serial.BytesToRead > 0)
                {
                    int c = serial.ReadByte();
                    sentence += (char)c;
                    if ((char)c == '\n')
                    {
                        if (sentence.IndexOf("GPRMC") > 0)
                        {
                            try
                            {
                                String[] data = sentence.Split(',');
                                // 3rd element = A if data is valid; V = invalid
                                if(data[2] == "A")
                                {
                                    int deg = Int16.Parse(data[3].Substring(0,2));
                                    int min = Int16.Parse(data[3].Substring(2,2));
                                    Double seconds = Double.Parse(data[3].Substring(4,5))*60;
                                    // \xB0 is degree sign
                                    // "F3" format formats seconds to 3 decimal places
                                    Debug.Print(deg + "\xB0 " + min + "' " +  
                                        seconds.ToString("F3") + "\" N");
                                    deg = Int16.Parse(data[5].Substring(0,3));
                                    min = Int16.Parse(data[5].Substring(3,2));
                                    seconds = Double.Parse(data[5].Substring(5,5))*60;
                                    Debug.Print(deg + "\xB0 " + min + "' " + 
                                        seconds.ToString("F3") +  "\" W");
                                }
                            }
                            catch (Exception exc)
                            {
                                // Brief sleep to avoid problem with tight loop
                                Thread.Sleep(100);
                            }

                        }
                        sentence = "";
                    }
                }
                else
                {
                    // Brief sleep to avoid problem with tight loop
                    Thread.Sleep(100);
                }
            }
        }
    }
}


Saturday, June 15, 2013

Adafruit Ultimate GPS Breakout & the Arduino Due

I've been fiddling around the last few days with various GPS modules, including the Adafruit Ultimate GPS Breakout (v. 3). The notes below cover the use of this GPS module with the Arduino Due. This example parses the $GPRMC NMEA sentence and pulls out the N latitude and W longitude. The output is formatted as degrees, minutes, and seconds.  To keep the example simple, the output just goes to the serial console.

I haven't gone mobile with the application yet.  To help with GPS reception at my desk, I am using this external cable antenna and antenna adapter.


Connections


GPS Breakout  Arduino Due
TX            D19 (RX1)
RX            D18 (TX1)
GND           GND
VIN           3.3V 

The Arduino Due's Serial2 (pins RX2, TX2) or Serial3 (pins RX3, RX3) could also be used.

Code


#include <string.h>

// variable for NMEA sentence 
String sentence = "";

void setup() {
  // For output to serial monitor
  Serial.begin(9600);
  // Connection to GPS
  Serial1.begin(9600);
}

void loop() {
  if (Serial1.available() > 0) {
    char c = Serial1.read();
    // Check if end of NMEA sentence
    if(c == '\n') {
      // Check if $GPRMC NMEA sentence
      if(sentence.startsWith("$GPRMC")) {
        char data[150];
        char *dataPtr = data;
        char *value; 
        sentence.toCharArray(data, sentence.length());
        int i = 0;
        // Tokenize each line into values using comma delimiter.
        // Returns NULL when no more tokens.
        // strtok_r is part of C standard library.
        while ((value = strtok_r(dataPtr, ",", &dataPtr)) != NULL) { 
          // 4th value is north latitude, 6th is west longitude
          if(i == 3 || i == 5) {
            int degMin = atoi(value);
            int degree = (int) degMin / 100;
            int minutes = degMin - (degree * 100);
            float seconds = (float) (atof(value) - (float) degMin) * 60.0;
            String label;
            if(i == 3)
              label = " N";
            else
              label = " W";  
            char secBuffer[6];
            dtostrf(seconds, 6, 3, secBuffer);
            char location[100];
            sprintf(location, "%02d\xB0 %02d' %s\"", degree, minutes, secBuffer);
            Serial.println(location + label);
          } 
          i++;
        }
        Serial.println();
      }
      sentence = "";
    }
    else {
      // Append character if not end of sentence
      sentence += c;
    }
  }
}

// Arduino IDE libraries do not include dtostrf() 
char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
  char fmt[20];
  sprintf(fmt, "%%%d.%df", width, prec);
  sprintf(sout, fmt, val);
  return sout;
}