Files
samplez/tunie/FIRST_READ.md
uhryniuk 4aa5da53d2 Commit tune maps and research so tunes are reachable from the phone
Removes the *.hex/maps_cache gitignore rule (explicit user call, reversing
the earlier no-redistribution stance) so the official TuneECU catalogue
maps, derived SAI/O2-delete composites, and the checksum/composition
tooling are actually available to pull up on a phone browser when using
the real TuneECU app. Also folds in tonight's KWP2000 fixes (TesterPresent
keep-alive, connect-failure cleanup, slow-init StartCommunication fix) and
the accumulated research docs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FP2GaxS9HkUdL5sLBnjKje
2026-08-27 01:34:05 -05:00

7.7 KiB

First ECU read (KKL cable) — offline quick reference

Pull this up locally, no signal needed. Everything here is already known/ confirmed as of tonight (2026-08-26) — nothing depends on being online. Bluetooth (vLinker MC+) is parked for now: it needed a full unpair/re-pair after nearly every attempt tonight (likely the adapter's own KWP firmware, not something software fixes) — the KKL cable sidesteps that whole class of problem, which is why it's next.

⚠ Current KKL cable (/dev/cu.usbserial-A50285BI) — confirmed bad, 2026-08-26

Both fast and slow init failed in a way that points at the cable itself, not wiring/pinout/software:

  • Fast init: timed out waiting for 1 bytes, got 0 (none) — failed at the very first echo check, right after transmitting. K-Line is half-duplex: your own transmission always echoes back on a working line. Zero bytes back, not even the echo, means RX isn't picking up anything at all.
  • Slow init: expected sync byte 0x55, got 00 — not silence this time, a real 0x00 byte. Consistent with RX stuck permanently low (a UART can't frame a start bit without a high→low transition, so a dead-low line reads back as a stream of 0x00s).

Both symptoms match a well-known, common failure mode for cheap "VAG-COM 409.1 KKL" cables: a bare FTDI FT232R with no real K-Line transceiver chip (should be something like an L9637) actually soldered in. TX may weakly drive the line, but RX never sees a clean signal, including its own echo. Nothing in tunie's K-Line code looks suspect — echo-consumption and 5-baud timing both match spec exactly.

Before writing this cable off for good, one more isolated check next time it's plugged in — independent of any init timing:

/Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -m tunie.cli raw --port /dev/cu.usbserial-A50285BI --baud 10400 --command AA --hex

If that returns nothing at all, that's about as clean a "cable is dead" confirmation as possible without a scope — worth getting a known-good KKL cable (or leaning on the Bluetooth path / TuneECU's own bundled cable) rather than continuing to debug this one in software.

Before you plug anything in

  • Connector location and shape checked. Real accounts from other owners on this same ECU family describe it as a standard 16-pin OBD-II-style plug, in front of the fusebox, behind the tank, no tools needed. If it matches, plug in directly. If it looks different/ smaller/non-standard, stop — that's the one real electrical risk here.
  • Pull the headlight AND taillight fuses before connecting anything — protects the battery (Keihin ECUs are sensitive to voltage drop) and doubles as a safety interlock. Fuse numbers are bike-specific, check the fusebox cover.
  • Battery tender/maintainer connected (a real smart tender, not a bare trickle charger).
  • Ignition on, engine off. Kill switch in run position.
  • KKL cable plugged in.

Step 1 — confirm the port shows up

cd /Users/dylan/dojo/samplez/tunie
/Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -m tunie.cli ports

Look for an FTDI/USB-serial entry (last confirmed working port this session: /dev/cu.usbserial-A50285BI — but ports can renumber, trust what this actually prints over memory). If nothing FTDI-looking shows up, stop here — that's a driver/cable problem, not a bike problem.

Step 2 — raw wiring smoke test (new tonight, do this before info)

K-Line is half-duplex: anything you write is normally echoed straight back over the wire if the adapter and wiring are electrically sound. This new tunie raw command proves that before risking a real protocol handshake:

/Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -m tunie.cli raw --port /dev/cu.usbserial-A50285BI --baud 10400 --command ATZ
  • Exact echo of ATZ comes back → wiring/pinout/adapter proven sound. This is the good result for K-Line (unlike Bluetooth, where an echo would mean something else). Move on to Step 3.
  • Nothing comes back at all → wiring/pinout/driver issue. Don't bother with info yet — recheck the connector, recheck tunie ports, confirm the FTDI driver is actually bound to that device.

Step 3 — the real read

/Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -m tunie.cli info --port /dev/cu.usbserial-A50285BI --adapter kline --retries 5

If fast init times out, slow init is a normal fallback, not a sign of a deeper problem:

/Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -m tunie.cli info --port /dev/cu.usbserial-A50285BI --adapter kline --init slow --retries 5

Add -v before info (i.e. tunie.cli -v info ...) if you want every raw frame logged — only useful for troubleshooting a failed connection.

What changed tonight (fixed, already in the code you'll be running)

  • tunie now sends a TesterPresent keep-alive between every read during the interrogation sweep, so a long scan can't let the ECU's diagnostic session lapse partway through (this was a real bug, found by tracing TuneECU's own decompiled code — m.java's hd() does the same thing).
  • Connection cleanup now always runs even when every retry fails — no more stale handles left open after a failed attempt.
  • Bad-port errors are now a clean message, not a raw Python traceback.

None of tonight's fixes were K-Line-specific bugs (they were mostly found chasing the Bluetooth adapter), but they all apply to this path too and none of them introduced anything new to worry about — tests/verify_protocol.py passes clean as of the last edit.

How you'll know it's done

Normal synchronous command — no background process. It prints a result (success or a friendly error) and returns you to the shell prompt. Prompt back = done. A few seconds to ~30s, longer if retries kick in.

Retries are automatic and visible:

Attempt 1/5 failed (...); retrying in 5s...

This does not power-cycle the bike for you — if all retries fail, that's the signal a real ignition off/on cycle is worth trying, not just re-running the command again.

Every run writes its own timestamped file to tunie/logs/ regardless of outcome:

(full session log: logs/tunie-info-20260826-201432.txt)

ls -t logs/ shows the newest one first if you lose track.

Reading the output

  • "Queries that did not answer" is normal, not a failure — the sweep deliberately probes a range of manufacturer-defined record numbers.
  • The record under 0x94 (software part number) is what to cross-check afterward against maps.json to confirm exactly which stock calibration is on the bike.
  • DTCs will most likely say "none reported" unless something's actually faulting right now.

If the connection won't work

In order:

  1. Ignition on, engine off — the ECU sleeps otherwise, most common miss.
  2. Re-check the connector pinout before suspecting anything else.
  3. Try --init slow if fast init times out (Step 3 above).
  4. Real ignition off/on power cycle if software retries don't help.
  5. If raw in Step 2 got nothing back at all, this is a wiring/adapter problem — no amount of retrying info will fix that on its own.

While you're at it

  • Watch the battery voltage manually — tunie doesn't read/display it. Multimeter on the terminals, or the bike's dash if it shows one. Below ~12.5V connection attempts get flaky; ~12.2V is the "stop and recharge" point.
  • Multiple attempts before success is normal — don't read one failed try as a real problem.

After you're done

Turn ignition off. Bring the log file back — paste its contents into a conversation with me, or just tell me the map ID under 0x94 and I'll cross-check it against maps.json directly.