-
Notifications
You must be signed in to change notification settings - Fork 236
nfc_test_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).
[mmu_nfc_reader gateN]
debug: 3 # 3 = probe watchdog + parse steps. 4 = full trace (slow, only for a failure)
MMU_TEST_CONFIG log_level=2Watch: 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.
| 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.
| 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.
| 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 |
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 |
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 # ×5Interpretation:
- 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.
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 alive — probe_stop restores TX bits unconditionally on purpose |
| 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.
(\_/)
( *,*)
(")_(") Happy Hare ReadyCopyright (C) 2022-2026 Paul Morgan
*** NEW V4 DOC IS HERE ***
1. Introduction
2. Installation
3. Essential Configuration
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
- State Persistence
- Statistics and Counters
- Tool and Gate Maps
- Filament Bypass
- Runout/Clog Detection
- Consumption Counters
- Synchronized Gear/Extruder
11. Quick References
12. Troubleshooting
13. FAQ
14. MCU Board Reference 🆕
15. Change Log
Happy Hare Discord