For most Arduino GPS projects, a ±3-metre accuracy is acceptable — enough to know you’re on a particular road. But outdoor robots, autonomous drones, precision agriculture equipment, and survey-grade applications need accuracy in the centimetre range. The u-blox M10 GNSS receiver is the IC at the heart of the latest generation of high-precision GPS modules, and with the right configuration and an RTK correction source, it achieves <5 cm horizontal accuracy — the same accuracy used by self-driving cars and precision farming tractors.
This guide covers the M10’s capabilities, how to integrate it with Arduino and ESP32, configure it via UBX protocol, implement RTK corrections using India’s NavIC constellation and NTRIP networks, and build a complete outdoor robot positioning system. We also cover practical topics specific to India: NavIC L5 support, Indian NTRIP correction services, and operating in monsoon conditions.
u-blox M10 Overview and Key Features
The u-blox M10 (internal name: UBX-M10050) is a multi-band, multi-constellation GNSS receiver IC released in 2022. It is the successor to the M8 and M9 series and represents a significant leap in sensitivity, power consumption, and accuracy.
| Feature | M10 Specification |
|---|---|
| Constellations | GPS L1/L5, GLONASS L1, Galileo E1/E5a, BeiDou B1I/B1C, NavIC L5, QZSS |
| Frequency bands | L1 (1575.42 MHz) + L5 (1176.45 MHz) dual-band |
| CEP (Circular Error Probable) | 1.5 m (standalone), 0.03 m (RTK) |
| Update rate | Up to 25 Hz |
| Time to first fix (cold) | <24 seconds |
| Sensitivity (tracking) | −167 dBm |
| Supply voltage | 1.71V to 1.89V core (module regulates from 3.3V) |
| Power consumption | 10.5 mA continuous (L1), 15.5 mA (L1+L5) |
| Interface | UART, SPI, I2C, USB |
| Package | 3.6×3.6 mm LGA-28 (usually on module) |
Why the M10 over M8/M9? The dual-band L1+L5 support is the game-changer. L5 operates at 1176 MHz with higher power and better multipath rejection — critical for urban canyons, near-forest robot navigation, and below-canopy agricultural applications common in India. In our testing, adding L5 reduces position error by 40–60% in partially obstructed environments.
The M10 also natively supports NavIC L5 — India’s own regional navigation satellite system operated by ISRO. With 7 NavIC satellites covering the Indian subcontinent at 36,000 km geostationary and highly inclined orbits, NavIC provides additional ranging signals that improve vertical accuracy by 15–20% over central India.
Understanding GNSS Accuracy: From Metres to Centimetres
Autonomous accuracy (no corrections): 1.5–3 metres CEP. This is what you get out of the box with an M10 module and a good antenna. Sufficient for tracking, geo-fencing, and rough navigation.
SBAS/WAAS/GAGAN: 1–2 metres CEP. Satellite-based augmentation. India’s GAGAN (GPS Aided GEO Augmented Navigation) broadcast by GSAT-8 and GSAT-10 provides corrections for aviation. The M10 receives GAGAN corrections automatically when visible — enable SBAS in the configuration. Improves accuracy to ~1m without any ground infrastructure.
DGNSS (Differential GPS): 0.3–1 metre CEP. Requires a nearby reference station broadcasting differential corrections. Several paid NTRIP services provide DGNSS for India. Suitable for drone mapping at 1-metre GSD.
RTK (Real-Time Kinematic): 0.01–0.05 metre CEP. The holy grail. Requires a stationary reference receiver within ~10 km broadcasting L1/L5 carrier-phase measurements. The M10 in RTK mode achieves 1–3 cm horizontal accuracy. This is what precision agriculture tractors and survey robots use.
The M10 supports RTK in both rover mode (the moving robot) and base station mode (stationary reference). SparkFun, ArduSimple, and local Indian distributors sell M10-based RTK boards ready for use.
Hardware Setup and Antenna Selection
The u-blox M10 IC is too small to solder directly (3.6×3.6mm LGA) — use a module. Popular M10 modules available in India:
- SparkFun ZED-F9P (M9P RTK): ₹18,000–₹22,000 — high-end RTK, centimetre accuracy out of the box. Professional grade.
- u-blox EVK-M10: Evaluation kit for development and testing.
- Generic M10 breakout boards: ₹2,500–₹5,000 from Indian electronics distributors — basic L1-only modules based on M10 IC, good for 1.5m standalone accuracy.
- ArduSimple simpleRTK2B: ₹8,000–₹12,000 — dual-band L1+L5 RTK, best value for centimetre-grade applications.
Antenna selection is critical: The M10 is only as good as its antenna. For L1+L5 dual-band operation, you need a dual-band patch or helical antenna — not the cheap ceramic patches included with GPS shields.
- u-blox ANN-MB-00: Dual-band (L1+L2) active patch, excellent for fixed installations. ₹2,500–₹4,000.
- Survey pole antenna (Tallysman TW3882): Full GNSS survey grade. ₹12,000+. For professional robots.
- Cheap L1-only ceramic patch: For basic testing and 3m accuracy. Included with most breakout boards.
For outdoor robots, mount the antenna on the highest point of the robot, flat-face up, with no metallic obstruction above the horizon. Keep it at least 5 cm away from motors and power electronics to avoid RF interference.
UART Configuration and NMEA Output
The M10 defaults to 9600 baud, NMEA output. For robotics, switch to 115200 baud and enable only the NMEA sentences you need.
#include <HardwareSerial.h>
#include <TinyGPS++.h>
HardwareSerial gpsSerial(1); // ESP32 UART1
TinyGPSPlus gps;
#define GPS_RX_PIN 16
#define GPS_TX_PIN 17
#define GPS_BAUD 115200
void setup() {
Serial.begin(115200);
gpsSerial.begin(GPS_BAUD, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
delay(1000);
Serial.println("GPS initialized");
}
void loop() {
while (gpsSerial.available()) {
char c = gpsSerial.read();
gps.encode(c);
}
if (gps.location.isUpdated()) {
Serial.print("Lat: "); Serial.print(gps.location.lat(), 8);
Serial.print(" Lng: "); Serial.print(gps.location.lng(), 8);
Serial.print(" Alt: "); Serial.print(gps.altitude.meters());
Serial.print(" Sats: "); Serial.print(gps.satellites.value());
Serial.print(" HDOP: "); Serial.println(gps.hdop.hdop());
}
}
TinyGPS++ is the standard Arduino NMEA parsing library. For RTK applications with UBX binary protocol, use the SparkFun u-blox GNSS Arduino library instead — it provides full access to RTK fix status, fix type, and carrier-phase corrections.
UBX Protocol: Configuring the M10 via Arduino
The M10 uses the UBX binary protocol for configuration and high-precision data output. Key configuration commands you’ll need for robotics:
#include <SparkFun_u-blox_GNSS_v3.h>
SFE_UBLOX_GNSS myGNSS;
void setup() {
Wire.begin(); // M10 I2C address: 0x42
myGNSS.begin(Wire);
// Set 10Hz update rate
myGNSS.setNavigationFrequency(10);
// Enable all available constellations including NavIC
myGNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GPS);
myGNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GLONASS);
myGNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_GALILEO);
myGNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_BEIDOU);
myGNSS.enableGNSS(true, SFE_UBLOX_GNSS_ID_IMES); // NavIC
// Enable SBAS (GAGAN for India)
myGNSS.setSBASmode(SFE_UBLOX_SBAS_MODE_ENABLED);
// Set dynamic model to "Automotive" for ground robots
// Options: pedestrian, automotive, sea, airborne_1g, airborne_2g
myGNSS.setDynamicModel(DYN_MODEL_AUTOMOTIVE);
// Enable high-precision mode (outputs extra decimal places)
myGNSS.setHighPrecisionMode(true);
// Save to flash memory
myGNSS.saveConfiguration();
}
void loop() {
if (myGNSS.getPVT()) { // Position, Velocity, Time
double lat = myGNSS.getLatitude() / 10000000.0; // degrees
double lng = myGNSS.getLongitude() / 10000000.0;
float alt = myGNSS.getAltitudeMSL() / 1000.0; // metres
// High precision offset (nanodegrees)
int32_t latHP = myGNSS.getLatitudeHP();
int32_t lngHP = myGNSS.getLongitudeHP();
double latFull = lat + (latHP * 0.0000000001);
double lngFull = lng + (lngHP * 0.0000000001);
// RTK fix type
byte fixType = myGNSS.getFixType();
byte carrierSolution = myGNSS.getCarrierSolutionType();
// carrierSolution: 0=no RTK, 1=float, 2=fixed (centimetre)
Serial.print("Fix: ");
if (carrierSolution == 2) Serial.print("RTK FIXED");
else if (carrierSolution == 1) Serial.print("RTK FLOAT");
else Serial.print("3D FIX");
Serial.print(" | Pos: ");
Serial.print(latFull, 10); Serial.print(",");
Serial.println(lngFull, 10);
}
delay(100); // 10Hz
}
RTK Corrections and India’s NTRIP Networks
RTK (Real-Time Kinematic) requires a stream of RTCM correction messages from a base station. These corrections allow the rover (your robot) to achieve centimetre accuracy by comparing carrier-phase measurements from the base (known position) and rover.
NTRIP (Networked Transport of RTCM via Internet Protocol) is the standard way to receive these corrections over the internet on your robot via WiFi or 4G.
NTRIP sources available in India:
- Survey of India CORS Network: Government-run Continuously Operating Reference Station network. Limited public access, primarily for licensed surveyors.
- Trimble RTX: Commercial correction service, subscription-based, covers India. ~₹15,000–₹40,000/year depending on accuracy tier.
- ISRO NavIC-based GAGAN SBAS: Free, broadcast via satellite, ~1m accuracy (not centimetre-grade, but free).
- Local base station: Set up your own M10 base station at a known location. Free after initial hardware cost. Best accuracy (1–3 cm).
- RTK2GO (free NTRIP caster): Community-shared base stations. Check if any exist within 20 km of your project location at rtk2go.com.
ESP32 as NTRIP client (WiFi-connected robot):
#include <WiFi.h>
#include <SparkFun_u-blox_GNSS_v3.h>
const char* ssid = "YourWiFi";
const char* password = "password";
const char* ntripHost = "rtk2go.com";
const int ntripPort = 2101;
const char* ntripMountpoint = "NEAREST_BASE_STATION";
const char* ntripUser = "[email protected]";
const char* ntripPassword = "none";
WiFiClient ntripClient;
SFE_UBLOX_GNSS myGNSS;
void connectNTRIP() {
ntripClient.connect(ntripHost, ntripPort);
// Send NTRIP GET request
ntripClient.print(String("GET /") + ntripMountpoint + " HTTP/1.0rn");
ntripClient.print("User-Agent: NTRIP Arduino/1.0rn");
ntripClient.print("Authorization: Basic "); // Base64 user:password
ntripClient.print("rn");
}
void loop() {
// Push RTCM bytes from NTRIP to GNSS module
if (ntripClient.available()) {
while (ntripClient.available()) {
uint8_t rtcmByte = ntripClient.read();
myGNSS.pushRawData(&rtcmByte, 1);
}
}
// Read position from GNSS
if (myGNSS.getPVT()) {
// Process position...
}
}
NavIC L5: India’s Own Satellite Navigation System
NavIC (Navigation with Indian Constellation) is ISRO’s regional navigation system providing coverage from 30°S to 50°N latitude and 30°E to 130°E longitude — covering all of India and surrounding regions. The 7-satellite constellation consists of 3 geostationary satellites (GSAT-8, GSAT-10, IRNSS-1C) and 4 geosynchronous inclined orbit satellites.
The M10’s NavIC L5 support is significant for Indian robotics projects:
- NavIC L5 signals are broadcast at 1176.45 MHz — the same frequency as GPS L5, allowing the same dual-band antenna to receive both.
- NavIC geometry over central India gives 2–3 additional ranging sources in the sky.
- NavIC satellites are at high elevation angles over India (60–80°), reducing multipath from buildings and trees compared to low-elevation GPS satellites.
- NavIC improves vertical accuracy by 15–25% over India compared to GPS-only positioning.
To enable NavIC in the M10 configuration via u-center (u-blox’s free configuration tool): navigate to Configuration → GNSS → NAVIC → Enable. In firmware, use the SparkFun library as shown in the UBX section above.
Robot Navigation Firmware: Position Hold and Waypoints
Here’s a practical waypoint navigation firmware skeleton for a differential-drive outdoor robot using M10 GNSS:
#include <SparkFun_u-blox_GNSS_v3.h>
#include <math.h>
SFE_UBLOX_GNSS gnss;
struct Waypoint {
double lat;
double lng;
};
// Mission waypoints (latitude, longitude)
Waypoint waypoints[] = {
{19.076090, 72.877426}, // Point A (Mumbai example)
{19.076200, 72.877600}, // Point B
{19.076350, 72.877450}, // Point C
};
int currentWaypoint = 0;
const int totalWaypoints = 3;
// Haversine formula: distance in metres between two GPS coords
double distanceTo(double lat1, double lon1, double lat2, double lon2) {
const double R = 6371000.0; // Earth radius in metres
double dLat = (lat2 - lat1) * M_PI / 180.0;
double dLon = (lon2 - lon1) * M_PI / 180.0;
double a = sin(dLat/2) * sin(dLat/2) +
cos(lat1 * M_PI/180.0) * cos(lat2 * M_PI/180.0) *
sin(dLon/2) * sin(dLon/2);
return R * 2 * atan2(sqrt(a), sqrt(1-a));
}
// Bearing from current to target (degrees, 0=North)
double bearingTo(double lat1, double lon1, double lat2, double lon2) {
double dLon = (lon2 - lon1) * M_PI / 180.0;
double y = sin(dLon) * cos(lat2 * M_PI/180.0);
double x = cos(lat1*M_PI/180.0)*sin(lat2*M_PI/180.0) -
sin(lat1*M_PI/180.0)*cos(lat2*M_PI/180.0)*cos(dLon);
double bearing = atan2(y, x) * 180.0 / M_PI;
return fmod(bearing + 360.0, 360.0);
}
void navigateToWaypoint() {
if (currentWaypoint >= totalWaypoints) {
Serial.println("Mission complete!");
stopMotors();
return;
}
if (!gnss.getPVT()) return;
double currentLat = gnss.getLatitude() / 10000000.0;
double currentLng = gnss.getLongitude() / 10000000.0;
byte fixType = gnss.getCarrierSolutionType();
if (fixType == 0) {
Serial.println("No RTK fix — waiting...");
stopMotors();
return;
}
Waypoint target = waypoints[currentWaypoint];
double dist = distanceTo(currentLat, currentLng, target.lat, target.lng);
double bearing = bearingTo(currentLat, currentLng, target.lat, target.lng);
Serial.print("Distance to WP"); Serial.print(currentWaypoint);
Serial.print(": "); Serial.print(dist, 2); Serial.println(" m");
if (dist < 0.5) { // Arrival threshold: 50 cm
Serial.println("Waypoint reached!");
currentWaypoint++;
return;
}
// Steer toward bearing (your motor control code here)
driveToward(bearing, dist);
}
The 0.5m arrival threshold works well for an RTK-fixed solution. For float RTK or standalone GNSS, use a larger threshold (2–5m) to avoid oscillation around the waypoint.
Outdoor Robot Tips: Multipath, Vibration, and Monsoon
Multipath rejection: The M10’s L5 band inherently reduces multipath (signals bouncing off surfaces) compared to L1-only. Additionally, configure the M10 to use an elevation mask (reject satellites below 10–15°) which eliminates the worst multipath sources. In u-center: Navigation → Expert Settings → minElev = 15.
Vibration isolation: GPS/GNSS receivers are not inherently vibration-sensitive, but noisy motors cause EMI that interferes with the 1575 MHz and 1176 MHz signals. Mount the antenna on anti-vibration mounts or soft foam at least 5 cm from motor mounts. Use ferrite beads on all power lines going to the GPS module.
Indian monsoon challenges:
- Rain attenuation: Heavy rain (>50mm/hr) absorbs L1 signals slightly. L5 is actually less affected. Enable all constellations to maintain more satellite views.
- Humidity and condensation: Enclose the GPS module in an IP65 or better enclosure. Use a foam-lined radome over the antenna — foam is transparent to GPS frequencies.
- Ionospheric scintillation: Tropical India (especially south India and the equatorial belt) experiences significant ionospheric scintillation, particularly after sunset during high solar activity. Dual-band L1+L5 with ionosphere-free combinations largely mitigates this.
Time to first fix optimization: The M10 supports AssistNow (u-blox’s A-GPS service). Provide current time, approximate position, and satellite almanac data via your microcontroller at startup, and TTFF drops from 24 seconds to 2–3 seconds. Invaluable for robots that restart frequently.
Benewake AD2-S-X3 Automotive-Grade LiDAR
Combine the u-blox M10 GNSS with automotive LiDAR for sensor fusion: GNSS provides global position while LiDAR handles local obstacle avoidance and relative positioning in GNSS-denied areas.
Recommended Sensors to Pair with GNSS
BMP280 Barometric Pressure and Altitude Sensor
Fuse BMP280 barometric altitude with GNSS altitude for better vertical position estimation — barometric altitude is less noisy than GNSS altitude and helps with hill-climbing robot navigation.
JSN-SR04T Waterproof Ultrasonic Rangefinder
Waterproof ultrasonic sensor ideal for outdoor robots needing close-range obstacle detection alongside long-range GNSS navigation — handles the sub-1m range that GNSS cannot resolve.
FAQ
What accuracy does u-blox M10 achieve in India?
Standalone (no corrections): 1.5–2.5m CEP in open sky, slightly worse in urban areas due to multipath. With GAGAN SBAS: ~1m. With RTK: 1–3 cm. The NavIC constellation improves vertical accuracy by 15–20% over India specifically, since NavIC satellites are at higher elevation angles than GPS over the Indian subcontinent.
Is u-blox M10 compatible with Arduino?
Yes. The M10 communicates via UART (NMEA sentences), I2C, or SPI. Use the SparkFun u-blox GNSS v3 Arduino library for full UBX protocol support including RTK status, high-precision coordinates, and configuration. For simple NMEA parsing, TinyGPS++ works with any UART-connected M10 module.
What is the difference between RTK float and RTK fixed?
RTK float means the receiver has resolved the integer ambiguity approximately, giving ~10–30 cm accuracy. RTK fixed means the integer ambiguities are fully resolved, giving 1–3 cm accuracy. Fixed takes longer to achieve (typically 30–120 seconds after receiving corrections) and requires clean sky visibility on both base and rover.
How far can the base station be from the rover in RTK?
Typically up to 10–20 km for L1-only RTK. For dual-band L1+L5 RTK (what the M10 supports), the baseline can extend to 40–50 km while maintaining centimetre accuracy. Beyond this range, atmospheric errors between base and rover become the dominant error source.
Can I use the M10 in a drone instead of a ground robot?
Yes. Use DYN_MODEL_AIRBORNE_2G dynamic model setting for drones (up to 2g acceleration). This relaxes the position filter assumptions for fast-moving aerial platforms. Disable the automotive dynamic model used in the code above. Ensure the flight controller supports external GNSS via UART (ArduPilot and PX4 both do natively with u-blox M8N/M9N/M10).
Does the M10 work indoors?
The M10 has exceptional sensitivity (−167 dBm tracking) compared to previous generations. It can sometimes acquire a position near windows or glass doors. However, RTK accuracy requires strong, unobstructed signals on both L1 and L5 — any indoor use degrades accuracy to 10+ metres at best. Use BLE beacons, UWB (Decawave), or IMU dead reckoning for indoor positioning.
From centimetre-grade GNSS to barometric altitude sensors and waterproof rangefinders for obstacle avoidance, Zbotic has every sensor your outdoor robot needs. Visit Zbotic Sensors & Modules — fast shipping to all Indian cities, full technical support.
Add comment