2026-10-09 01:00:46 +09:00
---
type: plan
2026-10-09 16:38:44 +09:00
status: done
2026-10-09 01:00:46 +09:00
updated: 2026-10-09
---
# CAN Bitrate for the Z27AG: Measure in the Car
2026-10-09 16:38:44 +09:00
## 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):
2026-10-13 17:54:42 +09:00
- `can-up@can_pcan` is **enabled with `WantedBy=sys-subsystem-net-devices-%i.device` ** : systemd starts it whenever
`can_pcan` appears, at boot or on hot-plug. It replaced `/etc/udev/rules.d/71-can-up.rules` (2026-10-13), whose
`SYSTEMD_WANTS` never reached systemd, by `NAME==` or by USB id: the interface stayed down on hot-plug and at boot,
so the recorder never opened a session and refused marks ("no session").
2026-10-13 18:28:23 +09:00
Verified on hot-plug 2026-10-13: three plug-ins in the car, each up within a second and recorded. Boot not yet seen.
2026-10-13 17:54:42 +09:00
- `/etc/systemd/system/can-up@.service` : oneshot, with that `[Install]` section; reads `/etc/default/can-<iface>` , sets the bitrate and options, brings the interface up, and stops with the device
2026-10-12 23:25:04 +09:00
- `/etc/default/can-can_pcan` : `BITRATE=500000` , `CAN_OPTS="restart-ms 100"`
2026-10-09 16:38:44 +09:00
2026-10-12 23:25:04 +09:00
**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` ).
2026-10-09 16:38:44 +09:00
2026-10-13 22:57:32 +09:00
The Z27AG's ECU never answered OBD-II on CAN: it speaks ISO 9141-2 on the K-line (pin 7), confirmed through an ELM327
on 2026-10-13. obd-poller now polls through that ELM over Bluetooth, so **nothing transmits on CAN ** . The adapter was left
acknowledging anyway, as harmless at the measured bitrate.
2026-10-13 17:50:30 +09:00
2026-10-09 01:00:46 +09:00
## 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 <rate> 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
2026-10-13 22:57:32 +09:00
belongs to the single writer (`obd-poller` , project-yukart decision 3). Do it deliberately, not as part of a sniff.
2026-10-09 01:00:46 +09:00
## 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)."
```