Skip to content

nfc_test_plan

moggieuk edited this page Jul 31, 2026 · 1 revision

NFC/RFID reader validation plan

Companion to nfc_driver_matrix.md. Turns the matrix into something you can run against real hardware. Two tracks, because the failure modes differ:

  • Track S — shared reader: one reader, tags presented by hand. Homing accuracy irrelevant; what matters is Spoolman resolution and that a missing reader degrades gracefully.
  • Track G — per-gate reader: reader per lane, used as a homing endstop. Everything in Track S plus homing behaviour, bus scaling and per-tick cost.

Run B (bench) first regardless. Track G additionally runs H (homing).

Speed note: gear_homing_speed defaults to 150 mm/s (mmu_unit_parameters.py:196), not the 100 mm/s the manager comment uses. Expected overshoot at default speed: ~3 mm (PN532), ~6 mm (RC522), ~15 mm (PN7160 no-IRQ), ~15–22 mm (PN5180).


0. Instrumentation (set once)

[mmu_nfc_reader gateN]
debug: 3          # 3 = probe watchdog + parse steps. 4 = full trace (slow, only for a failure)
MMU_TEST_CONFIG log_level=2

Watch: tail -f ~/printer_data/logs/klippy.log | grep -E 'mmu_nfc|rfid|NFC'

Status to sample: printer["mmu_nfc_reader gateN"].alive / .present / .last_uid / .reader_type / .interface

Commands used throughout: MMU_RFID_INIT|READ|RELEASE [NAME=] (driver level), MMU_NFC (manager level), MMU_NFC_SCAN, MMU_PRELOAD.


B. Bench bring-up — run for every reader, before any motion

ID Do Pass A failure means
B1 Klippy restart, read the log No config errors; each reader logs init: gate=N Wiring/bus validation in reader_factory rejected something — the message names the section and the option
B2 MMU_NFC Every reader listed, alive true Chip not answering: power, bus, address, CS
B3 MMU_RFID_READ NAME=x with no tag no tag detected, returns promptly A long hang here is the blocking-read problem the probe exists to avoid; check transceive_delay / pn5180_rf_timeout
B4 MMU_RFID_READ NAME=x with a tag on the antenna UID=..., stable across 10 repeats Intermittent = marginal RF, bus speed, or (software I2C) missing pull-ups
B5 MMU_NFC ... READ=1 DEEP=1 on one tag of each brand you own Log shows deep read uid=... strategy=<ntag_type2/mifare_classic/iso15693_type5> then parsed tag_format=... strategy=uid_only → tag type not classifiable. all MIFARE key attempts failed → wrong vendor or missing pycryptodome (the log says which)
B6 Pull the tag, MMU_RFID_READ, replace, read again Clean no tag then a fresh UID A sticky UID means release/clear is broken
B7 Note the reader's probe capability from the init log RC522/PN532: probe path. PN7160: init OK (tag homing probe available) PN7160 saying unavailable - no irq_pin = you are on the slow shim; expected if you didn't wire IRQ
B8 Chip-specific trap from §X

B7 is the single most important line to read if you intend to home to tags.


S. Shared-reader track

ID Do Pass
S1 Present a tag, wait ≥1 s (poll is NFC_CHECK_INTERVAL = 1.0 s) UID picked up without any command
S2 Leave the tag sitting on the reader 30 s Spoolman is not hammered — one lookup, then the 5 s NFC_TAG_HOLD_TIME cooldown + UID dedupe hold
S3 Swap to a second tag New UID resolves promptly, not blocked by the previous hold
S4 MMU_NFC SHARED=1 REGISTER=1 on an unknown tag with nfc_deep_read=1 + auto-create on Spool created from parsed metadata; report-only for shared (no gate map change)
S5 MMU_NFC SHARED=1 ENABLE=0, present a tag Nothing read at all. ENABLE=1 re-inits
S6 Start a print, present a tag Reader inactive during print (the active flag), no lookups
S7 UART only: unplug the adapter, restart klippy Klippy starts; reader reports not-alive. Replug + MMU_RFID_INIT recovers
S8 UART only: confirm the port is a /dev/serial/by-id/ path No not a /dev/serial/by-id/ path warning in the log

S7 is the shared-reader-specific value claim: a dead reader must not be able to stop the printer from starting.


G. Per-gate track

ID Do Pass
G1 MMU_NFC with every gate loaded Correct UID attributed to the correct gate — no off-by-one, no cross-talk
G2 Move one tag between two gates' readers UID follows the tag; the vacated gate reads empty. Catches a shared-bus/address mix-up that G1 can miss
G3 MMU_NFC GATES=0,1,2,3 READ=1 All gates answer in one command without a stall or a TTC
G4 MMU_NFC GATE=n REGISTER=1 Gate map updated for that gate (per-gate does assign, unlike shared)
G5 Read every gate 20× in a loop Zero read failures. Intermittents here are bus contention, not RF
G6 Software I2C only: same test with all readers configured Any silent cross-bus collision shows as intermittent failures on G5/G2 — reader_factory catches pin/address collisions at config time, but not weak pull-ups
G7 PN7160 multi-drop: 2–4 readers at 0x28–0x2B on one bus Each answers at its own address; G2 confirms no aliasing

H. Homing track (per-gate only)

Prereq: gate endstop must be a real MCU switch. If the log says is not a real MCU switch - plain homing or missing endstop ... - plain homing, H-series is inapplicable — the reader is not compounded into the home at all.

ID Do Pass Notes
H1 MMU_NFC_SCAN GATE=n with the tag inside the jog window Tag found, read, filament re-parked at the gate datum Requires nfc_gate_jog_scan_window set (neg,pos)
H2 MMU_NFC_SCAN with the tag already on the reader No motion at all — the pre-read short-circuits Cheapest correctness check of the whole path
H3 MMU_NFC_SCAN with no tag on the spool Sweeps the window, reports not found, re-parks once — filament does not walk backward on repeat invocations Run it 5× and measure the parked position; drift here is the bug the "ONE re-park off a datum" comment exists to prevent
H4 MMU_PRELOAD on a tagged spool Homed and tag read (they are separate outcomes). Ends parked off the gate switch
H5 Repeat H4 20× tag not readable after homing (debug log) appears rarely if ever Frequent = the tag is coasting past the antenna in the deceleration ramp; reduce gear_homing_speed or reposition the reader
H6 Speed sweep — see below Discriminates poll latency from RF geometry The key test
H7 Run H4 in a loop 30× while the extruder heats / a print runs No Timer Too Close Shim drivers (PN5180, PN7160-no-IRQ) are the ones at risk; this is the bench check the endstop's PROTOTYPE header asks for
H8 Immediately after an H4 trigger, MMU_RFID_READ Succeeds Validates the probe→read handoff. RC522 specifically: its probe leaves tags in READY and the read uses REQA, so a broken probe_stop field-drop fails every post-move read
H9 Disable the gate reader, then MMU_PRELOAD Refuses up front with the "reader is disabled" error — does not run the move full length and report no trigger

H6 — the speed sweep

The one measurement that tells you whether your chip choice matters. Run the same homing move at three speeds and record where it triggers:

MMU_TEST_CONFIG UNIT=0 gear_homing_speed=50
MMU_NFC_SCAN GATE=0     # ×5, record the chased distance from the log
MMU_TEST_CONFIG UNIT=0 gear_homing_speed=100
MMU_NFC_SCAN GATE=0     # ×5
MMU_TEST_CONFIG UNIT=0 gear_homing_speed=150
MMU_NFC_SCAN GATE=0     # ×5

Interpretation:

  • Distance grows roughly linearly with speed → poll latency dominates. Implied latency = Δdistance ÷ Δspeed. Compare against §C of the matrix: ~20 ms means the probe path is working; ~100 ms+ means you are on the shim (check B7).
  • Distance roughly constant across speeds → RF coupling range and the deceleration ramp dominate. Your chip choice is not the limiting factor and upgrading from RC522 to PN532 will buy nothing.
  • Spread within one speed exceeds the shift between speeds → tag/antenna geometry is the problem. Fix the mechanical mount before touching driver config.

Record the within-speed spread too; that is your real homing repeatability figure and nothing in the code can improve it.


X. Chip-specific traps

One test each — the thing most likely to be wrong for that chip.

Chip Trap Test
PN532 i2c Only one per bus (0x24 fixed) Configure two on one hardware bus → must be rejected at config time, not produce intermittent reads
PN532 i2c (software) Missing pull-ups; no clock stretching or bus timeout, so a wedged bus returns bad data rather than raising G5 loop ×100. Any garbage UID (not just a miss) points here
PN532 uart Mode pads must be HSU (SEL0=0, SEL1=1); one reader per tty B2 fails → check pads before wiring. Two on one port must be rejected
PN532 spi UNTESTED path. Two specifics to scope: the ACK check compares 6 raw bytes with no status prefix, and every spi_transfer response is indexed [1:] Log must show the UNTESTED against real hardware warning; treat all of B and H as new-code validation, not config validation
PN7160 No irq_pin → silently correct but 5× slower homing B7 log line; then H6 to confirm the latency you actually get
PN7160 Detection tick ends in _wait_for_irq_release(), bounded 50 ms — right at the drip budget H7 (TTC loop) is non-optional for this chip
PN5180 busy_pin + reset_pin are required, no defaults Omit one → config error naming it. Then confirm BUSY actually transitions (a stuck-high BUSY shows as busy_timeout in the log)
PN5180 pn5180_tag_format: auto walks both protocols per read, doubling miss cost Time B3 with auto vs pinned to ntag/iso15693; pin it if you know your tags
RC522 Probe leaves tags in READY; post-move read uses REQA H8 — this fails 100% of the time if the field-drop in probe_stop is broken, and 0% if it works. No ambiguity
RC522 is_alive() reports dead if the TX bits are left clear After any H-series failure, MMU_NFC must still show aliveprobe_stop restores TX bits unconditionally on purpose

Acceptance summary

Setup Must pass Should pass
Shared reader B1–B6, S1–S6 (+S7–S8 if UART) B7 n/a
Per-gate, no homing B1–B6, G1–G5 (+G6/G7 by topology)
Per-gate, homing to tag all of the above, plus B7, H1–H5, H7–H9 H6 characterised and recorded

Homing-off-a-tag is not implementable on this code (see matrix §F) — there is nothing to test yet. When it lands, the first test is absence hysteresis: confirm a single missed exchange does not trigger, on a stationary tag, 100 consecutive ticks.

*** NEW V4 DOC IS HERE ***

 1. Introduction
 2. Installation
 3. Essential Configuration
 4. Calibration
 5. Operation

-- YOUR MMU IS READY TO PLAY WITH --

 6. Slicer-MMU Setup

-- NOW YOU ARE READY TO PRINT! --

 7. Tuning
 8. Optional Feature Setup
 9. Advanced Configuration
 10. Advanced Concepts
11. Quick References

12. Troubleshooting
13. FAQ
14. MCU Board Reference 🆕
15. Change Log
Happy Hare Discord

Clone this wiki locally