Read-only CAN bus analyser: live trace, graphs, and automatic detection of the link between a physical action and the bus data.
Features · Installation · Getting started · Sources · Guide · Command line · Development
HyCAN listens to a vehicle CAN bus and helps you understand what it carries.
Switch the headlights on while holding a key, and the software tells you on its
own that it is CAN0 0x545 byte 0 bit 3. It never transmits anything on the bus.
All screenshots come from the built-in simulator: no real vehicle.
Formerly "CANscope": .canscope recordings still open.
| Live trace | One row per identifier, with period and length; changing bytes light up in orange. Filter by identifier, range, bus, name, or "what moves". |
| Action detection | Mark an action four to six times: three methods (status, edge, value) rank the bits and fields that follow it. |
| Signal databases (DBC) | Reads DBC files, assigns them to the right bus automatically, shows traffic coverage, exports a standard database. The opendbc Hyundai/Kia (C-CAN) database is bundled. |
| Replay | Plays a recording back with every decoded value, a shared cursor, and CSV export. |
| Statistics | Bit-level activity map and automatic interpretation of each byte: constant, counter, flags, analog value, checksum. |
| Monitored link | Rate, losses detected from line numbering, overflows reported by the board: you know whether the capture is complete. |
| Never lose a capture | Continuous log written to disk every second; saving runs in the background without interrupting the capture. |
| No hardware needed | A complete vehicle simulator to try everything, detection included. |
| 9 languages | Interface and command line in the Windows language, changeable at any time from the menu. |
- Download the latest release
(
HyCAN-<version>-Setup.exe) and run it. No administrator rights are needed; HyCAN is added to the Start menu and to Windows' installed apps. - Wizard options: open
.hycanprojects (and old.canscopefiles) by double-clicking, addhycan-clito the PATH, desktop icon. - Launch HyCAN.
| Data | Location |
|---|---|
Application (HyCAN.exe, hycan-cli.exe) |
%LOCALAPPDATA%\Programs\HyCAN |
| Capture logs | Documents\HyCAN |
| Projects | wherever you save them |
| Settings (language, last source) | user registry |
Uninstalling removes the application, the file association and the PATH entry, never your logs or projects.
At startup, HyCAN checks GitHub for a newer release, silently when offline. When one is available, it shows the release notes and offers Update, Later or Skip this version; Help › Check for updates... runs the check at any time. The update is downloaded and verified (size, SHA-256), then installed: only the application is replaced, and HyCAN restarts on its own. It is refused while a capture or a save is in progress.
pip install -r requirements.txt # PyQt6, pyqtgraph, numpy, pyserial
python hycan.py # starts the interfaceOn Windows, double-clicking HyCAN.pyw starts the interface without a console
window. Windows, Linux and macOS; Python 3.9 or later.
To build the installer, run python build_exe.py (requires PyInstaller and
Inno Setup 6): it produces the application
folder dist\HyCAN and the installer dist\HyCAN-<version>-Setup.exe to attach
to the GitHub release.
In two minutes, without hardware:
- Launch HyCAN (or
python hycan.py). - Capture → Connect... → Simulator tab → OK
- In the Action detection tab, a Simulator controls panel appears.
- Type
headlightsin the Action field. - Five times in a row: click MARK (or press space), tick Headlights in the simulator panel, wait 2 s, untick it, click MARK again.
- Analyse. The first row should be
CAN0 545 byte 0 bit 3. - Create the signal from the candidate: the bit is plotted live in the Graphs tab.
Help → Simulator: where the bits really are gives the solution.
| Source | Use |
|---|---|
| Serial / USB | Arduino + MCP2515 (reference setup), CANBed Dual, USB-CAN adapter in text mode |
| Network (HyGate) | the HyGate ESP32 gateway over Ethernet: the same capture as over USB, with no cable to the board |
| SocketCAN | Linux: can0, can1, vcan0… several interfaces at once |
| File | replays a trace (candump, HyCAN export), at real or accelerated speed |
| Simulator | complete virtual vehicle, no hardware |
HyGate is an ESP32 gateway that copies, byte for byte, the lines the capture board sends over its serial link, and serves them on TCP port 3333 of its Ethernet interface. HyCAN handles them exactly like the serial port: decoding, loss tracking, board messages, continuous log.
- On HyGate: Ethernet switched on, cable plugged into the router or directly into the PC.
- Capture → Connect... → Network (HyGate) tab:
hygate.local(via the router),169.254.10.20(direct to the PC) or its IP address; port 3333. - Test listens for two seconds without sending anything, and tells you whether the stream arrives and whether it carries frames (active bus) or only board messages.
A drop-out (HyGate restart, cable) does not stop the capture: HyCAN reconnects
every 2 s and says so in the console. If the PC cannot keep up, HyGate drops
lines rather than slowing the board down, and reports it
(# HyGate : N lignes perdues); the gap also shows up in loss tracking.
0A1B2C3D,0,316,-,0512340000000000 HyCAN compact (recommended), sequence in 6th field
[CAN0-100K] ID: 0x316 | Data: 05 12 old Lecteur_CAN.ino
CAN0|790|0|0|0|8|5|18|52|0|0|0|0|0 original CANBed sketch
(1701234567.123456) can0 316#051234 candump -l
can0 316 [3] 05 12 34 candump
An Arduino Nano 328P with two MCP2515 modules (16 MHz crystal), flashed with the
CAN_Monitor_MCP2515 sketch (not included in this repository):
| CS | INT | Rate | |
|---|---|---|---|
| CAN0 | D4 | D2 | 100 kb/s (B-CAN, comfort) |
| CAN1 | D5 | D3 | 500 kb/s (C-CAN, powertrain) |
- Truly passive listening: both MCP2515 are in
MCP_LISTENONLY. The controller then transmits nothing at all, not even an acknowledge bit. - Fit a 10 kΩ resistor between CS and +5 V on each module. During a reset, CS floats and the SPI clock blinks with the bootloader LED: without a pull-up, random instructions can reach the controller, including "leave silent mode" and "transmit".
- Timestamps on the board (
micros()): USB adds tens of milliseconds of jitter, which the Edge detection method does not tolerate. - Serial speed: Auto by default. HyCAN tries the usual speeds and keeps the
one whose lines read correctly; the Detect button shows the details (as does
hycan-cli probe --port COM3).
- There is no CAN transmit code in the project: no
send, nowrite. - The serial port is opened and only ever read. A test checks it: the simulated port raises an error at the slightest write attempt.
- The network source only reads its TCP connection, without even a greeting. A test checks it with a fake HyGate that counts what it receives.
- The board is never reset. On a USB-serial bridge (CH340, FTDI, CP210x), the DTR line drives the microcontroller's RESET: HyCAN recognises the bridge and leaves DTR idle. DTR is only raised on boards with native USB (RP2040, SAMD, Leonardo). Opening at 1200 baud, which would switch an RP2040 into bootloader mode, is refused.
A hardware caveat: a CAN controller in normal mode acknowledges the frames it
receives (ACK bit). For a fully passive probe, you need a controller in silent
mode: MCP_LISTENONLY on the MCP2515, or ip link set can0 type can listen-only on
with SocketCAN. The CANBed Dual (RP2040) does not expose this mode: it
acknowledges frames.
HyCAN follows the Windows language: English, French, Spanish, German, Italian, Russian, Chinese, Japanese or Korean, and English for any other language. Standard buttons (OK, Cancel) and file dialogs follow as well.
The Language menu changes it at any time: the window is rebuilt immediately, without losing the capture, the project or the marked trials. During a capture or a save, the choice is remembered and applied at the next start.
The command line speaks the same language; HYCAN_LANG forces one:
HYCAN_LANG=en hycan-cli --help # PowerShell: $env:HYCAN_LANG="en"Output files do not change format with the language: traces, continuous log, CSV and DBC stay readable by HyCAN and standard tools.
The trace (left panel) — Aggregated (one row per identifier) or Scrolling (chronological). Double-click the Name column to name a frame. The filter accepts space-separated terms:
316 an identifier (hexadecimal)
100-2FF a range
bus:1 a bus
dlc:8 a length
name:light free text in the name given to the frame
changed only what moves
static only what is frozen
noisy at least one bit that toggles constantly (counter, checksum)
-7A0 exclusion (prefix - or !)
- Name the action (
headlights,right indicator,steering wheel +…). - Hold MARK (button or space bar) for the whole duration of the action.
- Repeat 4 to 6 times, with a pause between trials.
- Analyse.
| Method | Question asked | Good for |
|---|---|---|
| Status | does the bit take one value during the action and the other outside it? | headlights, doors, selected gear, ignition |
| Edge | does the bit change right after each marked instant, and rarely elsewhere? | momentary buttons, indicators |
| Value | does an 8/16-bit field take a different range during the action? | speed, engine speed, temperature, position |
Counters and checksums are demoted automatically, and the most precise candidate wins: a single bit ranks ahead of the byte that contains it. A score above 0.9 almost certainly points to the right bit; between 0.5 and 0.9 it is a lead to confirm with more trials.
A DBC says, for each identifier, where each quantity lies and how to convert it
into a physical unit. HyCAN ships hyundai_can.dbc, from
commaai/opendbc (MIT), which describes the
C-CAN of Hyundai and Kia vehicles. For your own databases, set their folder in
the HYCAN_DBC environment variable.
A DBC does not say which bus it applies to: the same identifier can mean two unrelated frames on two buses. Applied to the wrong bus, it produces wrong but believable values. HyCAN therefore only assigns a DBC automatically when more than half of the observed identifiers are described in it, and the DBC coverage tab shows what is recognised, unknown or never seen.
The Replay tab shows everything that can be decoded, curves with a shared
cursor, and all values at the cursor time, with their unit and the name the DBC
gives them (D, R, P rather than 5, 14, 0). Multiplexed signals are left out,
and counted: plotting them without following their selector would give wrong
results.
A .hycan project holds the capture, frame names, signals, marked trials and
notes. Ctrl+S saves it without interrupting the capture, Ctrl+O reopens it
(.canscope files too); you can also double-click it or drop it onto the window.
| Export | Content |
|---|---|
.log |
trace in candump format, readable by HyCAN and standard tools |
.csv (frames) |
one row per frame, bytes in columns |
.csv (signals) |
one row per decoded sample, for Excel or pandas |
.dbc |
standard signal database (SavvyCAN, canmatrix, python-can) |
Once installed, HyCAN provides hycan-cli (the same as python hycan.py, from a
console); without arguments, it prints the help.
hycan-cli record --serial COM5 --baud 1000000 --out capture.log --duration 120
hycan-cli record --tcp hygate.local --out capture.log --duration 120
hycan-cli record --socketcan can0,can1 --out capture.log
hycan-cli ids --log capture.log # identifier summary
hycan-cli analyse --log capture.log --project project.json --action headlights
hycan-cli probe --port COM3 # serial speed of a board
hycan-cli ports # serial ports and the board behind each one
hycan-cli gui project.hycan # opens a project in the interfacehycan.py main program: interface and command line
HyCAN.pyw double-click, no console
build_exe.py builds HyCAN.exe, hycan-cli.exe and the installer
installer/ Inno Setup script of the installer
CHANGELOG.md notes for each version (used for the releases)
core/ frames, signals, detection, DBC, projects and exports
version.py version number and repository address
updater.py updates: latest release, verified download
i18n.py active language, detection, tr()
trad/ translations, one table per part of the interface
sources/ serial, network, SocketCAN, file, simulator — all read-only
line_stream.py shared by serial and network: lines, losses, log
tcp_source.py HyGate over TCP, automatic reconnection
ui/ main window, tabs, icon
mise_a_jour.py offering and installing updates
dbc/ bundled databases (opendbc)
tests/ one script per topic, no test dependency
Imports are absolute from the root (from core.frames import FrameStore):
hycan.py adds its own folder to the path, and each test does the same.
Adding a source means writing a class with open(), frames() and close()
(see sources/base.py); a source that receives lines of text inherits from
LineStreamSource.
The source code is written in French, and so are the translation keys: every
displayed text goes through tr("texte français", n=...) and its translation goes
in core/trad/ (rules and glossary: core/trad/CONSIGNES.md).
tests/test_i18n.py checks that every text exists in the 9 languages with the same
variables, then builds the whole interface in each language with no text missing.
Publishing a version: change VERSION in core/version.py, complete
CHANGELOG.md, run python build_exe.py, then create the GitHub release x.y.z
(no "v") with the CHANGELOG notes and the HyCAN-x.y.z-Setup.exe file attached:
installed copies of HyCAN offer it at their next start.
Tests — each one runs on its own and prints OK / ECHEC:
for f in tests/test_*.py; do python $f; doneMIT. dbc/hyundai_can.dbc comes from
commaai/opendbc, under the MIT license.



