From e659efc3c03d169dd8b000e267dc17cf5c8878df Mon Sep 17 00:00:00 2001 From: mikkeli Date: Fri, 9 Oct 2026 01:00:46 +0900 Subject: [PATCH] Plan: measure the Z27AG CAN bitrate in the car 500 kbps is the likely era standard but unconfirmed for the Colt, so no persistent bitrate yet. Adds a listen-only probe (installed on the car unit as can-bitrate-probe) that cycles common rates without disturbing the bus, the fallback if the OBD port is gatewayed and silent, and what to persist once the rate is known. Co-Authored-By: Claude Opus 5.5 --- docs/impl/plans/CAN-BITRATE.md | 67 ++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 docs/impl/plans/CAN-BITRATE.md diff --git a/docs/impl/plans/CAN-BITRATE.md b/docs/impl/plans/CAN-BITRATE.md new file mode 100644 index 0000000..1a91edf --- /dev/null +++ b/docs/impl/plans/CAN-BITRATE.md @@ -0,0 +1,67 @@ +--- +type: plan +status: active +updated: 2026-10-09 +--- +# CAN Bitrate for the Z27AG: Measure in the Car + +## Goal + +Find the bitrate of the bus reachable at the OBD port of the Mitsubishi Colt (Z27AG), then make `can_pcan` come up with it automatically. +Not set yet on purpose: no persistent bitrate until it's measured. + +## What is known (desk research, 2026-10-09) + +- The Colt's OBD port carries CAN on **pin 6 (CAN-H) / pin 14 (CAN-L)** + ([AiM Colt 2004–2008 guide](https://store.aimsports.com/download/ecu/stock/mitsubishi/Mitsubishi_Colt_2004-2008_103_eng.pdf)). +- Mitsubishi diagnostics of this era use KWP2000 on CAN (MUT-III). +- **500 kbps is the likely answer** (era standard for powertrain and OBD CAN), but nothing found confirms it for the Z27AG, and body networks + (ETACS etc.) on cars of this era often run slower. Hence: measure. + +## Procedure (in the car, ignition ON) + +1. PCAN-USB on the OBD port (pins 6/14), adapter on the Orin. It appears as `can_pcan`. +2. `sudo can-bitrate-probe can_pcan 3` + + It cycles 500k, 250k, 125k, 1M, 100k, 83.3k, 50k and 33.3k in **listen-only** mode (no ACKs, no error frames: a wrong rate can't disturb the bus). + For each rate it prints frames received, the RX error counter, and controller state. **The right rate has frames > 0 and RX errors ≈ 0.** + Wrong rates show 0 frames and/or climbing RX errors. +3. Confirm by watching traffic at that rate, still listen-only: + `sudo ip link set can_pcan up type can bitrate listen-only on && candump -c can_pcan`, and `cansniffer can_pcan` for changing IDs. + +**If every rate shows 0 frames:** the OBD port is probably behind a gateway that stays silent unless queried. Then the bitrate has to be found +by sending one standard OBD-II request (ISO 15765-4: try 500k, then 250k), e.g. mode 01 PID 00 to `0x7DF`. That's transmitting, so it +belongs to the single CAN writer (`obd-poller`, project-yukart decision 3). Do it deliberately, not as part of a sniff. + +## After the rate is known + +- Persist it for `can_pcan` (systemd-networkd `.network` with `[CAN] BitRate=` and `ListenOnly=yes` for the sniffing role, or a udev/systemd + unit that runs `ip link set ... up` on add). It must survive hot-plug, not just boot. +- Record the result in [DEVICE-NAMING](../reports/DEVICE-NAMING.md) / BOM, and in project-yukart's README (`can_pcan, 500 kbps` is currently an assumption). +- `can_onboard` (MTTCAN) can't go on the bus as is. The Orin's CAN pins are logic level and need an external CAN transceiver (e.g. SN65HVD230 class). + +## Probe script + +Installed at `/usr/local/sbin/can-bitrate-probe` on the car unit. Source: + +```bash +#!/bin/bash +# can-bitrate-probe: find a CAN bus's bitrate without disturbing it. +# Listen-only mode: the adapter sends no ACKs and no error frames, so a wrong bitrate cannot affect the bus. +# Usage: sudo can-bitrate-probe [iface] [seconds-per-rate] +IF=${1:-can_pcan}; T=${2:-3} +RATES="500000 250000 125000 1000000 100000 83333 50000 33333" +stat() { ip -s -d link show "$IF" | awk '/RX:/{getline; print $2}'; } # rx packets +berr() { ip -d link show "$IF" | grep -oE 'berr-counter tx [0-9]+ rx [0-9]+' | awk '{print $5}'; } +state() { ip -d link show "$IF" | grep -oE 'state (ERROR-[A-Z]+|BUS-OFF|STOPPED|SLEEPING)' | awk '{print $2}'; } +printf "%-9s %7s %8s %s\n" bitrate frames rx-errs state +for br in $RATES; do + ip link set "$IF" down + ip link set "$IF" type can bitrate "$br" listen-only on restart-ms 100 || { echo "$br: unsupported"; continue; } + ip link set "$IF" up + n=$(timeout "$T" candump -n 100000 "$IF" 2>/dev/null | wc -l) + printf "%-9s %7s %8s %s\n" "$br" "$n" "$(berr)" "$(state)" +done +ip link set "$IF" down +echo "Pick the rate with frames > 0 and rx-errs ~0. Interface left DOWN (listen-only still set)." +```