Introduction: Building a GPS/GNSS Receiver Using MosaicHAT and Arduino

Throughout the following steps, we'll see how to build a GPS/GNSS receiver using Arduino and mosaicHAT. mosaicHAT is a Raspberry Pi compatible GNSS board based on Septentrio module, mosaic-X5, the centimeter-level multi-band, multi-constellation GPS/GNSS receiver.

The compact mosaicHAT make it incredibly handy to provide IoT and robotics applications with highly accurate and precise positioning. mosaicHAT ­­project is open-source, fully documented on Github and can be easily manufactured or integrated into different designs:

https://github.com/septentrio-gnss/mosaicHAT

Step 1: Components

To build this project, we need the following components:

  • Arduino UNO (or any Arduino type actually)
  • mosaicHAT
  • GNSS antenna
  • 16*2 LCD screen (12C)
  • Breadboard
  • 2* 9V batteries
  • 2* battery connector
  • Pushbutton
  • Wires

Step 2: Schematic

Arduino:

  • Arduino VIN > Batteries +9V
  • Arduino GND > Batteries GND

mosaicHAT:

  • mosaicHAT TX > Arduino D10
  • mosaicHAT RX > Arduino D11
  • mosaicHAT +5V > Batteries +9V
  • mosaicHAT GND > GND

LCD display:

  • Screen SDA > Arduino A4
  • Screen SCL > Arduino A5
  • Screen VCC > Arduino +5V
  • Screen GND > GND

Pushbutton:

  • Pushbutton pin > Arduino D2
  • Pushbutton pin > GND

The schematic was designed using the open-source software Fritzing. You can download mosaicHAT's Fritzing part from here.

Step 3: Connections

  • I've used one +9V battery and later added another one in parallel to supply a higher current (We'll need to power the antenna as well!). Actually, using other power sources such as lithium batteries could be a smarter idea.
  • Screen brightness could be optimized using the variable resistor on its back.
  • Pushbutton connection is active LOW.

Step 4: Mosaic-X5 Configuration

We need mosaicHAT to output an NMEA stream through COM2 every time it boots up (in mosaicHAT, COM1 is connected to Raspberry Pi UART pins while COM2 is exposed for different FTDI connections). Arduino will read the messages and output readings on the LCD display.

Configuring mosaicHAT could be easily done using Septentrio web interface of mosaic-X5. Connect mosaicHAT to your PC through USB and open the webUI on its default address "192.168.3.1". Next:

  • Go to the Communication tab and choose Serial.
  • Change the baud rate of COM2 to 9600.
  • Click Ok for changes to take effect.
  • Go to NMEA/SBF Out and choose New NMEA Stream.
  • Select Serial connection type then COM2 as connection/port.
  • Keep the default interval (1 sec) and select GGA as a message to output.
  • Click Ok for changes to take effect.
  • Now a popup message will ask if you would like to save the current configuration as a boot configuration. Choose Save.

Congratulations! mosaicHAT is ready. Time to play with Arduino.

Step 5: Arduino Code

The following is the ArduinoC code of the receiver, alongside comments. Mainly, the code does the following:

  • Sets up the I2C LCD display and software serial for the mosaicHAT (as we don't want to use the USB serial of Arduino, keeping it for computer communication)
  • Reads the NMEA GGA messages coming from mosaicHAT and parses them into the readings of our interest.
  • Shows the readings on the display pages and navigate on pushbutton clicks, as following:
    1- Quality and SVs number
    2- Latitude and Longitude
    3- Height and Geoidal Separation

The code is also uploaded to this github repo.

#include <SoftwareSerial.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

SoftwareSerial mosaicSerial = SoftwareSerial(10, 11);; // RX, TX of software serial (mosaicHAT connection)
LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup() {
  pinMode(10,INPUT); //RX of software serial, input mode
  pinMode(11,OUTPUT); //TX of software serial, output mode
  mosaicSerial.begin(9600);// Software Serial connects to mosaicHAT
  Serial.begin(9600);  // default Serial connects to a computer via USB
  pinMode(2, INPUT_PULLUP);
  lcd.begin();
   lcd.backlight();
  lcd.setCursor(1,0);
  lcd.print("  mosaicHAT");
  lcd.setCursor(1,1);
  lcd.print("  &Arduino");
  delay(1000); // wait a second to show the intro 
} 

String nmea_string,sreadString;
String Latitude,Longitude,Latitude_direction,Longitude_direction,Quality_indicator,SVs_Number,Height,Geoid_separation,Quality_indicator_string; //nmea message elements
String quality_string_array [6]={"No Fix","GNSS fix","DGPS","","RTK","RTK Float"}; //string meanings of quality indicator values
bool nmea_flag=false,button_flag=false,push_button=true;
int separator_indices[14];
int page=0,disp_counter=0;

void loop() {

  push_button = digitalRead(2);
  push_button=!push_button; //convert from active LOW to active HIGH (true = clicked)

  // 
  if(push_button == true &&button_flag==false){
      page++;
      if(page>=3)page=0;
      button_flag=true;
  }else if(push_button==false){
      button_flag=false;
  }

  while (mosaicSerial.available()) {
    char c;
    delay(2) ; //delay to allow buffer to fill
    if (mosaicSerial.available() >0) {
         c = mosaicSerial.read();  //gets one byte from serial buffer
        sreadString += c; //makes the string sreadString  
    } 
  } 
  if(sreadString!="" ){
    Serial.println(sreadString);
    nmea_flag=true;
    nmea_string=sreadString;
  }
  sreadString="";
  
  if(nmea_flag){
    int c=0;
    for(int i=0;i<nmea_string.length();i++){
      if(nmea_string[i]==','){
        separator_indices[c]=i;
        c++;
      }
    }

    //parse nmea message into its important elements
    Quality_indicator= nmea_string.substring(separator_indices[5]+1,separator_indices[6]);
    SVs_Number= nmea_string.substring(separator_indices[6]+1,separator_indices[7]);
    Height=nmea_string.substring(separator_indices[8]+1,separator_indices[9]);
    Geoid_separation=nmea_string.substring(separator_indices[10]+1,separator_indices[11]);
    Latitude= nmea_string.substring(separator_indices[1]+1,separator_indices[2]);
    Longitude=nmea_string.substring(separator_indices[3]+1,separator_indices[4]);
    Latitude_direction= nmea_string.substring(separator_indices[2]+1,separator_indices[3]);
    Longitude_direction=nmea_string.substring(separator_indices[4]+1,separator_indices[5]);

    nmea_flag=false;
  }

  disp_counter++; 
  
  if(disp_counter>=10000){ // reducing update rate to avoid screen flickering
        lcd.clear();
    if(page==0){ // first page: Quality and SVs umber
      lcd.setCursor(1,0);
      Quality_indicator_string = quality_string_array[Quality_indicator.toInt()];
      lcd.print("Q: "+Quality_indicator_string);
      lcd.setCursor(1,1);
      lcd.print("SVs: "+SVs_Number);
    }else if(page==1){ // second page: Latitude and Longitude
      lcd.setCursor(0,0);
      lcd.print(Latitude+Latitude_direction);
      lcd.setCursor(0,1);
      lcd.print(Longitude+Longitude_direction);
    }else if(page==2){ // third page: Height and Geoidal Separation
      lcd.setCursor(1,0);
      lcd.print("H: "+Height+"m");
      lcd.setCursor(1,1);
      lcd.print("S: "+Geoid_separation+"m");
    }
     
    disp_counter=0;
  } 
} 

Step 6: Make Housing

Housings could be built with different methods, shapes and materials. I've used a laser cutter to make the acrylic box for the receiver. A laser cutter could be also used to make a wooden box. Find the laser cutter file from here.

Step 7: Start Playing!

All you need now is to connect a GNSS antenna and test the receiver. Take the receiver box to the roof of your building or an open area and test it with the greatest number of possible GNSS satellites. You could also try it in more challenging environments.

Step 8: Further

mosaicHAT

mosaicHAT is an open-source GPS/GNSS PCB that integrates Septentrio's mosaic-X5 GNSS module (and other Septentrio pin-compatible modules such as Septentrio's mosaic-Sx) with basic communications and which can be stacked into a Raspberry Pi system.

The goal of the design is to allow easy hardware prototyping using the mosaic-X5 GNSS module taking advantage of Raspberry Pi capabilities. The board could be also used standalone using USB.

Getting mosaicHAT

mosaicHAT can now be purchased from Ardusimple directly. Ardusimple is a company which produces easy to use GNSS RTK systems. Check Ardusimple mosaicHAT.

mosaic-X5

Septentrio's mosaic-X5, a multi-band, multi-constellation GNSS receiver in a low-power surface mount module with a wide array of interfaces, designed for mass-market applications like robotics and autonomous systems, capable of tracking all Global Navigation Satellite System (GNSS) constellations supporting current and future signals. With unique built-in AIM+ technology for interference mitigation, Septentrio is offering a performance benchmark in mass-market GNSS positioning building blocks.