Skip to content

Slot 2/3 anticollision failures: full-day measurements, cross-slot UID bleed, and four candidate causes in the driver #26

Description

@Bartyx

Follow-up to #22 ("Anticol errors"), which describes the same symptom on my machine — OpenRFID cannot read a right-hand slot while the stock Snapmaker reader handles the same spool fine. That issue has had no data attached since it was opened, so here is a measured day from one U1, plus a read of the driver source.

Disclosure: this report was written by Claude (Anthropic's AI), working from my printer's openrfid.log, live Moonraker queries and a checkout of this repository. I ran the tests on my own machine and I am posting this; the analysis and code references are the model's and I have not independently verified every claim. Treat the code section as a hypothesis to check, not as a finding. Happy to re-run anything.

Environment

  • Snapmaker U1, extended firmware, Klipper software_version: 1.5.2.13_20260722102206
  • OpenRFID as shipped by the firmware, i.e. this repo at 1a6f605 (pulled in by paxx12-snapmaker-u1/SnapmakerU1-Extended-Firmware@5f52c61)
  • RFID Detection System: OpenRFID (force generic vendor), later plain OpenRFID; also tested against the stock Snapmaker setting
  • Tags: blank NTAG213 (CC = E1 10 12 00) and NTAG215 (CC = E1 10 3E 00) stickers. No vendor tags on any spool.
  • Tag placement was not changed at any point during the measurements below.

Slot/reader/coil mapping, from examples/u1.cfg:

Slot Reader Coil
0 left upper
1 left lower
2 right upper
3 right lower

Evidence

1. The two readers are not comparable

One day, every scan attempt in openrfid.log:

Slot Reader + coil Read Missed Success
0 left + upper 12 1 92%
1 left + lower 14 4 78%
2 right + upper 10 61 14%
3 right + lower 14 53 21%

Scan errors the same day: left 113, right 2338 — a 20× difference between two coils driven by the same code.

2. The failure is at anticollision, not at wake-up

right   anticoll err -25   2146
right   wakeup err -22       83
right   anticoll err -22      52
left    wakeup err -20        41
left    anticoll err -21      37
right   anticoll err -21      30
left    select err -22        17
right   wakeup err -25        15

On the right reader WUPA succeeds and the anticollision cascade fails, 2146 times. That is a tag that is powered and answering ATQA but whose bit-level responses are not being decoded reliably.

The distinction is visible in the log: when a holder is genuinely empty, the failure is wakeup err -20 (the left-reader rows above, recorded with no spool mounted). A present-but-unreadable tag gives anticoll err. The two are not the same condition.

3. The tag is provably present while this happens

Tag lost before reading appears 52 times in one day — i.e. scan() succeeded once, the session was restarted, and the second scan() found nothing:

12:12:43  Tag detected:
          - TagType: Mifare Ultralight / NTAG
          - UID: 04:42:42:8A:48:68:80
          - ATQA: 44:00   BCC: 8C:2A   SAK: 04:00
12:12:43  ERROR rfid_reader:rfid_reader_right_side: anticoll err: -25
12:12:43  WARNING root: Tag lost before reading

So "no tag detected" on these slots does not mean "no tag on the holder".

4. The same physical tag is reported on two slots

Six times, slots 2 and 3 returned the identical UID within a second or two of each other. 0442428A486880 is physically on slot 3 only; slot 2 held a different spool with a different tag, which never appears in the log at all:

10:40:40 slot 3  ->  10:40:41 slot 2   UID 0442428A486880
10:41:26 slot 3  ->  10:41:27 slot 2   UID 0442428A486880
10:46:34 slot 3  ->  10:46:36 slot 2   UID 0442428A486880
10:47:09 slot 2  ->  10:47:10 slot 3   UID 0442428A486880
10:47:27 slot 3  ->  10:47:28 slot 2   UID 0442428A486880
10:47:54 slot 3  ->  10:47:57 slot 2   UID 0442428A486880

The left reader performs the same upper/lower GPIO switch in the same burst and correctly returns two different UIDs, so the switching logic itself works:

10:46:33  Successfully read tag with UID E0454F3F on reader slot_0_reader
10:46:09  Detected tag with UID 049899B5CE2A81 on reader slot_1_reader

This matches reports in paxx12-snapmaker-u1/SnapmakerU1-Extended-Firmware#232 — bdwilson ("if I try to load 3 while 4 has a sensor on it, even if there is no filament loaded into 4, 3 will never show") and tropisch ("the printer detects the same Filament in spool 2 as in spool 1").

Downstream this is worse than a missed read: two slots resolve to one spool, so filament usage gets attributed to the wrong spool.

5. A power cycle does not reliably fix it

I ran three controlled series of single-channel FILAMENT_DT_UPDATE CHANNEL=<n> calls. The first had a flaw — a 4 s gap between channels, which is shorter than a 20-retry scan (~7 s), so the retry loops interleaved. Discard it. The other two:

Run A — 15 s spacing, verified zero overlap between channels:

slot 2: 0 read / 14
slot 3: 0 read / 14

Run B — same spacing, started 90 s after a full power cycle (OpenRFID start at 12:50:55, first read 12:52:13):

slot 2: 0 read / 20    <- fails from the very first attempt after boot
slot 3: 2 read / 21    <- 12:57:02 on the 17th retry, 12:59:29 on the 4th

So the "works until it stops, power cycle clears it" pattern reported elsewhere did not hold here: slot 2 failed on the first read after boot. A restart is not a reliable workaround.

What I ruled out

  • Tag placement — unchanged throughout; the same spool and tag read on the left reader and fail on the right.
  • Tag type — NTAG213 and NTAG215 both affected; both read fine on the left reader.
  • Vendor tag interference — no vendor tags on these spools, the stickers are blank.
  • Concurrent channel scans — Run A and Run B are single-channel with verified spacing.
  • Empty holdersTag lost before reading and the occasional full read prove a tag is in the field.

Candidate causes in the driver

These come from reading this repository at 1a6f605. I have not tested any of them; they are offered as places to look.

a) hard_reset() is never called at runtime

src/reader/fm175xx/rfid.py:41    self.hard_reset()   # only call site, in __init__
src/reader/fm175xx/rfid.py:43    def hard_reset(self):

start_session() (rfid.py:49) only does the soft __reader_a_init() register write plus carrier-on; the reset pin is never touched again. There is no path that hard-resets the chip after repeated failures — only reconstructing the object does, which is why a service or power cycle is the only known recovery.

paxx12 described the symptom as "a slot can stop reading tags until a power cycle" in SnapmakerU1-Extended-Firmware#232. A retry policy that calls hard_reset() after N consecutive failed scans on a reader would give the runtime a recovery path it currently lacks.

b) RxGain is hard-coded one step below maximum

__reader_a_init(), src/reader/fm175xx/rfid.py:303-306:

self.__register_write(Constants.FM175XX_GSN_ON_REG, 0xF0)        # CWGsN  = 15 (max)
self.__register_write(Constants.FM175XX_CW_GSP_REG, 0x3F)        # CWGsP  = 63 (max)
self.__register_write(Constants.FM175XX_RF_CFG_REG, 0x60)        # RxGain = 0b110 = 43 dB
self.__register_write(Constants.FM175XX_RX_THRESHOLD_REG, 0x84)  # MinLevel 8, CollLevel 4

FM175XX_RF_CFG_REG is 0x26 (RFCfgReg); bits 6:4 are RxGain. 0x60 selects 43 dB, while 0x70 selects the maximum 48 dB. The transmit side is already at maximum on both registers, so receive gain is the only setting left below the ceiling.

That is specifically interesting for this failure mode: ATQA is a short, robust exchange and it succeeds; the anticollision cascade is longer and far more sensitive to receive SNR, and it is what fails. 5 dB of receiver gain is exactly the margin that separates the two.

c) RxThresholdReg is at the chip default

Same block, 0x84MinLevel = 8, CollLevel = 4. MinLevel gates how weak a subcarrier is still decoded and CollLevel gates collision detection during anticollision. Both are left at the reset default, and both are directly on the path that is failing.

d) The RF field is cycled twice per successful read

src/runtime.py:97-100:

reader.start_session()     # carrier on
scan_result = reader.scan()
reader.end_session()       # carrier off

then src/runtime.py:160-169 for the same tag:

reader.start_session()     # carrier on again
if reader.scan() == None:
    logging.warning("Tag lost before reading")

Every successful read therefore requires the tag to be activated twice, with the field switched off in between. For a well-coupled tag this is free; for a marginal one it doubles the chance of failure, and it is the direct source of all 52 Tag lost before reading events above. Holding one session open across scan and read, or retrying the second activation before giving up, would remove that.

Relatedly, the only time.sleep() calls in the whole driver are inside hard_reset(). start_session() enables the carrier and scan() sends WUPA immediately, with no guard time for the tag to power up.

What would help me most

  1. Is there a reason RxGain is 0x60 rather than 0x70 — was 0x70 tried and found worse? If not, I am happy to run my series with 0x70 and post the before/after numbers, since I have a machine that fails reproducibly.
  2. Would you accept a PR adding a hard_reset() after N consecutive scan failures, and/or making the RFCfgReg / RxThresholdReg values configurable per [fm175xx] section?
  3. Since the stock Snapmaker reader handles these same slots (as you noted in Anticol errors #22), is its register initialisation known anywhere? A diff against it would settle b) and c) quickly.

I can provide the full openrfid.log (roughly 900 kB for the day) and re-run any test on request.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions