How to configure XIAO MG24 with 3 UARTs (Debug, GPS, GSM)?

Hi everyone,

I’m working on a project with the XIAO MG24 where I need to have three UARTs available at the same time:

  • One for USB serial (debugging / logging)
  • One for a GPS module
  • One for a GSM module

On most Arduino-style boards I would normally use the hardware UART(s) for GPS and GSM, and sometimes add a SoftwareSerial instance if I need more. However, on the XIAO MG24 it seems like SoftwareSerial is not implemented.

I’ve installed the latest XIAO MG24 board package in Arduino IDE, and I can use Serial and Serial1 without problems. But I can’t figure out how to properly configure a third hardware UART (aka Serial2).

Questions:

  1. Does the XIAO MG24 hardware actually expose more than 2 UART instances, and if so, which pins can be used for them?
  2. How can I configure Serial2 in Arduino (e.g. which files to edit in the board package to enable it)?
  3. If only 2 UARTs are possible in practice, is there a recommended alternative to handle a third device (since SoftwareSerial isn’t working on MG24)?

I would really appreciate if someone could point me to the correct pin mapping or configuration steps to enable 3 UARTs, or suggest a stable workaround.

Thanks in advance!

Hi there,

So ,
I can offer with Software serial you need to spell it out in all ways in your defines and Variables you use. No macro shortcuts available.
pretty standard when you want to go that way.
Also no Speeds above 9600 baud for stability.

Here are two examples, not EXACT for whatever , but you can see I did similar with the GPS Grove unit demo. (3 Serial ports)

// ===================================================================================
// XIAO nRF52840 Triple Serial Example
//   - Serial  : USB-C (debug + upload)
//   - Serial1 : Hardware UART on D6 (RX) / D7 (TX) → GPS
//   - Serial2 : SoftwareSerial on D4 (RX) / D5 (TX) → GSM
// ===================================================================================

#include <Arduino.h>
#include <SoftwareSerial.h>

// Hardware Serial1 (GPS) fixed to pins D6/D7 on XIAO nRF52840
#define GPS_BAUD 9600

// SoftwareSerial (GSM) – choose spare pins (example: D4, D5)
#define GSM_RX_PIN 4   // XIAO D4 ← GSM TX
#define GSM_TX_PIN 5   // XIAO D5 → GSM RX
#define GSM_BAUD   9600

SoftwareSerial Serial2(GSM_RX_PIN, GSM_TX_PIN); // RX, TX

void setup() {
  // USB debug serial
  Serial.begin(115200);
  while (!Serial) { ; }
  Serial.println("=== XIAO nRF52840 Triple Serial Demo ===");

  // GPS (hardware Serial1)
  Serial1.begin(GPS_BAUD);
  Serial.println("Serial1 (GPS) started on D6=RX, D7=TX");

  // GSM (SoftwareSerial)
  Serial2.begin(GSM_BAUD);
  Serial.println("Serial2 (GSM) started on D4=RX, D5=TX");
}

void loop() {
  // ---- GPS → USB ----
  if (Serial1.available()) {
    char c = Serial1.read();
    Serial.write(c);
  }

  // ---- GSM → USB ----
  if (Serial2.available()) {
    char c = Serial2.read();
    Serial.write(c);
  }

  // ---- USB → GSM (pass AT commands from Serial Monitor) ----
  if (Serial.available()) {
    char c = Serial.read();
    Serial2.write(c);
  }
}

Mg24 ish…

// ===================================================================================
// MG24 Triple Serial Demo
//   - Serial (USB-C): Debug / Logging
//   - Serial1: GPS module (Hardware UART)
//   - Serial2: GSM module (SoftwareSerial)
// 
// NOTE: Adjust RX/TX pins for Serial1 and Serial2 according to your wiring.
// ===================================================================================

#include <Arduino.h>
#include <SoftwareSerial.h>

// ----------- PIN DEFINITIONS -----------
// Hardware Serial1 pins (example: GPS connected)
//   Check the Xiao MG24 pinout: D0 = PA05, D1 = PA06 (default Serial1)
#define GPS_RX_PIN 0   // RX on XIAO (connects to GPS TX)
#define GPS_TX_PIN 1   // TX on XIAO (connects to GPS RX)

// SoftwareSerial pins (example: GSM module)
#define GSM_RX_PIN 4   // RX on XIAO (connects to GSM TX)
#define GSM_TX_PIN 5   // TX on XIAO (connects to GSM RX)

// ----------- OBJECTS -----------
SoftwareSerial Serial2(GSM_RX_PIN, GSM_TX_PIN); // RX, TX

void setup() {
  // USB debug serial
  Serial.begin(115200);
  while (!Serial) { ; } // Wait for Serial monitor
  Serial.println("MG24 Triple Serial Example Starting...");

  // Hardware Serial1 (GPS)
  Serial1.begin(9600, GPS_RX_PIN, GPS_TX_PIN);  // Some cores allow pin remap, else just Serial1.begin(9600)
  Serial.println("Serial1 (GPS) initialized at 9600 baud.");

  // SoftwareSerial (GSM)
  Serial2.begin(9600);
  Serial.println("Serial2 (GSM) initialized at 9600 baud.");
}

void loop() {
  // ---- GPS passthrough ----
  if (Serial1.available()) {
    int c = Serial1.read();
    Serial.write(c);  // Log GPS data to USB debug
  }

  // ---- GSM passthrough ----
  if (Serial2.available()) {
    int c = Serial2.read();
    Serial.write(c);  // Log GSM data to USB debug
  }

  // ---- Forward debug commands to GSM ----
  if (Serial.available()) {
    int c = Serial.read();
    Serial2.write(c);
  }
}

First one I have used , Second is a riff on the first with the Mg24

HTH
GL :slight_smile: PJ :v:

You can get a full 3 ports with the second UARTE peripheral (no SoftwareSerial, full hardware) so you get three real UARTs on the nRF52840? That way GPS + GSM both run at high speed.
food for thought. No bit-banging :grin:

There are a few options.

USART1 can be used - Serial .
ESUART0 can be used - Serial1.

Since SPI is allocated to EUSART1 (?) if you don’t use SPI, you could potentially use EUSART1.

I generally use RTT or SWO if I need debug information and have a shortage of serial interfaces.

Alternatively use a wireless interface to send “test” data.