Skip to content

onetablespoon/readDDI

Repository files navigation

READDDI - Multi-backend Digital Dial Indicator (DDI) Remote Measurement for Mahr and Mitutoyo

Remote-triggered DDI/SPC measurements (Using USB and VCP backends)


Table of Contents


Overview

This project provides an open-source DDI measurement framework with two validated backend paths under one CLI and library API: a Mahr pure-USB FTDI path (mahr) and a Mitutoyo USB-ITN-SF VCP/COM path (mitutoyo_idc). It is designed for fixtured and CNC-adjacent workflows where touching the gauge would disturb the setup, enabling deterministic remote triggering, automation-ready capture, and raw payload visibility for both ecosystems. The architecture separates transport and protocol layers so family-specific behavior (Mahr FTDI control/bulk signaling vs. Mitutoyo VCP trigger/read flow) is handled cleanly while keeping a unified user workflow.

The repository now supports two families through one CLI flow:

  • mahr (pure USB FTDI path)
  • mitutoyo_idc (USB-ITN-SF VCP/COM path)

Project Maintenance Philosophy

This repository has two equal priorities:

  1. Simplicity of use for callers (prime_dditrigger_measurementread_measurement)
  2. Preservation of discovery context so protocol knowledge is not lost over time

What to optimize

  • Keep top-level usage simple and stable.
  • Keep internals understandable, especially in protocol-sensitive paths.
  • Keep raw observability available for diagnostics and future reverse engineering.

What not to do

  • Do not remove comments that explain why protocol steps exist.
  • Do not flatten transport/protocol logic if it hides capture-backed behavior.
  • Do not delete code simply because it looks "old" when it still documents validated device behavior.

Deprecation and knowledge-retention rule

Deprecated runtime code may be removed only after its insight is preserved in durable form:

  • README section with rationale and replacement behavior
  • reference to capture/test evidence
  • recovery notes for known failure states

If the insight is unique and not yet captured elsewhere, keep the code (or move the context into comments/docs first) before deletion.

Motivation - Why Remote DDI Triggering.

Remote triggering is a core requirement for this effort because it enables repeatable, non‑disturbing, fixtured measurement. The DDI device remains mechanically stable, the part moves independently, and the measurement event is initiated without touching the gauge. This eliminates operator‑induced variation and allows the measurement cycle to be integrated into automated or semi‑automated projects.

Traditional machinist practice typically evolved around hand‑held, operator‑driven measurement, where the user physically presses the button on the indicator. In that environment, the operator is part of the measurement system: they position the gauge, feel the contact, decide when the reading is valid, and trigger the measurement manually. Because this workflow dominated for decades, vendors optimized their software and hardware ecosystems around human presence, not automation. MarCom, SPC keyboards, wireless buttons, foot switches, and RS‑232 forwarding all reflect this assumption.

This effort operates with a differing assumption. When the gauge is rigidly fixtured and the part is moved by machine i.e., CNC or fixture, pressing the button on the DDI may not be possible, introduces mechanical disturbance, potentially creates timing issues, and of course may cause operator‑dependent variation. In these conditions, remote triggering is not optional—it is the only way to obtain stable, repeatable, automation‑ready measurements. The DDI protocol supports this electrically, but vendor software does not necessarily expose it or allow for easy integration within user projects. This effort restores that capability by controlling the DDI interface directly to issue the required measurement trigger sequence remotely.

Remote triggering is therefore treated as a primary feature of the DDI. The DDI driver, initialization sequence, and measurement routines are all designed to support deterministic, non‑contact triggering across Mahr and Mitutoyo devices. This enables projects that traditional machinist tools and vendor software do not address, and it is one of the primary motivations for the existence of this effort.

USB Backend

This effort intentionally uses different USB backends for each family because the validated driver path differs by hardware ecosystem.

  • mahr USB backend:

    • Uses direct USB control/data through PyUSB/libusb
    • Requires WinUSB binding (no COM port)
    • Best when deterministic pure-USB FTDI control is needed
  • mitutoyo_idc USB backend:

    • Uses Mitutoyo VCP driver path (ITVCP64.sys) through COM/pyserial
    • Requires a COM port from USB-ITN-SF and USB-ITPAK VCP driver installation
    • Best when using officially supported Mitutoyo driver stack

These are not interchangeable at runtime: selecting the wrong family/driver mode will fail detection.


Compatibility (Verified)

Verified combinations for this repository:

  • Mahr 1087Ri + 16 ExU 4102357 cable
  • Mitutoyo 543-700B ID-C0512NXB DDI + 06AGQ0001F USB-ITN-SF cable

Other combinations may work, but are not currently verified.

Driver / Transport Matrix

Family Example Hardware Cable Driver Mode Required Transport Used by This Repo CLI Family Notes
Mahr Mahr 1087Ri 16 ExU 4102357 (FTDI) WinUSB (via Zadig) PyUSB/libusb direct USB mahr Pure-USB path; no COM port required
Mitutoyo ID-C DDI 543-700B ID-C0512NXB 06AGQ0001F USB-ITN-SF Mitutoyo VCP (ITVCP64.sys) COM/VCP (pyserial) mitutoyo_idc Requires installed USB-ITPAK VCP driver

Mahr Platform Guide

Hardware

  • Mahr 1087Ri (verified) or compatible Mahr DDI indicator
  • 16 ExU 4102357 cable (Mahr FTDI)
  • Windows 11

One-time Setup (Mahr FTDI pure-USB path)

Install WinUSB using Zadig:

  1. Download Zadig: https://zadig.akeo.ie
  2. Plug in the MarConnect cable
  3. Select the device with:
    • VID: 0403
    • PID: 6001
    • Manufacturer: FTDI
  4. Replace the driver with WinUSB
  5. Unplug and replug the cable

This allows PyUSB to communicate directly with the Mahr FTDI chip.

Important Note About Driver Switching

After replacing the FTDI driver with WinUSB, the cable will no longer enumerate as a COM port. This is expected. Windows will continue to bind the device to WinUSB every time it is plugged in, because Zadig updates the driver association in the Windows driver store. Unplugging and replugging the cable does not revert it to the FTDI Virtual COM Port (VCP) driver.

This means:

  • Device Manager will no longer show USB Serial Port (COMx).
  • Software that depends on COM ports (e.g., MarCom, legacy SPC tools, pyserial scripts) will not detect the device.
  • The cable will appear only under Universal Serial Bus devices as a WinUSB device.

This is the correct configuration for PyUSB and for this project’s Mahr pure‑USB backend.

Please see Appendix D: Driver Switching and Recovery below if you need to revert to COM port mode.


2. Install Python dependencies

pip install pyusb

Ensure libusb-1.0.dll is placed next to ddi_init.py.


Mitutoyo ID-C Platform Guide

Hardware

  • Mitutoyo 543-700B ID-C0512NXB DDI (verified)
  • 06AGQ0001F USB-ITN-SF cable (verified)
  • Windows 11

One-time Setup (Mitutoyo VCP path)

For mitutoyo_idc mode, the USB-ITN-SF cable must be bound to the Mitutoyo VCP driver (ITVCP64.sys) so a COM port is available.

Reference documentation:

High-level procedure:

  1. Download and install USB-ITPAK from the official Mitutoyo page above.
  2. Follow the manual section "2.3 Installing the VCP Driver".
  3. Confirm Device Manager shows USB-ITN (COMx) using ITVCP64.sys.
  4. Use that COM port with this tool via --port.

Notes:

  • Do not use Zadig/WinUSB for the Mitutoyo mitutoyo_idc path.
  • Mitutoyo path uses COM/VCP (pyserial), not direct PyUSB FTDI.

Example Usage

Use the included CLI script.

Mahr:

python ddi_remote_measurement.py --family mahr

Mitutoyo ID-C (requires COM port):

python ddi_remote_measurement.py --family mitutoyo_idc --port COM5

Expected output (default mode):

2.8360

Multiple measurements:

python ddi_remote_measurement.py --family mitutoyo_idc --port COM5 --trials 3 --trial-delay 0.2

Raw outputs:

python ddi_remote_measurement.py --family mitutoyo_idc --port COM5 --raw_ascii
python ddi_remote_measurement.py --family mitutoyo_idc --port COM5 --raw_hex

Smoke Test (First-Time Validation)

Use the included manual smoke-test runner to validate core workflow and raw modes:

  • prime_ddi(...)
  • trigger_measurement(...)
  • read_measurement(...)
  • CLI --raw_ascii / --raw_hex

Mahr:

python ddi_smoke_test.py --family mahr

Mitutoyo ID-C:

python ddi_smoke_test.py --family mitutoyo_idc --port COM5

Optional:

python ddi_smoke_test.py --family mitutoyo_idc --port COM5 --trials 5 --trial-delay 0.2
python ddi_smoke_test.py --family mitutoyo_idc --port COM5 --skip-cli-check

The runner prints stage-by-stage pass/fail information and exits non-zero on failure.

Note on raw_ascii output:

  • raw_ascii means decoded ASCII text from device bytes, not necessarily alphabetic characters.
  • For these devices, measurement payloads are often ASCII digits (for example 00005440 or -00.0105).
  • raw_hex shows the same bytes in hexadecimal form so you can compare text-vs-bytes directly.

Example successful output (Mitutoyo ID-C):

=== readDDI smoke test ===
family=mitutoyo_idc  trials=3  cli_check=True

[1/4] prime_ddi baseline check
   baseline ascii: 00005440
   baseline hex:   0x30303030353434300D

[2/4] trigger/read trial checks
   trial 1: 00005440
   trial 2: 00005440
   trial 3: 00005440
   summary: nonempty=3/3, parseable=3/3

[3/4] raw mode rendering check (library path)
   raw ascii/hex rendering OK

[4/4] CLI default/raw checks
   default output: 0.0005
   raw_ascii:      00005440
   raw_hex:        0x30303030353434300D

PASS: smoke test completed.

Example successful output (Mahr):

=== readDDI smoke test ===
family=mahr  trials=3  cli_check=True

[1/4] prime_ddi baseline check
   baseline ascii: -00.0105
   baseline hex:   0x2D30302E303130350D

[2/4] trigger/read trial checks
   trial 1: -00.0105
   trial 2: -00.0105
   trial 3: -00.0105
   summary: nonempty=3/3, parseable=3/3

[3/4] raw mode rendering check (library path)
   raw ascii/hex rendering OK

[4/4] CLI default/raw checks
   default output: -0.0105
   raw_ascii:      -00.0105
   raw_hex:        0x2D30302E303130350D

PASS: smoke test completed.

Using the Library in Your Own Scripts

Mahr (pure USB FTDI):

from ddi_init import prime_ddi, trigger_measurement, read_measurement

dev, ep_in, baseline = prime_ddi("mahr")
print("Baseline raw:", baseline.decode("ascii", errors="replace").strip())

for _ in range(5):
   trigger_measurement(dev)
   m = read_measurement(ep_in)
   print("Measurement raw:", m.decode("ascii", errors="replace").strip())

Mitutoyo ID-C (VCP/COM):

from ddi_init import prime_ddi, trigger_measurement, read_measurement

dev, ep_in, baseline = prime_ddi("mitutoyo_idc", mitutoyo_com_port="COM5")
print("Baseline raw:", baseline.decode("ascii", errors="replace").strip())

for _ in range(5):
   trigger_measurement(dev)
   m = read_measurement(ep_in)
   print("Measurement raw:", m.decode("ascii", errors="replace").strip())

Mitutoyo notes:

  • Use mitutoyo_com_port with the exact USB-ITN (COMx) value from Device Manager.
  • mitutoyo_idc mode requires Mitutoyo VCP driver ITVCP64.sys (not Zadig/WinUSB).
  • If mitutoyo_com_port is omitted, the module default MITUTOYO_COM_PORT is used.

These two examples cover the common library workflows.


Code Map (Where to Look)

Use this map when onboarding, debugging, or proposing changes.

Runtime entry points (stable caller workflow)

  • ddi_init.py

    • prime_ddi(...): one-time session setup + baseline read
    • trigger_measurement(...): family-aware remote trigger
    • read_measurement(...): family-aware raw measurement read
  • ddi_remote_measurement.py

    • user-facing CLI wrapper around the stable workflow
    • retry policy, output modes, and lightweight parsing for automation

Discovery and reverse-engineering tools

  • mitutoyo_command_probe.py
    • exploratory command probing for Mitutoyo VCP path
    • tiered scan mode, write-fault handling, JSON evidence export

Evidence and historical context

  • captures/
    • packet captures and decoded traces used to validate behavior
  • Appendix sections in this README
    • capture interpretation, command findings, and recovery behavior

Change safety guidance

  • If a change affects trigger/init timing or token behavior, update both:
    1. inline "why this is here" comments in code
    2. relevant README appendix/policy sections
  • Preserve raw observability paths (raw_ascii, raw_hex, probe JSON) unless a replacement is documented.

Architecture

The driver is organized into four layers:


Transport Layer

  • Mahr backend: USB discovery + interface claim on Mahr FTDI device
  • Mitutoyo backend: COM/VCP port open via Mitutoyo driver

Protocol Layer

Mahr Initialization (mahr_init())

The Mahr 1087 Ri requires a precise FTDI UART configuration:

  • SetData 7E1
  • RTS/DTR high
  • Flow control off
  • Intermediate baud
  • RTS/DTR off
  • 5× Reset/GetModemStat (SPC enable handshake)
  • RTS/DTR high
  • Final baud 19200
  • SetData 7E2
  • Idle: DTR low

This sequence was reverse‑engineered from USB captures of MarCom.

Mahr Protocol Details

FTDI Status Header

Every bulk packet begins with:

byte0: modem status
byte1: line status

For Mahr:

11 60
ASCII Format
[sign][digits].[digits]\r

Example:

+02.7725\r
Timing
  • Trigger → measurement: ~40–50 ms
  • FTDI idle packets: ~32 ms interval
Why DTR Works

The Mahr gauge interprets a DTR rising edge as a remote measurement request after the FTDI UART engine is configured correctly.

Mahr FTDI Flowchart
                   +---------------------+
                   |  USB Device Found   |
                   +----------+----------+
                              |
                              v
                   +----------+----------+
                   |  Claim Interface 0  |
                   +----------+----------+
                              |
                              v
                   +----------+----------+
                   |   FTDI Init Start   |
                   +----------+----------+
                              |
        -------------------------------------------------
        |                 |                 |           |
        v                 v                 v           v
  +-----------+    +-------------+    +-----------+  +-----------+
  | SetData   |    | Flow Ctrl   |    | SetBaud   |  | ModemCtrl |
  | (7E1)     |    | Off         |    | (09C4)    |  | (RTS/DTR) |
  +-----------+    +-------------+    +-----------+  +-----------+
                              |
                              v
                   +----------+----------+
                   |   SPC Handshake     |
                   |  (5× Reset/Stat)    |
                   +----------+----------+
                              |
                              v
                   +----------+----------+
                   |  Final UART Config  |
                   |  (7E2 @ 19200)      |
                   +----------+----------+
                              |
                              v
                   +----------+----------+
                   |   Idle: DTR Low     |
                   +----------+----------+
                              |
                              v
                   +----------+----------+
                   |   Trigger (DTR ↑)   |
                   +----------+----------+
                              |
                              v
                   +----------+----------+
                   |  Measurement Ready  |
                   +---------------------+

Mitutoyo Initialization (current VCP path)

Mitutoyo ID-C uses the validated VCP trigger path in this repository (Z\r over COM).


Measurement Layer

Trigger

  • Mahr (mahr): trigger is a Mahr FTDI control-line pulse (DTR low→high rising edge).
  • Mitutoyo (mitutoyo_idc): trigger is a VCP write of Z\r (0x5A0D) to the USB-ITN-SF COM port.

Read

  • Mahr backend reads from Mahr FTDI bulk endpoint and returns:
[2‑byte FTDI status header][ASCII payload]

The driver:

  • strips the header

  • accumulates payload

  • stops at \r

  • Mitutoyo backend reads chunked VCP bytes, parses status/value fragments, and returns the raw value token (for example 00005040\r).


High‑Level Initialization (prime_ddi())

This function:

  1. Opens the selected backend (Mahr FTDI USB or Mitutoyo VCP/COM)
  2. Runs vendor‑specific init
  3. Performs a warm‑up trigger
  4. Reads and discards warm‑up output
  5. Performs up to 3 real triggers
  6. Returns the first valid measurement

Appendix A: Initialization Sequence

A.1 — Mahr FTDI

SetData (7E1)

bmRequestType: 0x40
bRequest:      0x04
wValue:        0x0207
wIndex:        0x0000

ModemCtrl (DTR=1, RTS=1)

bRequest: 0x01
wValue:   0x0101

Flow Control Off

bRequest: 0x02
wValue:   0x0000

SetBaudRate (intermediate)

bRequest: 0x03
wValue:   0x09C4

SPC Handshake (5×)

Reset:         bRequest=0x00
GetModemStat:  bRequest=0x05

Final SetBaudRate (19200)

bRequest: 0x03
wValue:   0x0271

Final SetData (7E2)

bRequest: 0x04
wValue:   0x1207

Idle (DTR low)

bRequest: 0x01
wValue:   0x0000

A.2 — Mitutoyo ID-C

Validated path in this repository for mitutoyo_idc:

  1. Open Mitutoyo VCP COM port (ITVCP64.sys) with 9600, 7E2 framing.
  2. Send trigger payload:
ASCII: "Z\r"
HEX:   5A 0D
  1. Read chunked response bytes from COM.
  2. Parse measurement token from digit chunks (for example 00005040).

Notes:

  • In USB captures, this maps to host→device control activity on EP0 via the Mitutoyo stack.
  • This backend intentionally uses the VCP path, not direct FTDI/PyUSB.

Appendix B: Trigger Sequence

B.1 Mahr FTDI

DTR low

bRequest: 0x01
wValue:   0x0100

DTR high

bRequest: 0x01
wValue:   0x0101

Measurement arrives ~40–50 ms later.

B.2 Mitutoyo (VCP)

Write to COM port: "Z\r"
Hex: 5A 0D

Typical response pattern (chunked):

  • status/header-like token (for example Q9F...)
  • digit token (for example 00005040)
  • terminator fragment (...\r)

Appendix C: Capture Interpretation

C.1 Mahr FTDI

The Mahr FTDI chip emits periodic bulk‑IN packets even when idle:

11 60

These are status headers, not measurements.

A real measurement:

STATUS: 11 60
PAYLOAD: 2b 30 32 2e 37 37 32 35 0d
ASCII: "+02.7725\r"

C.2 — Mitutoyo VCP

For the validated Mitutoyo path, captures show repeated host→device trigger-related control activity before measurements, while user-space interaction remains a COM write of Z\r through ITVCP64.sys.

This appendix is intentionally split by platform:

  • C.1 Mahr: direct FTDI USB packet semantics
  • C.2 Mitutoyo: VCP-trigger semantics with control-transfer correlation

Appendix D: Driver Switching and Recovery

D.1 Mahr 16 ExU cable driver switching

Restoring the Mahr FTDI VCP Driver (Reverting the Cable)

If you need to return the cable to COM‑port mode, you must manually reinstall the FTDI Virtual COM Port driver. Zadig does not provide an "undo" button; it replaces the driver association in the Windows driver store.

To restore the original FTDI VCP driver:

  1. Open Zadig again.
  2. Select the same device (VID 0403, PID 6001, Manufacturer FTDI).
  3. In the driver selection box, choose:
    • USB Serial (FTDI)
    • or FTDI (VCP)
    • FTDI CDM
      (The exact label depends on your FTDI driver version.)
  4. Click Replace Driver.
  5. Unplug and replug the cable.
  6. Verify in Device Manager that you now see:
    • USB Serial Converter under USB Controllers
    • USB Serial Port (COMx) under Ports (COM & LPT)

Once restored, the cable will behave like a normal FTDI serial device again and MarCom will detect it.


When Mahr FTDI Drivers Do Not Appear in Zadig

If Zadig does not show any of the FTDI VCP options:

  • USB Serial (FTDI)
  • FTDI (VCP)
  • FTDI CDM

…and the device appears only under Universal Serial Bus devices as a WinUSB Device, then Windows is no longer associating the hardware with the FTDI driver class. This happens because Zadig updates the driver binding in the Windows driver store, and Windows will continue to load WinUSB for this VID/PID until the FTDI drivers are explicitly reinstalled.

To restore the FTDI VCP driver options, use one of the following procedures:

Option A — Reinstall the FTDI CDM Driver Package (Recommended)

  1. Download the official FTDI VCP driver package from FTDI:
    https://ftdichip.com/drivers/vcp-drivers/
  2. Run the installer (CDMxxxxxx.exe).
  3. Unplug and replug the cable.
  4. Open Zadig again.
  5. The FTDI driver options should now appear in the right‑hand driver list.
  6. Select USB Serial (FTDI) (or equivalent) and click Replace Driver to restore COM‑port behavior.

Option B — Remove the WinUSB Binding and Force Windows to Re‑enumerate

  1. Open Device Manager.
  2. Expand Universal Serial Bus devices.
  3. Right‑click the WinUSB‑bound device (VID 0403 / PID 6001).
  4. Select Uninstall device.
  5. Check Delete the driver software for this device if available.
  6. Unplug and replug the cable.
  7. Windows should now prompt for a driver or automatically install the FTDI driver if present in the driver store.
  8. If it does not, install the FTDI CDM package as in Option A.

Option C — Reinstall MarCom (if the user originally had MarCom installed)

MarCom bundles FTDI's CDM drivers. Reinstalling MarCom will:

  • restore the FTDI driver association
  • repopulate the Windows driver store
  • allow Zadig to see the FTDI VCP options again

After reinstalling MarCom, unplug and replug the cable, then reopen Zadig.


Mahr Summary

  • Switching to WinUSB is required for PyUSB and this project's pure‑USB DDI driver
  • After switching to WinUSB, the cable will not revert to a COM port automatically
  • Zadig modifies the driver association persistently; unplugging does not revert it
  • To restore COM port behavior, you must manually reinstall the FTDI VCP driver using one of the methods above
  • Once restored, you can switch between WinUSB and FTDI drivers as needed

D.2 Mitutoyo (USB-ITN-SF) driver switching

Return Mitutoyo VCP device to HID-class driver behavior

If you installed the Mitutoyo VCP driver and need to return to HID-class behavior:

  1. Open Device Manager.
  2. Locate the Mitutoyo USB-ITN-SF device (VID 0FE7, PID 4001), See Details->Hardware Ids for the USB-ITN (COMx) device.
  3. Open Update driver / Browse my computer / Let me pick.
  4. Select the appropriate HID-class device option (or uninstall current device and driver package so Windows re-enumerates with default class binding).
  5. Unplug/replug and confirm the device appears under the HID class instead of COM Ports.

Important:

  • Exact device class labels can vary by installed package and Windows build.
  • Always follow the official Mitutoyo USB-ITPAK manual guidance for your release when changing driver mode.
  • Official reference: USB-ITPAK V3.0 No. 99MAM030A2, section "2.3 Installing the VCP Driver".

Mitutoyo Summary

  • mitutoyo_idc mode in this repository requires Mitutoyo VCP (ITVCP64.sys) and a COM port.
  • If COM is missing, verify the VCP driver is installed and bound.
  • If you intentionally switch away from VCP (for example to HID), this repository’s Mitutoyo VCP backend will no longer communicate until VCP is restored.

Appendix E: Mitutoyo 543-700B Command Findings

This appendix records command/response findings observed on:

  • Indicator: Mitutoyo 543-700B ID-C0512NXB
  • Cable: USB-ITN-SF (VCP path)
  • Tooling: mitutoyo_command_probe.py and 700B_test_01.pcapng

E.1 Ordering observed in capture (700B_test_01.pcapng)

Q* command traffic appears before Z trigger traffic in the captured initialization/control phase.

  • First observed Q* frame: 1526
  • First observed Z frame: 3002

This supports the interpretation that Q* is likely identification/status/config query traffic, while Z is measurement trigger/read traffic (with \r used as the command terminator for these tokens).

E.2 Confirmed command mapping from probe run

From the sequence probe (Q0A,Q01,Q02,Q3D,Q03,...,P930101,Z):

  • Q01 returned serial-number field data:

    • Example ASCII: QAF010863498712\r
    • Parsed value: serial 63498712
  • Q02 returned code-number field data:

    • Example ASCII: QAF0208543-700B\r
    • Parsed value: code no. 543-700B
  • Q3D returned model field data:

    • Example ASCII: QAF3D0BID-C0512NXB\r
    • Parsed value: model ID-C0512NXB
  • Q03 returned status/flag-like field data:

    • Example ASCII: QAF0300\r
  • Q0A returned an additional metadata/config-like block:

    • Example ASCII: QAF0A06000000250400\r
  • P930101 returned an acknowledge/parameter-like response:

    • Example ASCII: PAF930106\r
  • P8D00 was confirmed as a zero command on 543-700B:

    • Single-shot command: P8D00\r
    • Validation method: live observation of DDI display behavior during controlled fixture test
  • P920101 was observed to power off / disable active display state on 543-700B:

    • Single-shot command: P920101\r
    • Response observed: PAF920106\r
    • Validation method: live observation of DDI display behavior during controlled fixture test
    • Additional behavior: after P920101, Z trigger can return empty response until device power is restored
  • Z returned measurement-style response frames:

    • Example ASCII: Q9F75000000250400\r
    • Additional observed example: Q9F78000279454400\r (contains magnitude 2794, i.e. ~2.794 in current unit scaling)
    • Post-recovery observed example: Q9F7A000279504400\r (magnitude matches observed DDI display ~2.795)
  • Recovery finding after P920101 disable state:

    • Software recovery attempts using P940101, P930101, P8E00, P8D00 did not restore Z responses in the same powered session
    • Power-cycle of the DDI restored normal operation (Q01 query response + valid Z measurement response)

E.3.1 Known state machine (current hypothesis)

Observed behavior is consistent with this practical state model:

  • ON / Measurement-Enabled

    • Q* queries respond
    • Z returns measurement frames
  • P920101 issued

    • transitions device to OFF / Measurement-Latched-Disabled
  • OFF / Measurement-Latched-Disabled

    • Q* may still respond
    • Z may return empty
    • tested software commands (P940101, P930101, P8E00, P8D00) did not clear latch in-session
  • Power-cycle

    • restores ON / Measurement-Enabled
    • Q* and Z both return valid responses again

E.3 Command families currently inferred

  • Z\r: trigger/read measurement path
  • Q*\r: query/identify/status path
  • P*\r: parameter/action path (state-changing commands confirmed)

E.4 Safety notes

  • Unsupported tokens can produce COM write failures (Win32 error 31) on this setup.
  • Keep exploratory tests tiered and one-token-at-a-time after baseline checks.
  • Use known-stable baseline commands (Z, R, 1) to confirm communications before testing new tokens.

E.5 How mitutoyo_command_probe.py works

mitutoyo_command_probe.py opens the Mitutoyo VCP port (9600, 7E2), sends each candidate token as ASCII (by default appending \r), then captures response bytes for a short window and summarizes responses per command.

For each command token, the script records:

  • payload bytes sent (payload_hex)
  • response bytes (response_hex)
  • decoded ASCII response (response_ascii)
  • simple measurement-like flag (measurement_like)

It also supports:

  • write retries on serial faults (--write-retries)
  • continue-on-error logging (default) or strict abort (--fail-fast)
  • tiered scan mode (--tiered-scan) to run baseline-safe tokens first, then exploratory tokens one-by-one

Outputs can be written to JSON for later diffing and analysis (--json-out).

E.6 Example probe usage

Baseline-safe confirmation (Z, R, 1):

py mitutoyo_command_probe.py --port COM5 --candidates Z,R,1 --repeat 3 --read-window 0.30 --settle-ms 300 --write-retries 4 --json-out probe_confirm_safe_tokens.json

Tiered scan with stop on first fault:

py mitutoyo_command_probe.py --port COM5 --candidates Z,R,Q,?,P,S,T,D,M,A,B,C,1,2,3 --tiered-scan --tier0-candidates Z,R,1 --tier1-candidates Q,?,P,S,T,D,M,A,B,C,2,3 --tier-stop-on-error --repeat 3 --read-window 0.30 --settle-ms 300 --write-retries 4 --json-out probe_tiered.json

Single-shot zero candidate test (confirmed zero token on this setup):

py mitutoyo_command_probe.py --port COM5 --candidates P8D00 --repeat 1 --read-window 0.40 --settle-ms 500 --write-retries 4 --fail-fast --json-out probe_single_P8D00.json

Troubleshooting

Mahr troubleshooting

No bulk IN endpoint found

You are still using the FTDI VCP driver.
Install WinUSB via Zadig.

No measurements returned

Check:

  • Gauge is awake
  • Cable fully inserted
  • Initialization completed
  • Trigger is being sent

Blank measurement

Normal for warm‑up.
prime_ddi() handles this.

Mitutoyo troubleshooting

No COM port found / open failed

  • Confirm USB-ITN-SF is using ITVCP64.sys.
  • Confirm Device Manager shows USB-ITN (COMx).
  • Pass that exact port with --port.

Parseable measurement not returned every trial

  • This can happen with intermittent status-only reads.
  • The CLI includes per-trial retries; increase trial delay if needed.

Raw output needed for diagnostics

  • Use --raw_ascii or --raw_hex to inspect response payloads directly.

Flowchart

                     +----------------------+
                     |  Start Measurement   |
                     +----------+-----------+
                                |
                                v
                     +----------+-----------+
                     |  prime_ddi() called? |
                     +----+-------------+---+
                          |             |
                         No            Yes
                          |             |
                          v             v
            +-------------+---+   +-----+----------------+
            | Call prime_ddi() |   | Trigger measurement |
            +------------------+   +----------+----------+
                                              |
                                              v
                                   +----------+----------+
                                   |  read_measurement() |
                                   +----------+----------+
                                              |
                                              v
                         +--------------------+--------------------+
                         | Measurement ends with '\r'?             |
                         +-----------+------------------------------+
                                     |
                          +----------+----------+
                          |                     |
                         No                    Yes
                          |                     |
                          v                     v
          +---------------+---------+   +--------+----------------+
          | Increase timeout /      |   |  Print measurement      |
          | check cable / gauge     |   |  (success)              |
          +--------------------------+   +-------------------------+

License, Authorship, and Acknowledgments

  • License: This project is released under the MIT License. See LICENSE.
  • Third-party components: Bundled third-party binaries (including libusb-1.0.dll) are licensed separately; see docs/legal/THIRD_PARTY_NOTICES.md.
  • Authorship: The project author is onetablespoon.
  • AI-Assisted Development Acknowledgment: Parts of implementation, refactoring, and documentation were developed with assistance from GitHub Copilot (including multiple model variants) under maintainer direction and review.

Trademark, Affiliation, and Interoperability Notice

Mitutoyo and Mahr are trademarks of their respective owners.

This project is an independent, community-developed compatibility effort and is not affiliated with, endorsed by, or sponsored by Mitutoyo or Mahr.

The project focuses on interoperability with user-owned hardware and does not include or redistribute vendor proprietary firmware or source code.

Legal note: this repository is provided for technical interoperability and research purposes; users are responsible for compliance with applicable laws, regulations, and agreements in their jurisdiction.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages