Interfacing Quectel L86 GPS+GLONASS GNSS Module with Arduino

We are back with another GNSS module and this time, it’s the L86 from Quectel. If you’ve never heard of them, Quectel is a Chinese company that makes GNSS and telecommunication modules and they are very popular among product designers. In this tutorial, we will take a closer look at the L86 GNSS module that combines both GPS and GLONASS constellations for positioning. The compact module comes with a ceramic patch antenna and also supports external antenna. You will find here the pinouts and code connecting this module with your Arduino boards.
If you are completely new to GPS/GNSS modules, you can check out our NEO-6M GPS tutorial. Even though written for another GPS module, it explains everything basic you need to know to start using GPS or other GNSS modules in your projects.
What is GPS/GNSS & How to Interface u-blox NEO-6M GPS Module with Arduino
Quectel L86

The Quectel L86 (aka L86-M33) is a compact multi-GNSS module based on the MediaTek MT3333 GNSS chipset. It integrates a ceramic Patch-on-Top (POT) antenna on the module and can receive positioning signals from GPS, GLONASS, Galileo and QZSS constellations. It has a -149 dBm acquisition sensitivity and a -167 dBm tracking sensitivity. 99 acquisition channels and 33 tracking channels allow the module to acquire the position lock faster and continue tracking even in challenging situations like indoors. The EASY™ (Embedded Assist System) is a proprietary technology that allows the L86 to store the ephemeris data of up to 3 days in the RAM and use it to calculate and predict the satellite positions faster. With AlwaysLocate™ technology, L86 can adaptively adjust the on/off time to achieve balance between positioning accuracy and power consumption according to the environmental and motion conditions. The L86 is size and pin compatible with the older L80 GPS-only module. Now let’s take a look at the features and specifications as advertised by the manufacturer.
Features
- Multi-GNSS engine for GPS, GLONASS, Galileo and QZSS.
- Embedded patch antenna: 18.4 × 18.4 × 4.0 mm.
- Extremely compact footprint: 16.0 × 16.0 × 6.45 mm.
- Automatic antenna switching function.
- Support short circuit protection and antenna detection.
- Built-in LNA for better sensitivity.
- EASY™, an advanced AGPS technology without external memory.
- Ultra low power consumption in tracking mode, 26 mA.
- AlwaysLocate™, an intelligent controller of periodic mode.
- LOCUS, an embedded logger function without the need of host and external flash.
- High sensitivity: -167 dBm @ Tracking, -149 dBm @ Acquisition.
- 99 acquisition channels, 33 tracking channels.
- Balloon mode, for high altitude up to 80 Km.
- Support DGPS, SBAS (WAAS/EGNOS/MSAS/GAGAN).
- Great anti-jamming performance due to multi-tone active interference canceller.
- PPS VS. NMEA can be used for time service.
- Support SDK command developed by Quectel.
Specifications
- Chipset: MediaTek MT3333
- Constellations: GPS, GLONASS, Galileo, and QZSS
- Frequency: GPS L1 (1575.42MHz), GLONASS L1 (1601.71MHz)
- SBAS: WAAS, EGNOS, MSAS, GAGAN
- Acquisition Channels: 99
- Tracking Channels: 33
- Sensitivity:
- Acquisition: -149 dBm
- Tracking: -167 dBm
- Reacquisition: -161 dBm
- Accuracy
- Horizontal Position Accuracy: < 2.5 m CEP autonomous
- Velocity Accuracy: <0.1 m/s without aid
- Acceleration Accuracy: <0.1 m/s2
- Timing Accuracy: 10 ns at 1 PPS out
- Acquisition Time
- Reacquisition Time: < 1 s
- TTFF @ -130 dBm with EASY™:
- Cold Start: < 15 s
- Warm Start: < 5 s
- Hot Start: < 1 s
- TTFF @ -130 dBm without EASY™:
- Cold Start: < 35 s
- Warm Start: < 30 s
- Hot Start: < 1 s
- Data and Update Rate
- Support Rate: UART 4800~115200 bps, Default 9600 bps
- IO Voltage: 2.7V~2.9V
- Data Protocol: NMEA 0183, PMTK
- Output frequency: 1~10 Hz, Default 1 Hz
- Operational Limits
- Altitude: 18,000 m Max
- Velocity: 515 m/s Max
- Acceleration: Less than 4 G
- Power Consumption
- Supply Voltage: 3~4.3V
- Acquisition: 30 mA @ 3.3V (GPS + GLONASS)
- Tracking: 26 mA @ 3.3V (GPS + GLONASS)
- Temperature Range: -40 °C ~ +85°C
- Dimensions: 18.4 x 18.4 x 6.45 mm
- Weight: 7.6 g
Block Diagram


Pinout
The L86 is available as an LCC (Leaded Chip Carrier) package with 12 pins. In addition to the POT antenna, the L86 can also switch the antennas to either the POT or an external antenna. The pinout diagram is given below.

Pin # | Pin Name | Description |
---|---|---|
1 | RXD1 | Data receive |
2 | TXD1 | Data transmit |
3 | GND | Supply ground |
4 | VCC | Positive supply |
5 | V_BCKP | Backup power supply for the RTC. Can connect to VCC or a battery. |
6 | 1PPS | One pulse per second output |
7 | FORCE_ON | Module wake up pin |
8 | AADET_N | Active antenna detection |
9 | NC | Not connected |
10 | RESET | System reset. Active low. |
11 | EX_ANT | External active antenna input |
12 | GND | Supply ground |
Dimensions

7Semi L86-M33 EVE-GNSS


The L86-M33 EVE-GNSS is a breakout module for the L86, from 7Semi, which is a brand of the popular Indian ecommerce website Evelta based in Mumbai. The L86-M33 makes it easy to interface the L86 module with any microcontroller of your choice. The L86-M33 is available for INR 925 while the L86 module is available for INR 670 from Evelta at the time of writing.
Features
- 3.3V power supply.
- CR1220 coin cell holder for RTC backup.
- U.FL connector for external antenna.
- Indicator LEDs
- Power – Green
- Position – Blue
- Antenna – Red
- 40 x 28 mm dimensions

Schematic
Evelta has not released the schematic of the EVE-GNSS module, but it should be based on the design guidelines from Quectel as shown below.
Pinout

The above image shows the pins available on the EVE-GNSS board. Following is the pin names and their description.
Pin Name | Description |
---|---|
RX | Data receive |
TX | Data transmit |
GND | Supply ground |
3.3V | Positive supply |
V_BACK | Backup power supply for the RTC. It is connected to the RTC battery. |
F_ON | Module wake up pin |
RESET | System reset. Active low. |
There are three LEDs on the board. ANT LED (Red) is connected to the AADET_N
pin of the L86. When the external antenna is connected and selected, the ANT LED will turn off. With the internal POT antenna, the LED will remain on. The GPS LED (Blue) is connected to the 1PPS
of the L86 and indicates the position lock status. PWR (Green) indicates the power supply input.
Wiring
We are going to use a FireBeetle-ESP32-E board for interfacing the L86 module and read data from it. The FireBeetle-ESP32-E is a versatile development board from DFRobot, and comes with a USB-C connector instead of the old USB-Micro. You can use any other Arduino boards as well for running the example code provided.

We just need to connect the 3.3V power to the L86 module and connect the RX and TX pins to any of the UART pins of the ESP32 board. Note that the L86 EVE-GNSS module does not have any voltage regulators onboard and therefore can not accept any voltages higher than 3.3V. For example, supplying 5V will likely damage the module. Following table shows the wiring we used.
GNSS Board | ESP32 | FireBeetle-ESP32E |
---|---|---|
3.3V | 3.3V | 3.3V |
GND | GND | GND |
RX | GPIO16 | D11 |
TX | GPIO17 | D10 |
If this is the first time you are using an ESP32 board, we have a great tutorial for beginners.
Getting Started with Espressif ESP32 Wi-Fi & Bluetooth SoC using DOIT-ESP32-DevKit-V1 Development Board
CSE_GNSS Library
The CSE_GNSS is an open-source Arduino library from CIRCUITSTATE Electronics, and can be used to read any GPS/GNSS module with the standard NMEA output and decode the messages. You can define custom NMEA data sentences and extract the positional parameters effortlessly. There are two examples available in the library as of now.
- View_GNSS_Data.ino – Reads the raw data from the GNSS module and prints it to the serial monitor. This sketch is useful for verifying the wiring and the output of the GNSS module you have.
- Print_GPRMC.ino – As the name suggests, this reads the $GPRMC sentence from the GNSS module, extract the data and print them to the serial monitor.
We will modify these Arduino examples slightly for our Quectel L86 GNSS module.
Arduino Code
The following is an Arduino code for reading raw NMEA data and printing them to the serial monitor. It is the View_GNSS_Data.ino example modified for ESP32.
//======================================================================================//
/**
* @file View_GNSS_Data.ino
* @brief Reads raw data from the GNSS module and prints it on the serial monitor.
* @date +05:30 12:37:39 AM 03-08-2024, Saturday
* @version 1.0.1
* @author Vishnu Mohanan (@vishnumaiea)
* @par GitHub Repository: https://github.com/CIRCUITSTATE/CSE_GNSS
* @par MIT License
*
*/
//======================================================================================//
#include <Arduino.h>
#include <CSE_GNSS.h>
//======================================================================================//
#define PORT_GPS_SERIAL Serial1 // GPS serial port
#define PORT_DEBUG_SERIAL Serial // Debug serial port
// For ESP32
#define PIN_GPS_SERIAL_TX 16
#define PIN_GPS_SERIAL_RX 17
#define VAL_GPS_BAUDRATE 9600
#define VAL_DEBUG_BAUDRATE 115200
//======================================================================================//
// Forward declarations
void setup();
void loop();
//======================================================================================//
// Set the serial ports and the baudrate for the GNSS module.
// Both ports have to be manually initialized through begin() call.
CSE_GNSS GNSS_Module (&PORT_GPS_SERIAL, &PORT_DEBUG_SERIAL);
//======================================================================================//
/**
* @brief Setup the serial ports and pins.
*
*/
void setup() {
PORT_DEBUG_SERIAL.begin (VAL_DEBUG_BAUDRATE);
// For ESP32 boards
PORT_GPS_SERIAL.begin (VAL_GPS_BAUDRATE, SERIAL_8N1, PIN_GPS_SERIAL_RX, PIN_GPS_SERIAL_TX);
GNSS_Module.begin(); // Initialize the GNSS module.
PORT_DEBUG_SERIAL.println();
PORT_DEBUG_SERIAL.println ("--- CSE_GNSS [View_GNSS_Data] ---");
delay (1000);
}
//======================================================================================//
/**
* @brief Runs indefinitely.
*
*/
void loop() {
GNSS_Module.read (1024); // Read multiple NMEA data lines from the GNSS module
// Print the data
for (int i = 0; i < GNSS_Module.gnssDataBufferLength; i++) {
PORT_DEBUG_SERIAL.print (GNSS_Module.gnssDataBuffer [i]);
}
PORT_DEBUG_SERIAL.println();
delay (500);
}
//======================================================================================//
C++Since the ESP32 has multiple hardware serial ports, we are using Serial1
to talk to the GNSS module. The default Serial
port will be used for debugging messages. In the loop()
function, we will just read 1024 bytes and print them to the serial monitor. Now compile and upload the code to your ESP32 board. After opening the serial monitor, you will start to see NMEA data coming from the GNSS module.
$GPRMC,111023.623,V,,,,,0.00,0.00,020723,,,N,V*34
$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32
$GPGGA,111023.623,,,,,0,0,,,M,,M,,*4F
$GPGSA,A,1,,,,,,,,,,,,,,,,1*03
$GPGSA,A,1,,,,,,,,,,,,,,,,2*00
$GPGSV,4,1,14,18,61,085,,32,60,279,,28,31,187,,23,29,026,,0*65
$GPGSV,4,2,14,10,29,343,,27,28,295,,195,26,129,,24,18,052,,0*52
$GPGSV,4,3,14,29,14,162,,25,08,139,,26,05,221,,31,04,205,,0*69
$GPGSV,4,4,14,08,01,314,,194,01,106,,0*55
$GLGSV,2,1,08,83,57,148,,84,53,342,,69,29,353,18,70,28,280,,1*77
$GLGSV,2,2,08,82,14,154,,79,13,105,,80,12,155,,71,01,240,,1*7C
$GPGLL,,,,,111023.623,V,N*7D
$GPTXT,01,01,02,ANTSTATUS=OPEN*2B
$GPRMC,111024.623,V,,,,,0.08,0.00,020723,,,N,V*3B
$GPVTG,0.00,T,,M,0.08,N,0.15,K,N*3E
$GPGGA,111024.623,,,,,0,0,,,M,,M,,*48
$GPGSA,A,1,,,,,,,,,,,,,,,,1*03
$GPGSA,A,1,,,,,,,,,,,,,,,,2*00
$GPGSV,4,1,14,18,61,085,,32,60,279,,28,31,187,,23,29,026,,0*65
$GPGSV,4,2,14,10,29,343,,27,28,295,,195,26,129,,24,18,052,,0*52
$GPGSV,4,3,14,29,14,162,,25,08,139,,26,05,221,,31,04,205,,0*69
$GPGSV,4,4,14,08,01,314,,194,01,106,,0*55
$GLGSV,2,1,08,83,57,148,,84,53,342,,69,29,353,18,70,28,280,,1*77
$GLGSV,2,2,08,82,14,154,,79,13,105,,80,12,155,,71,01,240,,1*7C
$GPGLL,,,,,111024.623,V,N*7A
$GPTXT,01,01,02,ANTSTATUS=OPEN*2B
$GPRMC,111025.623,V,,,,,0.64,194.86,020723,,,N,V*32
$GPVTG,194.86,T,,M,0.64,N,1.18,K,N*3A
$GPGGA,111025.623,,,,,0,0,,,M,,M,,*49
$GPGSA,A,1,,,,,,,,,,,,,,,,1*03
$GPGSA,A,1,,,,,,,,,,,,,,,,2*00
Serial MonitorNow we can try reading and decoding the $GPRMC data. GP indicates GPS and used when the positioning data comes only from the GPS satellites. Upload the following code and open the serial monitor. This is a version of the Print_GPRMC.ino example modified for ESP32.
//======================================================================================//
/**
* @file Print_GPRMC.ino
* @brief Reads the NMEA output from the GNSS module and prints it on the serial monitor.
* @date +05:30 12:28:39 AM 03-08-2024, Saturday
* @version 1.0.1
* @author Vishnu Mohanan (@vishnumaiea)
* @par GitHub Repository: https://github.com/CIRCUITSTATE/CSE_GNSS
* @par MIT License
*
*/
//======================================================================================//
#include <Arduino.h>
#include <CSE_GNSS.h>
//======================================================================================//
#define PORT_GPS_SERIAL Serial1 // GPS serial port
#define PORT_DEBUG_SERIAL Serial // Debug serial port
// For ESP32
#define PIN_GPS_SERIAL_TX 16
#define PIN_GPS_SERIAL_RX 17
#define VAL_GPS_BAUDRATE 9600
#define VAL_DEBUG_BAUDRATE 115200
//======================================================================================//
// Forward declarations
void setup();
void loop();
//======================================================================================//
// Set the serial ports and the baudrate for the GNSS module.
// Both ports have to be manually initialized through begin() call.
CSE_GNSS GNSS_Module (&PORT_GPS_SERIAL, &PORT_DEBUG_SERIAL);
// Following is how we define the format of the GPRMC (with Second mode indicator)
String GPRMC_Sample = "$GPRMC,120556.096,V,,,,,0.00,204.84,020723,,,N,V*33"; // A sample reference line
String GPRMC_Data_Names [] = {"Header", "UTC", "Status", "Latitude", "Latitude Direction", "Longitude", "Longitude Direction", "Speed", "Course", "Date", "Mag Variation", "Mag Variation Direction", "Mode", "Second Mode", "Checksum"};
String GPRMC_Description = "Recommended Minimum Specific GNSS Data"; // A human readable description of the data.
// Format: Name, Description, Data Count, Data Names, Sample
NMEA_Data NMEA_GPRMC ("GPRMC", GPRMC_Description, 15, GPRMC_Data_Names, GPRMC_Sample); // An object to save and handle the data.
//======================================================================================//
/**
* @brief Setup the serial ports and pins.
*
*/
void setup() {
PORT_DEBUG_SERIAL.begin (VAL_DEBUG_BAUDRATE);
// For ESP32 boards
PORT_GPS_SERIAL.begin (VAL_GPS_BAUDRATE, SERIAL_8N1, PIN_GPS_SERIAL_RX, PIN_GPS_SERIAL_TX);
GNSS_Module.begin(); // Initialize the GNSS module.
GNSS_Module.addData (&NMEA_GPRMC); // Add the data object to the GNSS module.
PORT_DEBUG_SERIAL.println();
PORT_DEBUG_SERIAL.println ("--- CSE_GNSS [Print_GPRMC] ---");
delay (1000);
}
//======================================================================================//
/**
* @brief Runs indefinitely.
*
*/
void loop() {
GNSS_Module.read (1024);
GNSS_Module.extractNMEA();
String GNSS_Data = GNSS_Module.getNmeaDataString();
GNSS_Module.getDataRef ("GPRMC").find (GNSS_Data); // Find the GPRMC sentences in the read data
GNSS_Module.getDataRef ("GPRMC").print(); // Print the GNRMC sentences in preformatted format
delay (10);
}
//======================================================================================//
C++Unlike the NEO-6M GY-NEO6MV2 module we have tested before, the GPRMC sentence of L86 here has 15 fields instead of 14, by default. This is because of the presence of the extra Second Mode Indicator. Because the CSE_GNSS library allows us to define the message formats and fields, we can easily change this in the code as seen in the lines below.
// Following is how we define the format of the GPRMC (with Second mode indicator)
String GPRMC_Sample = "$GPRMC,120556.096,V,,,,,0.00,204.84,020723,,,N,V*33"; // A sample reference line
String GPRMC_Data_Names [] = {"Header", "UTC", "Status", "Latitude", "Latitude Direction", "Longitude", "Longitude Direction", "Speed", "Course", "Date", "Mag Variation", "Mag Variation Direction", "Mode", "Second Mode", "Checksum"};
String GPRMC_Description = "Recommended Minimum Specific GNSS Data"; // A human readable description of the data.
// Format: Name, Description, Data Count, Data Names, Sample
NMEA_Data NMEA_GPRMC ("GPRMC", GPRMC_Description, 15, GPRMC_Data_Names, GPRMC_Sample); // An object to save and handle the data.
C++The remaining logic of the code is very simple. In the loop()
function, we will read a fixed number of bytes from the GNSS module. Here, we are reading 1024 bytes. You can change this to any other number depending on the RAM available or the number of data lines you want to read at a time. The read data is stored into an internal buffer. The extractNMEA()
function then extracts the NMEA data from the buffer. This process removes any invalid characters such as leading or trailing whitespaces. Next, we can convert the data in the buffer to an Arduino String using getDataString()
function. In the next two lines, we will search the line for the GPRMC header, decode the data and save them to the NMEA_GPRMC
object.
After flashing the code, you can open the serial monitor and get a similar output like below. You have to be an open space with clear sky. Make sure to direct the patch antenna to the open sky. It can take some time to find multiple satellites and synchronize the time on the module. For us, it took around 3 minutes to get a lock initially. After the initial lock, you will get the position faster from then onward.
NMEA_Data check(): $GPGLL,,,,,140056.083,V,N*77
NMEA_Data check(): Invalid header.
NMEA_Data check(): $GPTXT,01,01,02,ANTSTATUS=OPEN*2B
NMEA_Data check(): Invalid header.
NMEA_Data check(): $GPRMC,140057.083,V,,,,,0.00,204.84,020723,,,N,V*35
NMEA_Data check(): Valid GPRMC sentence.
NMEA_Data set(): $GPRMC,140057.083,V,,,,,0.00,204.84,020723,,,N,V*35
NMEA_Data check(): $GPRMC,140057.083,V,,,,,0.00,204.84,020723,,,N,V*35
NMEA_Data check(): Valid GPRMC sentence.
NMEA_Data parse(): $GPRMC,140057.083,V,,,,,0.00,204.84,020723,,,N,V*35
NMEA_Data print():
GPRMC: $GPRMC,140057.083,V,,,,,0.00,204.84,020723,,,N,V*35
Header: $GPRMC
UTC: 140057.083
Status: V
Latitude:
Latitude Direction:
Longitude:
Longitude Direction:
Speed: 0.00
Course: 204.84
Date: 020723
Mag Variation:
Mag Variation Direction:
Mode: N
Second Mode: V
Checksum: 35
Serial MonitorThat’s everything for this tutorial. Please let us know your feedback and suggestions to improve this article in the comments. Happy positioning 🛰️
Links
- Quectel L86 GNSS – Product Page
- Buy Quectel L86 – Evelta
- Buy 7Semi L86-M33 EVE-GNSS Breakout Module – Evelta
- CSE_GNSS Arduino Library by CIRCUITSTATE – GitHub
- What is GPS/GNSS & How to Interface u-blox NEO-6M GPS Module with Arduino – CIRCUITSTATE Electronics
Short Link
- Short URL to this page – https://www.circuitstate.com/quectell86