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:
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.