Problem interfacing XIAO-ESP32C6 to RD-03E radar module (uart, Serial1)

I’m trying to interface an RD-03E radar module to my XIAO-ESP32C6 board. The RD-03 module uses a fixed baud rate of 256000. I’m able to compile and load code to the module but I’m not receiving any data over the UART. I’m using XIAO pin D3 for the TX and pin D2 for RX. The code I’m using is included below. Any advice will be much appreciated.

// testRD03E radar sensor
// JCL, 4June2025
// https://www.electroniclinic.com/rd-03d-mmwave-radar-multi-human-tracking-with-distance-speed-positioning/

#define RX_PIN D2
#define TX_PIN D3
#define BAUD_RATE 256000
#define BUFFER_BYTES 64
 
// Variables
uint8_t RX_BUF[BUFFER_BYTES] = {0};
uint8_t RX_count = 0;
uint8_t RX_temp = 0;
 
// Single-Target Detection Commands
uint8_t Single_Target_Detection_CMD[12] = {0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0x80, 0x00, 0x04, 0x03, 0x02, 0x01};
// Multi-Target Detection Command
uint8_t Multi_Target_Detection_CMD[12] = {0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0x90, 0x00, 0x04, 0x03, 0x02, 0x01};
 
void setup() {
    Serial.begin(115200); // Debugging info to Serial Monitor
    delay(500);

    Serial1.begin(BAUD_RATE, SERIAL_8N1, RX_PIN, TX_PIN);
    Serial1.setRxBufferSize(BUFFER_BYTES);

    Serial.println("RD-03D Radar Module Initialized");
 
    // Send single-target detection command
    Serial1.write(Single_Target_Detection_CMD, sizeof(Single_Target_Detection_CMD));

    Serial.println("Single-target detection mode activated.");
    delay(500);

    // Send multi-target detection command
    // Serial1.write(Multi_Target_Detection_CMD, sizeof(Single_Target_Detection_CMD));
    // Serial.println("Multi-target detection mode activated.");
    // delay(1000);

    RX_count = 0;
    Serial1.flush();
}
 
void loop() {
    // Read data from Serial1
    while (Serial1.available()) {
    //if (Serial1.available() > 0) {
        RX_temp = Serial1.read();
        RX_BUF[RX_count++] = RX_temp;
 
        // Prevent buffer overflow
        if (RX_count >= sizeof(RX_BUF)) {
            RX_count = sizeof(RX_BUF) - 1;
        }
 
        // Check for end of frame (0xCC, 0x55)
        if ((RX_count > 1) && (RX_BUF[RX_count - 1] == 0xCC) && (RX_BUF[RX_count - 2] == 0x55)) {
            processRadarData();
        }
    }
}

void processRadarData() {
         printBuffer();
        memset(RX_BUF, 0x00, sizeof(RX_BUF));   // Reset buffer and counter
        RX_count = 0;
    }

// Function to print buffer contents
void printBuffer() {
    Serial.print("RX_BUF: ");
    for (int i = 0; i < RX_count; i++) {
        Serial.print("0x");
        if (RX_BUF[i] < 0x10) Serial.print("0");  // Add leading zero for single-digit hex values
        Serial.print(RX_BUF[i], HEX);
        Serial.print(" ");
    }
    Serial.println();
}

Hi there,

So using the code tags above " </> " just paste it in there, will yield better results and higher quality help .

So looking at this you are close but conflated some stuff…
Your not explicitly setting up com port 1 correctly for hardware serial.
only software serial for the assignable ports can be used,

// testRD03E radar sensor
// JCL, 4June2025
// Rd-03D mmWave Radar: Multi-Human Tracking with Distance, Speed & Positioning

#define RX_PIN D2
#define TX_PIN D3
#define BAUD_RATE 256000
#define BUFFER_BYTES 64

// Variables
uint8_t RX_BUF[BUFFER_BYTES] = {0};
uint8_t RX_count = 0;
uint8_t RX_temp = 0;

// Single-Target Detection Commands
uint8_t Single_Target_Detection_CMD[12] = {0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0x80, 0x00, 0x04, 0x03, 0x02, 0x01};
// Multi-Target Detection Command
uint8_t Multi_Target_Detection_CMD[12] = {0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0x90, 0x00, 0x04, 0x03, 0x02, 0x01};

void setup() {
Serial.begin(115200); // Debugging info to Serial Monitor
delay(500);

Serial1.begin(BAUD_RATE, SERIAL_8N1, RX_PIN, TX_PIN);
Serial1.setRxBufferSize(BUFFER_BYTES);

Serial.println("RD-03D Radar Module Initialized");

// Send single-target detection command
Serial1.write(Single_Target_Detection_CMD, sizeof(Single_Target_Detection_CMD));

Serial.println("Single-target detection mode activated.");
delay(500);

// Send multi-target detection command
// Serial1.write(Multi_Target_Detection_CMD, sizeof(Single_Target_Detection_CMD));
// Serial.println("Multi-target detection mode activated.");
// delay(1000);

RX_count = 0;
Serial1.flush();
}

void loop() {
// Read data from Serial1
while (Serial1.available()) {
//if (Serial1.available() > 0) {
RX_temp = Serial1.read();
RX_BUF[RX_count++] = RX_temp;

    // Prevent buffer overflow
    if (RX_count >= sizeof(RX_BUF)) {
        RX_count = sizeof(RX_BUF) - 1;
    }

    // Check for end of frame (0xCC, 0x55)
    if ((RX_count > 1) && (RX_BUF[RX_count - 1] == 0xCC) && (RX_BUF[RX_count - 2] == 0x55)) {
        processRadarData();
    }
}
}

void processRadarData() {
printBuffer();
memset(RX_BUF, 0x00, sizeof(RX_BUF)); // Reset buffer and counter
RX_count = 0;
}

// Function to print buffer contents
void printBuffer() {
Serial.print("RX_BUF: “);
for (int i = 0; i < RX_count; i++) {
Serial.print(“0x”);
if (RX_BUF[i] < 0x10) Serial.print(“0”); // Add leading zero for single-digit hex values
Serial.print(RX_BUF[i], HEX);
Serial.print(” ");
}
Serial.println();
}

You may want to take a look, I had something similar. and did it this way… YMMV

https://forum.seeedstudio.com/t/reading-distance-using-esp32-and-seeed-24ghz-human-static-lite-sensor/275885/6?u=pj_glasso
for a general rule though, I follow this understanding…
they are not all the same , USE a hardware UART ports whenver High Speed or timing is more critical, i.e. Serial for USB, Serial1 for D7 & D6
Those are assigned UARTS, Software_Serial Allows you to use any GPIO pins as a comport pair,via BIT_Banging but some limits are obvious doing it this way.

Hardware + Software Serial on ESP32 (C3/S3/C6)

#include <HardwareSerial.h>
#include <SoftwareSerial.h>

// Hardware Serial on UART1 (TX = GPIO10, RX = GPIO9 for example)
HardwareSerial Serial1(1);  // Use UART1

// Software Serial on arbitrary GPIOs (TX = GPIO6, RX = GPIO7 here)
SoftwareSerial mySoftSerial(6, 7);  // TX, RX

void setup() {
  // USB Serial for debug
  Serial.begin(115200);
  delay(1000);
  Serial.println("=== Serial Ports Example ===");

  // Start Hardware Serial1
  Serial1.begin(9600, SERIAL_8N1, 9, 10);  // RX = 9, TX = 10
  Serial.println("Hardware Serial1 started on GPIO9/10");

  // Start Software Serial
  mySoftSerial.begin(9600);
  Serial.println("Software Serial started on GPIO6/7");
}

void loop() {
  // Send message out both ports
  Serial1.println("Hello from HardwareSerial1");
  mySoftSerial.println("Hello from SoftwareSerial");

  delay(1000);
}

:warning: Notes:

  • You can remap UART pins using Serial1.begin(baud, config, rxPin, txPin) on ESP32.
  • Avoid using GPIOs 0, 1, 3, or others with boot functions unless you know they’re safe on your board.
  • For the Xiao ESP32C3/S3, UART1 and UART2 are available depending on your board config.
  • SoftwareSerial can be flaky on higher baud rates—best kept at 9600–19200 for stable use.

Try yours like this, and get back …

#include <HardwareSerial.h>

#define RX_PIN 2   // Adjust for your board C6 is GPIO02 &GPIO21 for D2 & D3 if the pin macros are not supported.
#define TX_PIN 21
#define BAUD_RATE 256000
#define BUFFER_BYTES 64

uint8_t RX_BUF[BUFFER_BYTES] = {0};
uint8_t RX_count = 0;

// Command frame
uint8_t Single_Target_Detection_CMD[12] = {
  0xFD, 0xFC, 0xFB, 0xFA,
  0x02, 0x00, 0x80, 0x00,
  0x04, 0x03, 0x02, 0x01
};

void setup() {
  Serial.begin(115200);
  delay(500);

  Serial1.begin(BAUD_RATE, SERIAL_8N1, RX_PIN, TX_PIN);
  Serial1.setRxBufferSize(BUFFER_BYTES);

  Serial.println("RD-03D Radar Module Initialized");
  Serial1.write(Single_Target_Detection_CMD, sizeof(Single_Target_Detection_CMD));
  Serial.println("Single-target detection mode activated.");

  RX_count = 0;
  Serial1.flush();
}

void loop() {
  while (Serial1.available()) {
    uint8_t RX_temp = Serial1.read();
    RX_BUF[RX_count++] = RX_temp;

    if (RX_count >= sizeof(RX_BUF)) RX_count = sizeof(RX_BUF) - 1;

    if (RX_count > 1 && RX_BUF[RX_count - 2] == 0x55 && RX_BUF[RX_count - 1] == 0xCC) {
      processRadarData();
    }
  }
}

void processRadarData() {
  Serial.print("RX_BUF: ");
  for (int i = 0; i < RX_count; i++) {
    if (RX_BUF[i] < 0x10) Serial.print("0");
    Serial.print(RX_BUF[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
  RX_count = 0;
  memset(RX_BUF, 0, sizeof(RX_BUF));
}

HTH
GL :slight_smile: PJ :v:

1 Like

Just use hardware serial - works for me!

#include <HardwareSerial.h>

#define RX_PIN GPIO_NUM_2
#define TX_PIN GPIO_NUM_21
#define BAUD_RATE 256000

HardwareSerial MySerial(1);

void setup() {
  // Initialize serial communication
  MySerial.begin(BAUD_RATE, SERIAL_8N1, RX_PIN, TX_PIN);
  
  // Wait for the serial port to connect
  while (!MySerial) {
    delay(10);
  }
  
  // Print a message to indicate that the serial port is ready
  MySerial.println("Serial port initialized at " + String(BAUD_RATE) + " baud.");
}

2 Likes