Skip to main content

Quick Start

This guide introduces the FoBE Breakout L76K and how to use it.

Hardware diagram

The following figure illustrates the FoBE Breakout L76K hardware diagram.


FoBE Breakout L76K Hardware Diagram

Mechanical dimensions

FoBE Breakout L76K is a single-sided 25.4mm x 25.4mm (1" x 1") 1.6mm thick PCB with a SH1.0 6-pin connector and a set of 6-pin 2.54mm header holes. Fixing by 4 x 1.6mm Screw holes.


FoBE Breakout L76K Mechanical Dimensions

Interfaces

The module provides a 6-Pin JST SH1.0 connector and corresponding 2.54mm header holes.

2.54mm 6-PinJST-SH1.0Features
3V33V3Power supply, Only 3.3V
GNDGNDGround
TXTXUART data output
RXRXUART command input
RSTRSTReset IC, Active Low
WAKEWAKEStandby mode control, Active Low

Advanced

Jumper

The module features two jumper pads:

InterfaceDescription
CONSTELLATIONSatellite constellation selector:
Soldered: GPS + GLONASS
Open: BeiDou + GPS (Default)
LED-JUMPERDisconnect this jumper to turn off the PPS LED for further power saving

Additional Features

  • Built-in Battery: 3.1V rechargeable button cell for data retention
  • Active Antenna Support: Connect "ACTIVE-ANT PWR" pad to 3V3 when using active antenna
  • PPS Output: Pulse-per-second signal output, independent of LED jumper control

Programming

Running with FoBE Quill ESP32S3 Mesh

Let's get started with the FoBE Quill ESP32S3 Mesh using the MFP interface.

  1. Connect the FoBE Breakout L76K to the FoBE Quill ESP32S3 Mesh using the MFP interface.

FoBE Breakout L76K Connection

  1. Create a sketch or PlatformIO project, or follow the FoBE Quill ESP32S3 Programming Guide for pre-configuration.

  2. Install the necessary library in your project:

mikalhart/TinyGPSPlus@^1.1.0
  1. Copy the following code into your sketch or PlatformIO project:
#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>

#define GNSS_BAUD 9600 // GNSS module baud rate
#define GNSS_RX_PIN PIN_MFP1 // RX pin for GNSS communication, change if needed
#define GNSS_TX_PIN PIN_MFP2 // TX pin for GNSS communication, change if needed
#define GNSS_RST_PIN PIN_MFP3 // Reset pin for GNSS, change if needed
#define GNSS_WAKE_PIN PIN_MFP4 // Wake pin for GNSS, change if needed
#define PERI_EN_PIN PIN_PERI_EN // Peripheral enable pin, change if needed

TinyGPSPlus gnss;

// Buffer to store the latest NMEA sentence
String latestNmeaSentence = "";
char nmeaBuffer[128];
int bufferIndex = 0;

// Time tracking variables
unsigned long startupTime = 0;
unsigned long firstFixTime = 0;
bool firstFixAchieved = false;

void setup()
{
// Initialize serial communication
Serial.begin(115200);
Serial.println("Serial initialized");

// Initialize peripheral power
if (PERI_EN_PIN >= 0)
{
pinMode(PERI_EN_PIN, OUTPUT);
digitalWrite(PERI_EN_PIN, HIGH); // Enable peripheral power
Serial.println("Peripheral power enabled");
}

// Initialize GNSS module (optional, if you want to test searching time cost)
pinMode(GNSS_RST_PIN, OUTPUT);
pinMode(GNSS_WAKE_PIN, OUTPUT);
digitalWrite(GNSS_RST_PIN, LOW); // Reset the GNSS module
delay(100);
digitalWrite(GNSS_RST_PIN, HIGH); // Release reset
digitalWrite(GNSS_WAKE_PIN, HIGH); // Wake the GNSS module

Serial1.begin(GNSS_BAUD, SERIAL_8N1, GNSS_RX_PIN, GNSS_TX_PIN);
Serial.println("GNSS bus initialized");

// Wait a moment for module to fully initialize
delay(200);

// Record startup time
startupTime = millis();
Serial.printf("Startup time recorded: %lu ms\n", startupTime);

// Wait for GNSS to be ready (equivalent to sensor init loop)
Serial.println("Waiting for GNSS data...");
unsigned long startTime = millis();
while (millis() - startTime < 10000) // Wait up to 10 seconds
{
while (Serial1.available() > 0)
{
gnss.encode(Serial1.read());
}
if (gnss.location.isValid() || gnss.time.isValid() || gnss.satellites.value() > 0)
{
break;
}
delay(200);
}

// Configure GNSS settings, calculate checksum reference https://www.hhhh.org/wiml/proj/nmeaxor.html
Serial1.write("$PCAS04,7*1E\r\n"); // Configure satellite constellation
delay(250);
Serial1.write("$PCAS11,3*1E\r\n"); // Configure positioning mode
delay(250);
Serial1.write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n"); // Configure positioning frequency
delay(250);
Serial1.write("$PCAS02,200*1D\r\n"); // Configure positioning frequency
delay(250);

Serial.println("GNSS sensor initialized");

// Start measurement (GNSS automatically starts after initialization)
}

void loop()
{
delay(50); // Wait equivalent to gnss.wait()

// Read data from GNSS (equivalent to gnss.update())
bool dataUpdated = false;
while (Serial1.available() > 0)
{
char c = Serial1.read();

// Build NMEA sentence buffer
if (c == '$')
{
bufferIndex = 0;
nmeaBuffer[bufferIndex++] = c;
}
else if (bufferIndex > 0 && bufferIndex < 127)
{
nmeaBuffer[bufferIndex++] = c;
if (c == '\n')
{
nmeaBuffer[bufferIndex] = '\0';
latestNmeaSentence = String(nmeaBuffer);
}
}

if (gnss.encode(c))
{
dataUpdated = true;
}
}

if (dataUpdated) // Equivalent to gnss.update() == RESULT_OK
{
if (gnss.location.isValid() || gnss.time.isValid()) // Equivalent to gnss.hasNewData()
{
// Check for first fix achievement
if (!firstFixAchieved && gnss.location.isValid())
{
firstFixTime = millis();
firstFixAchieved = true;
}

// Display data on screen
Serial.print("\033[H\033[J");
Serial.println("> FoBE Breakout L76K Monitor");
Serial.println();
Serial.print("\033[7m");
Serial.printf("%-12s%-12s%-12s\n", "INDEX", "VALUE", "UNIT");
Serial.print("\033[0m");

if (gnss.location.isValid())
{
Serial.printf("%-12s%-12.6f%-12s\n", "LATITUDE", gnss.location.lat(), "°");
Serial.printf("%-12s%-12.6f%-12s\n", "LONGITUDE", gnss.location.lng(), "°");
}

if (gnss.altitude.isValid())
{
Serial.printf("%-12s%-12.2f%-12s\n", "ALTITUDE", gnss.altitude.meters(), "m");
}

if (gnss.speed.isValid())
{
Serial.printf("%-12s%-12.2f%-12s\n", "SPEED", gnss.speed.kmph(), "km/h");
}

if (gnss.satellites.isValid())
{
Serial.printf("%-12s%-12d%-12s\n", "SATELLITES", gnss.satellites.value(), "");
}

if (gnss.hdop.isValid())
{
Serial.printf("%-12s%-12.2f%-12s\n", "HDOP", gnss.hdop.hdop(), "");
}

// Add GPS time display
if (gnss.time.isValid() && gnss.date.isValid())
{
Serial.printf("%-12s%02d:%02d:%02d%-12s\n", "TIME", gnss.time.hour(), gnss.time.minute(), gnss.time.second(), "UTC");
Serial.printf("%-12s%04d-%02d-%02d%-12s\n", "DATE", gnss.date.year(), gnss.date.month(), gnss.date.day(), "");
}

// Add Time to First Fix Information
if (firstFixAchieved)
{
unsigned long timeToFirstFix = firstFixTime - startupTime;
Serial.printf("%-12s%-12.3f%-12s\n", "TTFF", timeToFirstFix / 1000.0, "SEC");
}
else
{
unsigned long currentTime = millis();
unsigned long timeElapsed = currentTime - startupTime;
Serial.printf("%-12s%-12.3f%-12s\n", "SEARCHING", timeElapsed / 1000.0, "SEC");
}

// Print latest NMEA data stream below the table
Serial.println();
Serial.println("Latest NMEA Data Stream:");
if (latestNmeaSentence.length() > 0)
{
Serial.print(latestNmeaSentence);
}
else
{
Serial.println("No NMEA data received yet");
}
}
}
}
important

This example code uses ANSI output formatting. Your terminal must support ANSI escape codes to display the output correctly.

# platformio.ini
[env:fobe_quill_esp32s3_mesh]
platform = FoBE Espressif 32
board = fobe_quill_esp32s3_mesh
framework = arduino
lib_deps =
mikalhart/TinyGPSPlus@^1.1.0
monitor_speed = 115200
monitor_raw = true
  1. Build and upload the project. You should see the FoBE Breakout L76K Monitor output in the serial monitor (raw mode).
> FoBE Breakout L76K Monitor

INDEX VALUE UNIT
LATITUDE 22.123456 °
LONGITUDE 114.123456 °
ALTITUDE 71.20 m
SPEED 17.33 km/h
SATELLITES 15
HDOP 24.80
TIME 19:59:03UTC
DATE 2025-08-08
TTFF 3.236 SEC

Latest NMEA Data Stream:
$GNGSA,A,1,,,,,,,,,,,,,25.5,24.8,25.5,1*0D