--- type: plan status: done updated: 2026-10-09 --- # CAN Bitrate for the Z27AG: Measure in the Car ## Result (2026-10-09, in the car, ignition on, PCAN terminator off) **500 kbps.** `can-bitrate-probe`: 2673 frames in 3 s at 500k with zero RX errors, 0 frames at every other rate. The OBD port is **not** gatewayed: broadcast traffic is visible passively. 10 s listen-only capture (`~/can-captures/z27ag-20261009-163736-ign.log`, `candump -L` format): **27 IDs, ~893 frames/s** (≈22% bus load), all periodic at 5 / 10 / 25 / 50 / 100 Hz. IDs: `0C0` (100 Hz), `119 139 13D 149 14D 156 210 231 235 300 312 443` (50 Hz), `239 423 42F 447 570 573` (25 Hz), `2F1` (10 Hz), `159 449 710 711 712 713` (5 Hz), `152` (2 Hz). Persisted (boot and hot-plug): - `/etc/udev/rules.d/71-can-up.rules`: on add of `can_pcan`, wants `can-up@can_pcan.service` - `/etc/systemd/system/can-up@.service`: oneshot; reads `/etc/default/can-`, sets the bitrate and options, brings the interface up, and stops with the device - `/etc/default/can-can_pcan`: `BITRATE=500000`, `CAN_OPTS="restart-ms 100"` **Listen-only was on during the sniffing phase**, so the adapter never ACKed on the car's bus. Dropped 2026-10-12 for `obd-poller` (svc-core), the single writer: the adapter now acknowledges frames like any scan tool. To go back, set `CAN_OPTS="listen-only on restart-ms 100"` there and replug the PEAK (or restart `can-up@can_pcan`). ## 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)." ```