{
  "id": "howmanyoliversarethere/micropython-uhf-module",
  "name": "micropython-uhf-module",
  "prettyName": "micropython-uhf-module",
  "description": "A MicroPython driver for the Tenhanyun TY928 UHF Embedded Module",
  "version": "",
  "author": "howmanyoliversarethere",
  "license": "MIT",
  "tags": [],
  "status": "VALID",
  "official": false,
  "source": "https://github.com/howmanyoliversarethere/micropython-uhf-module",
  "updatedAt": "2026-09-27T07:00:19.852Z",
  "page": "https://checkmim.com/packages/howmanyoliversarethere+micropython-uhf-module",
  "createdAt": "2026-09-26T13:27:01.039Z",
  "submittedBy": "oliverr",
  "install": {
    "mpremote": "mpremote mip install github:howmanyoliversarethere/micropython-uhf-module",
    "mip": "import mip; mip.install(\"github:howmanyoliversarethere/micropython-uhf-module\")"
  },
  "readme": "# UHF RFID Reader Modules\n\nThis 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](https://www.tenhanyun.com), and RoyalRay's [RRUx2828M family](https://www.rr-rfid.com/embedded/rrux2828m.html) (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).\n\n_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.\n\nTo 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.\n\nFeatures:\n\n- ✅ Communicate over UART using the shared frame protocol (framing + CRC16)\n- ✅ Inventory (discover) EPC C1G2 tags in range, with per-tag RSSI\n- ✅ Filter inventory to a single known tag - the basis of the warmer/colder use case\n- ✅ Read / write tag memory (reserved, EPC, TID and user banks)\n- ✅ Write a new EPC number to a tag\n- ✅ Configure RF power, RF link profile, frequency band, inventory time, baud rate and device address\n- ✅ Control the buzzer/LED output and GPIO pins\n- ✅ Read reader info and serial number (handy as a communication self-check)\n- ✅ Streaming \"fast inventory\" mode, extended reader parameters, per-antenna RF power and region readback\n- 🚧 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](uhf_reader.py) for the full list, with the relevant manual section/command code noted against each.\n\n## Usage\n\n```python\nfrom machine import UART\nfrom uhf_reader import UHFReader\n\nuart = UART(1, baudrate=115200, tx=17, rx=16, timeout=50, timeout_char=10)\nreader = UHFReader(uart)\n\nprint(reader.get_reader_info())\n\n# Optionally set the frequency band and channel range for your jurisdiction\n# Should only need to be done once\n# reader.set_frequency(\"australia\", min_channel=0, max_channel=9)\n\nfor tag in reader.inventory():\n    print(tag[\"epc\"].hex(), tag[\"rssi\"])\n```\n\nSee 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.\n\n## Notes\n\n- **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 and `FREQUENCY_BANDS` in `uhf_reader.py`. This driver does not validate RF-legality for you.\n- **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.\n- 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 with `ping()` before assuming the factory default). The protocol requires the gap between consecutive bytes to stay under 15ms - if your port's `UART` constructor supports a `timeout_char` argument, set it comfortably below that.\n- Allow ~140ms after power-up/`EN` before the module will respond to commands.\n"
}