UHF RFID Reader Modules
This is a MicroPython library for UHF RFID reader modules in the Tenhanyun/RoyalRay protocol families, controlled over UART. It implements the binary command/response protocol described in the "UHF RFID Reader Series User Manual" - a single protocol that, as far as can be determined, is shared across what's really one underlying OEM design sold under multiple brands and part numbers: Tenhanyun's TY928↗ (opens in a new tab), and RoyalRay's RRUx2828M family↗ (opens in a new tab) (RRU72828M/RRU52828M/RRU32828M, for the Impinj E710/E510/E310 reader chips respectively), and likely other modules/readers in the same series with more antenna ports (e.g. RRU2881, RRU9816, RRUx881, RRUx199).
This driver was written and tested against a TY928 specifically - it should work with little-to-no changes against other modules in the family (same command set, same framing), but expect treacherous untrodden paths (see setup_antenna() for a 4/8/16-port-only example). PRs welcome for extending support / functionality.
To use this library, copy uhf_reader.py into your MicroPython project and instantiate a UHFReader with a machine.UART object. The examples folder has a generic communication check and a tag EPC-write example.
Features:
- ✅ Communicate over UART using the shared frame protocol (framing + CRC16)
- ✅ Inventory (discover) EPC C1G2 tags in range, with per-tag RSSI
- ✅ Filter inventory to a single known tag - the basis of the warmer/colder use case
- ✅ Read / write tag memory (reserved, EPC, TID and user banks)
- ✅ Write a new EPC number to a tag
- ✅ Configure RF power, RF link profile, frequency band, inventory time, baud rate and device address
- ✅ Control the buzzer/LED output and GPIO pins
- ✅ Read reader info and serial number (handy as a communication self-check)
- ✅ Streaming "fast inventory" mode, extended reader parameters, per-antenna RF power and region readback
- 🚧 Everything else in the protocol - tag kill/protection, ISO18000-6B, the memory buffer commands, EM4325 sensor-tag support, and more - is present as a stub that raises
NotImplementedError. See the bottom of uhf_reader.py↗ (opens in a new tab) for the full list, with the relevant manual section/command code noted against each.
Usage
from machine import UART
from uhf_reader import UHFReader
uart = UART(1, baudrate=115200, tx=17, rx=16, timeout=50, timeout_char=10)
reader = UHFReader(uart)
print(reader.get_reader_info())
# Optionally set the frequency band and channel range for your jurisdiction
# Should only need to be done once
# reader.set_frequency("australia", min_channel=0, max_channel=9)
for tag in reader.inventory():
print(tag["epc"].hex(), tag["rssi"])
See the examples folder for a basic communication check and an EPC-write example, and see uhf_reader.py for the class definition and all of the available methods.
Notes
- Set the correct frequency band and channel range for your jurisdiction with
set_frequency()before keying up RF at any meaningful power - see the docstring andFREQUENCY_BANDSinuhf_reader.py. This driver does not validate RF-legality for you. - Always have an antenna connected to the IPEX connector before transmitting - running the PA into an open circuit for extended periods risks damaging the module.
- Factory-default UART settings are 57600bps, 8N1 - but
set_baud_rate()persists across power-down, so a module may already be running at a different rate (115200bps for the module this repo's examples target; confirm yours withping()before assuming the factory default). The protocol requires the gap between consecutive bytes to stay under 15ms - if your port'sUARTconstructor supports atimeout_charargument, set it comfortably below that. - Allow ~140ms after power-up/
ENbefore the module will respond to commands.