Back to engineering archive

Record 017 / Connected systems

ESP32 UHF RFID inventory interface

An ESP32 exchanges inventory frames with a YRM100/YRM1001 UHF RFID reader over UART.

Firmware module
ESP32UHF RFIDUARTProtocol handling

Firmware flow

Receive and inspect a reader frame

Control flow reconstructed from the selected readFrame() implementation.

Timeouts, oversized payloads and an invalid trailer stop reception. A checksum mismatch only emits a warning before the routine returns the command and payload length.

This explains a source variant, not a verified RFID read. Checksum warnings do not reject a frame, and the separate EPC scanner does not validate CRC.

Read the implementation

code.txt — framed UART receiver.

static bool readFrame(uint8_t &outCmd, uint8_t *buf, uint16_t &outLen, uint16_t timeoutMs = 300) {
  // Seek 0xBB
  uint32_t t0 = millis();
  while (millis() - t0 < timeoutMs) {
    if (Reader.available()) {
      if (Reader.read() == 0xBB) break;
    }
  }
  if (millis() - t0 >= timeoutMs) return false;

  uint8_t addr, cmd, lh, ll;
  if (!readByteWait(addr, timeoutMs)) return false;
  if (!readByteWait(cmd,  timeoutMs)) return false;
  if (!readByteWait(lh,   timeoutMs)) return false;
  if (!readByteWait(ll,   timeoutMs)) return false;

  uint16_t len = (uint16_t(lh) << 8) | ll;
  if (len > 512) return false; // sanity guard for our fixed buffer

  // Read payload
  for (uint16_t i = 0; i < len; i++) {
    if (!readByteWait(buf[i], timeoutMs)) return false;
  }

  // CS + tail
  uint8_t csh, csl, tail;
  if (!readByteWait(csh, timeoutMs)) return false;
  if (!readByteWait(csl, timeoutMs)) return false;
  if (!readByteWait(tail, timeoutMs)) return false;
  if (tail != 0x7E) return false;

  // (Optional) verify checksum
  uint32_t sum = addr + cmd + lh + ll;
  for (uint16_t i = 0; i < len; i++) sum += buf[i];
  uint16_t cs = sum & 0xFFFF;
  uint16_t got = (uint16_t(csh) << 8) | csl;
  if (cs != got) {
    Serial.print(F("[WARN] Checksum mismatch, calc=0x"));
    Serial.print(cs, HEX);
    Serial.print(F(" got=0x"));
    Serial.println(got, HEX);
  }

  outCmd = cmd;
  outLen = len;
  return true;
ActionLook for the 0xBB header
CheckAddress, command and length received; payload length at most 512?
CheckPayload and trailer received, ending in 0x7E?
CheckCalculated checksum matches the received value?
ResultReturn false
ActionPrint a checksum warning
ResultPublish command and length; return true

Technical notes

The reader protocol

The matched source uses ESP32 UART1 with GPIO17 for transmit and GPIO16 for receive. Requests use a 0xBB header, command and length fields, a checksum and a 0x7E trailer. This is a UHF RFID interface, correcting the earlier NFC label.

Bounded frame reception

The receiver waits for each byte, rejects a payload length above 512 and checks the trailer. It reports a checksum mismatch but still returns the frame as received; that diagnostic is not an integrity guarantee.

Inventory inspection

The main loop requests inventory about once per second and also drains unsolicited frames. The EPC scanner prints candidate identifiers from bounded payload positions and skips CRC bytes; reader compatibility and successful tag reads were not tested in this review.

Engineering archiveArchive record

Project enquiries

Discuss your project.

Tell us what you’re developing and where you need engineering support.

Discuss your project