Cant get HMMD mmWave talking with ESP32C6 Using Hardware serial

About The Problem

I wanted to explore HMMD mmWave thus I connected the sensor up with esp32c6. For starters, I used the software serial, but the data coming through seemed garbled up. My initial suspect were the high baud rate 115200, thus I switched from Software to Hardware serial.

After switching to hardware serial, although I was able decode and use the data, the data stream seemed to hang after 1-2 messages from the sensor. Hence my problem, in theory the sensor should always send the datastream, but the link seems to break after 1-2 messages when using hardware serial.

About My Setup

  • I’m using vscode with pio and arduino framework.
  • https://github.com/Seeed-Studio/platform-seeedboards.git as platform
  • Sensor is connected to D6/D7

here’s that manufacturer recommends (uses software serial, garbles up data)

#include <SoftwareSerial.h>

SoftwareSerial mySerial(D7, D6); // RX, TX

void sendHexData(String hexString) {
  // Convert hex string to bytes
  int hexStringLength = hexString.length();
  byte hexBytes[hexStringLength / 2];
  for (int i = 0; i < hexStringLength; i += 2) {
    hexBytes[i / 2] = strtoul(hexString.substring(i, i + 2).c_str(), NULL, 16);
  }

  // Send bytes through software serial
  mySerial.write(hexBytes, sizeof(hexBytes));
}

void readSerialData() {
  // Read and print data from software serial
  while (mySerial.available() > 0) {
    char incomingByte = mySerial.read();
    Serial.print(incomingByte);
  }
}

void setup() {
  // Start the serial communication with a baud rate of 115200
  Serial.begin(115200);
  mySerial.begin(115200);

  // Wait for the serial port to initialize
  while (!Serial) {
    delay(100);
  }

  // Hex string to send
  String hex_to_send = "FDFCFBFA0800120000006400000004030201";
  sendHexData(hex_to_send);
}

void loop() {
  // Read and print serial data
  readSerialData();
}

Here’s the code that I’m using (uses hardware serial, data stops coming through after 1-2 messages)

#include <Arduino.h>
#include <HardwareSerial.h>

HardwareSerial mySerial(0); // RX, TX

void sendHexData(String hexString) {
  // Convert hex string to bytes
  int hexStringLength = hexString.length();
  byte hexBytes[hexStringLength / 2];
  for (int i = 0; i < hexStringLength; i += 2) {
    hexBytes[i / 2] = strtoul(hexString.substring(i, i + 2).c_str(), NULL, 16);
  }

  // Send bytes through software serial
  mySerial.write(hexBytes, sizeof(hexBytes));
}

void readSerialData() {
  // Read and print data from software serial
  while (mySerial.available() > 0) {
    char incomingByte = mySerial.read();
    Serial.print(incomingByte);
  }
}

void setup() {
  // Start the serial communication with a baud rate of 115200
  Serial.begin(115200);
  mySerial.begin(115200);

  // Wait for the serial port to initialize
  while (!Serial) {
    delay(100);
  }

  // Hex string to send
  String hex_to_send = "FDFCFBFA0800120000006400000004030201";
  sendHexData(hex_to_send);
}

void loop() {
  // Read and print serial data
  readSerialData();
}

Hi there,

And Welcome Here,

So your not far off, The Hardware Serial needs Hardware flow control enabled on the port. The Hang is when the Receive data (as you see , It BLASTS) Receive Buffer overflows. Software serial or Xon/Xoff Flow control is too slow unless the port speeds are very low.

What’s actually wrong in both sketches

  1. The code is printing binary as if it’s text

This line is a trap:

char incomingByte = mySerial.read();
Serial.print(incomingByte);

the sensor sends binary frames (very likely), a lot of bytes will be non-printable. It will look ā€œgarbledā€ even when it’s correct.

Fix: print hex:

uint8_t b = mySerial.read();
Serial.printf("%02X ", b);

2) The ā€œHardwareSerial mySerial(0)ā€ is probably the wrong UART

On ESP32 Arduino:

  • Serial is typically UART0 (USB/console)
  • Serial1 / Serial2 map to other UARTs

Doing HardwareSerial mySerial(0); can collide with Serial or get weird depending on core/variant.

Fix: use Serial1 (or explicit UART1/2), and map pins explicitly:

#define RX_PIN D7
#define TX_PIN D6
Serial1.begin(115200, SERIAL_8N1, RX_PIN, TX_PIN);

(Also: make sure you didn’t swap RX/TX. Sensor TX must go to ESP RX.)

3)You send the init command once… then maybe the sensor stops because it expects ACK / continuous polling / or it went into a different mode

Many mmWave modules:

  • require a ā€œstart streamingā€ command
  • or they stream only when polled
  • or they stop if their output buffer fills and the host doesn’t drain fast enough

The loop drains, but printing can be slow and block.

Why it ā€œhangs after 1–2 messagesā€ on hardware serial

Common causes:

A) UART pins not actually attached to that UART

If you don’t pass pins in .begin(), ESP32 may use default pins for that UART, not D6/D7.

B) It is saturating output / blocking on prints

If the mmWave sensor streams fast, dumping every byte to USB serial can block long enough that RX FIFO overruns → looks like stream ā€œstops.ā€ :backhand_index_pointing_left: :wink:

C) Buffer too small

ESP32 UART RX buffer can be small depending on core settings.

I would try this suggestion from the LLM

#include <Arduino.h>

#define RX_PIN D7
#define TX_PIN D6
#define BAUD   115200

// init command
static const uint8_t CMD[] = {
  0xFD,0xFC,0xFB,0xFA,0x08,0x00,0x12,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0x04,0x03,0x02,0x01
};

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

  Serial.println("UART test start");

  Serial1.begin(BAUD, SERIAL_8N1, RX_PIN, TX_PIN);
  Serial1.setRxBufferSize(4096);     // bigger buffer helps a lot

  delay(200);
  Serial.println("Sending init cmd...");
  Serial1.write(CMD, sizeof(CMD));
}

void loop() {
  static uint32_t last = 0;

  while (Serial1.available()) {
    uint8_t b = Serial1.read();
    Serial.printf("%02X ", b);
    last = millis();
  }

  // newline gap so it’s readable
  if (millis() - last > 50) {
    Serial.println();
    last = millis();
  }

  delay(1);
}

Post up what you find.

HTH
GL :slight_smile: PJ :v:

  1. The code is printing binary as if it’s text

I know this is confusing, but the manufacturer recommended this. I also was very skeptical, thus initially I also thought of printing out raw hex. This resulted in: 4F 4E 0D 0A 52 61 6E 67 65 20 33 35 33 36 0D 0A. Now that we know the hex, I converted this to binary which results in:

ON
Range 3536

Therefore, printing binary as text is intended by the manufacturer.

  1. The ā€œHardwareSerial mySerial(0)ā€ is probably the wrong UART

Wiki for esp32c6 suggests two ways to use Hardware serial: first using the HardwareSerial mySerial(0); and second using the Serial1.begin(115200, SERIAL_8N1, RX_PIN, TX_PIN);

I tried both, weirdly enough, only HardwareSerial mySerial(0); seems to be able to read any data from the sensor. In other words, Serial1 just isn’t able to read any data.

This is very frustrating, as far as I understood, both of the code should be achieve the same thing right? Additionally, I didn’t even touch the wiring between the different hardware serial implementations.

You send the init command once… then maybe the sensor stops because it expects ACK / continuous polling / or it went into a different mode

I’m currently experimenting with this, trying different modes etc etc. Though my initial observations are still there:

  • Software serial, although can’t be converted to proper text, receives data continuously even if the ā€˜start streaming’ command is sent once.
  • Hardware serial using HardwareSerial.h receives the data that could be converted to proper text, but only does this once. I tried sending the ā€œstart streamingā€ command again, but still no data is being received.

C) Buffer too small

I don’t know how to increase the buffer size for HardwareSerial.h library.


Finally, I tried the code you suggested but with no luck, it just prints newlines. Additionally, I also sweared at the circuit :joy: and replaced the sensor with new one but still no luck.

Will keep at it and keep you guys posted… tysm for the help @PJ_Glasso

1 Like