Projects
Advanced Sensors
GPS

Overview

This project reads values from a GPS sensor and displays the readings on a 20x4 LCD screen with an I2C backpack. This sketch measures and prints the following parameters:-

  • Latitude
  • Longitude
  • Speed
  • Altitude (not in microPython )

Components

ComponentPurpose
Arduino NanoThis will be the microcontroller
NEO6/7M/8M GPSThis will be the GPS sensor
I2C LCD 20X4This will be the LCD display

Circuit Diagram

nano_gps_lcd_fritzing

Connections

NEO 6M/7M/8M GPS

Nano PinNEO XM GPS Pin
D5/RX2TX
D6/TX2RX
5VVCC
GndGnd

I2C LCD Pin

Nano PinI2C LCD Pin
A4SDA
A5SCL
5VVCC
GNDGND

Code

/*
  Project: GPS Sensor value reading with output on LCD with I2C Backpack
  Project Description:
  This sketch writes readings read from a GPS sensor to an LCD display module.
  This sketch is for a 20x4 screen.
 
  Author: STEMVentor Educonsulting
  
  This code is copyrighted. Please do not reuse or share for any purpose other than for learning with subscribed STEMVentor programs.
  This code is for educational purposes only and is not for production use.
*/
 
// LIBRARIES
 
//used for communicating with I2C devices
#include <Wire.h> 
// for reading gps values
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
//https://www.arduino.cc/reference/en/libraries/liquidcrystal-i2c/
// Install the LiquidCrystal I2C by Frank de Brabander from the IDE library manager. 
#include <LiquidCrystal_I2C.h>
 
 
// PIN DEFINITIONS
// define the pin to which the GPS sensor is connected
// for Arduino Nano  , comment if using ESP32
#define gpsTx 5  // GPS module TX pin connected to Arduino nano GPIO D5
#define gpsRx 6  // GPS module RX pin connected to Arduino nano GPIO D6
 
//uncomment if using ESP32 
// #define gpsTx 16  // GPS module TX pin connected to ESP32 GPIO 16
// #define gpsRx 17  // GPS module RX pin connected to ESP32 GPIO 17
 
 
// GLOBAL VARIABLES
//GPS module baud rate , usually 9600
static const uint32_t GPSBaud = 9600;
// Define the display size
const byte rows = 4;
const byte cols = 20;
 
// used for reading sensor value
float  latitudeValue ;
float  longitudeValue ;
float  speedValue ;
float  altitudeValue  ;
 
 
 
/* INITIALIZE OBJECTS
 * Libraries usually follow an object-oriented approach that requires
 * an instance of the class to call its methods.
 */
/* 
 * All I2C components have an address, the default is usually 0x27
 * If that doesn't work, see this:https://playground.arduino.cc/Main/I2cScanner/
 * The init statement accepts the address and the number of columns and rows.
 */
LiquidCrystal_I2C lcd(0x27, cols, rows);
SoftwareSerial ss(gpsTx, gpsRx); // Configure SoftwareSerial with your actual GPS module pin connections
TinyGPSPlus gps;
 
 
/* LOCAL FUNCTIONS */
 
// Read sensor value
void readGPS() //read values from NEO6M/7M/8M GPS sensor
{
  delay(1000);
  while (ss.available() > 0) { //check if GPS is sending data on the serial connection
    if (gps.encode(ss.read())) { //read the incoming data
      if (gps.location.isValid()) //if the incoming data is valid and error free
      { 
        latitudeValue = gps.location.lat(); //read latitude value till 6 decimal places
        longitudeValue = gps.location.lng(); //read longitude value till 6 decimal places
 
        if (gps.speed.isValid())
        {
          delay(200);
          speedValue = gps.speed.kmph();//read speed in kmph
        }
 
        if (gps.altitude.isValid())
        {
          delay(200);
          altitudeValue = gps.altitude.meters(); //read height
        }
 
      }
    }
  }
}
 
/*
  Function to print to LCD on a single row.
  Takes the row number and the text to display on that row (max 20 chars, rest will be truncated).
  The entire display is cleared if the clear_all flag is true, else only the row is cleared (the default).
 */
void printToLCDByRow(int row, String text, bool clear_all = false)
{
  const char* twenty_spaces = "                    ";
 
  if(clear_all){ 
    lcd.clear(); //clears the entire display
  } 
 
  lcd.setCursor(0, row-1);
  lcd.print(twenty_spaces); //clears the row
  lcd.setCursor(0, row-1); //cursor has to be set again after printing spaces
  lcd.print(text);
}
 
/*
 Function to print to LCD across rows with each row having 20 chars.
 Messages can be a maximum of 20x4 chars, rest will betruncated.
 The entire display is cleared before printing the text.
 Test string of 20 char:
 12345678901234567890
 Test strings of 80 chars: 
 12345678901234567890123456789012345678901234567890123456789012345678901234567890
 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec varius est donec.
 
 */
void printToLCD(String text)
{
  lcd.clear(); //clears the entire display
 
  byte chars_remaining = text.length();
  byte char_from = 0;
  byte char_to = chars_remaining < cols ? text.length() : char_from + cols;
  byte row = 1;
 
  while(chars_remaining > 0){
    String line = text.substring(char_from, char_to);
    printToLCDByRow(row, line);
 
    chars_remaining = text.length() - char_to;
    char_from = char_to;
    char_to = chars_remaining < cols ? text.length() : char_from + cols;
    row++;
  }
 
  Serial.println("Data string has been displayed on LCD");
}
 
void lcdSetup() // function to LCD setup
{
  // Initializing wire
  Wire.begin();
  // Initialize the LCD.
  lcd.init();
  // Turn on the blacklight and print a message.
  lcd.backlight();
  // Use the function to display text on each line indiviudally.
  printToLCDByRow(1, "I2C LCD Ready!", true);
  printToLCDByRow(2, "Enter some text.", false);
  printToLCDByRow(3, "Max 80 characters.", false);
  printToLCDByRow(4, "For a 20x4 LCD.", false);
}
 
void gpsSetup()
{
  ss.begin(GPSBaud); //setup GPS communication channel
}
 
/* SETUP CODE: runs once when the board starts up or resets */ 
//The Main Setup function which sets up all the modules
void setup() 
{
    // Start the serial communication with baud rate suitable for your components.
    Serial.begin(9600); 
    lcdSetup();
    gpsSetup();
    Serial.println("The board is ready !");
}
 
/* MAIN LOOP: runs repeatedly at a very high frequency (1000s of times a second) */
void loop() 
{
  delay(1000);
  readGPS();
  printToLCDByRow(1, "Latitude" + String(latitudeValue), true);
  printToLCDByRow(2, "Longitude" + String(longitudeValue), false);
  printToLCDByRow(3, "Speed" + String(speedValue), false);
  printToLCDByRow(4, "Altitude" + String(altitudeValue),  false);
}