[ Sniffing CAN bus with the ESP32 Bit-Pirate ]
The ESP32 Bit-Pirate is a Bus-Pirate-style multi-tool firmware for the ESP32-S3 — a web-based CLI that speaks a pile of protocols, CAN among them. Bolt an MCP2515 module onto it and you have a pocket CAN sniffer that captures to its own flash and hands the log off over Wi-Fi. No laptop tethered to a SocketCAN adapter, no dashboard torn apart. This walks the whole loop: wire it to the bus, sniff, pull the capture off, and open it in SavvyCAN for decoding — using the two small converter scripts from the Scripts section. New to CAN itself? Read the generic CAN bus introduction first; this guide assumes you know what an arbitration ID and a data frame are.
[ What you need ]
— An ESP32-S3 board with at least 8 MB of flash — a plain S3
DevKit, LILYGO T-Embed, M5 Cardputer, Seeed Xiao S3, etc. (any S3
that Bit-Pirate supports).
— An MCP2515 CAN module — the common blue SPI board pairing an
MCP2515 controller with a TJA1050 transceiver, CANH/CANL screw
terminals, and an INT pin. Bit-Pirate drives CAN through this,
not the ESP32's built-in controller.
— Jumper wires and a way onto the bus — an OBD-II breakout, or
a tap on the vehicle connector you're after.
— A host machine with Python 3 and SavvyCAN for the analysis end.
The 3.3 V / 5 V gotcha. Most MCP2515 modules are 5 V parts, and
the ESP32 is 3.3 V. Powering the whole module at 5 V feeds 5 V back
out of the MCP2515's SO (MISO) pin into a 3.3 V ESP32 input — over
spec. The clean fixes are a logic-level shifter on the SPI lines, or
the well-documented module mod that runs the MCP2515 at 3.3 V while
keeping the TJA1050 at 5 V. Bench-test on a spare bus before you trust
it on a vehicle.
[ Wiring the MCP2515 ]
The module talks to the ESP32 over SPI, and to the car over CANH / CANL.
SPI side — module → ESP32-S3
VCC 3.3 V / 5 V (see the gotcha above)
GND GND
CS chip-select GPIO
SO MISO GPIO
SI MOSI GPIO
SCK SCK GPIO
INT interrupt GPIO (optional but recommended)
Pick free, SPI-capable GPIOs on your board — the exact pins vary by
S3 model, and you tell Bit-Pirate which ones you used with config
(next section), so there's no fixed mapping to memorize. Keep the SPI
leads short.
Bus side — module → vehicle
CANH → CAN High
CANL → CAN Low
On the OBD-II connector that's pin 6 (CAN-H) and pin 14 (CAN-L) for
the powertrain bus. On a JEEP you can also tap CAN-C or CAN-IHS behind
the glovebox — see the Jeep CAN primer for those connectors.
Termination. These modules ship with a 120 Ω resistor across
CANH/CANL. A vehicle bus is already terminated at both ends, so a third
120 Ω tap loads it down — for a short read-only sniff it's usually
tolerated, but if the bus gets cranky, lift that resistor (cut the jumper
or desolder it).
[ Flash & connect ]
Flash ESP32-Bit-Pirate onto the S3 the same way as any S3 firmware —
follow the install steps in the project's repo. (For a refresher on
browser-based ESP32 flashing in general, the ESP32 web flasher
write-up covers the mechanics.)
Once it's running, reach the web CLI one of two ways:
— Its own Wi-Fi AP — join the Bit-Pirate access point, then point
a browser at http://192.168.4.1/ (the ESP32 SoftAP default).
— USB serial — open the serial console at the firmware's baud for
the same command prompt.
Everything below is typed at that Bit-Pirate prompt.
[ Configure the CAN mode ]
Enter CAN mode, then useconfigto set the SPI pins you wired and the bus bitrate. Bit-Pirate supports 125, 250, 500, and 1000 kbps and snaps whatever you give it to the nearest one. Match the bitrate to the bus you're on — guess wrong and you'll see nothing (or error frames): 500 kbps OBD-II powertrain / most modern CAN-C 125 kbps JEEP CAN-IHS (interior / comfort bus) 250 kbps a lot of J1939 / medium-duty The on-site Bus & Message Reference lists which JEEP bus runs at which speed. When in doubt, try 500 first; a correctly-clocked idle bus still shows steady broadcast traffic within a second or two. config set SPI pins (CS / SO / SI / SCK) and CAN speed status show MCP2515 controller state and error flags Runstatusafterconfig— if the MCP2515 isn't wired right or the bitrate is wrong, its error flags light up here before you waste time staring at an emptysniff.
[ Sniff the bus ]
With pins and speed set, start the capture:
sniff capture and print every CAN frame
send [id] transmit a frame (writes to the bus — see Safety)
receive [id] wait for a specific ID
sniff is passive — it only listens, so it's the safe place to start.
Frames print one per line, and the format is exactly what the converter
script downstream expects:
📥 26 | ID: 0x123 | DLC: 8 | Data: AA BB 01 02 03 04 05 06
— a running counter, the arbitration ID, the data length, and the payload bytes. Let it run while you exercise the thing you're chasing (press a button, open a door, blip the throttle) so the frames that change get captured. Bit-Pirate writes the session to its LittleFS flash, browsable and downloadable from the web interface.
[ Get the capture onto your machine ]
You could copy the serial text into a file by hand, but the tidy way is to pull it straight off the device's flash over Wi-Fi with bp_fetch.py — stdlib Python, nothing to install: python3 bp_fetch.py 192.168.4.1 --list list the flash python3 bp_fetch.py 192.168.4.1 --file can_capture.txt download it It hits Bit-Pirate's/littlefs/listand/littlefs/downloadHTTP endpoints, so run it on the same network as the device (or joined to its AP). Both scripts live in the Scripts section below and in the bitpirate-to-savvycan repo.
[ Convert to SavvyCAN ]
SavvyCAN doesn't read Bit-Pirate's log directly, so run it through bitpirate_to_savvycan.py, which rewrites it as a SavvyCAN-native (GVRET) CSV: python3 bitpirate_to_savvycan.py can_capture.txt That writescan_capture_savvy.csv. Or skip a step —bp_fetch.pywith--convertdownloads and converts in one shot: python3 bp_fetch.py 192.168.4.1 --file can_capture.txt --convert One catch — timing is synthetic. Bit-Pirate's sniff log carries no per-frame timestamp, so the converter spaces frames a fixed--intervalapart (default 1 ms). Frame order is preserved, but the absolute and relative timing is fabricated — perfect for decoding IDs and payloads, DBC work, and ASCII scans; do not read bus-timing or inter-frame gaps off it. Pass a DBC with--dbc car.dbcand it also drops a<out>_decoded.txtsidecar of human-readable signals (scalar signals, Intel or Motorola byte order, signed/unsigned, factor/offset).
[ Analyze in SavvyCAN ]
Open SavvyCAN and load the CSV with File → Load Logs — pick the GVRET/CSV format. From there the usual moves: — Filter by ID to isolate one module's chatter from the flood. — Sort / group to spot which IDs change when you actuated something. — Load a .dbc (File → Load DBC) to decode raw bytes into named signals — SavvyCAN handles the full DBC spec, multiplexing and all, where the sidecar decoder above only does plain scalars. — Graph a signal over the capture to watch it move. Cross-reference anything you find against the Bus & Message Reference for IDs that are already decoded, and remember the timing caveat — the X-axis is frame order, not real seconds.
[ Safety ]
sniffis read-only and safe on a live vehicle.sendandreceiveare not —sendputs real frames on the bus, and blasting arbitration IDs at a moving car is how you set faults, drop modules into limp mode, or worse. Capture and understand first; only transmit once you know what an ID does and you're parked with nothing depending on the bus. Writing the wrong bytes can require a dealer reflash to undo. The CAN bus intro covers the general safe-practice rules; they all apply here.
[ Scripts ]
bitpirate_to_savvycan.py # Bit-Pirate log → SavvyCAN GVRET CSV (+ optional DBC decode)
bp_fetch.py # pull a capture off the device over Wi-Fi, optionally convert
bitpirate-to-savvycan # both scripts on GitHub
[ See Also ]
CAN bus — a generic introduction # protocol, framing, safety
Jeep CAN bus primer # where to tap CAN-C / CAN-IHS
Bus & Message Reference # decoded IDs, per-bus bitrates
ESP32 web flasher # browser-based ESP32 flashing
ESP32 getting started # new to ESP32? specs, power, flashing basics
ESP32-Bit-Pirate # the firmware project
Links & Resources # SavvyCAN and other tooling
