A Bus Pirate style multi-protocol tool for the ESP32 (WROOM-32, S3 and C3 boards). It can be controlled from three equivalent consoles: USB serial, a web console in the browser (WiFi) and Bluetooth serial.
| Feature | State |
|---|---|
| USB console with history | ✅ |
| HiZ (safe default state) | ✅ |
| I2C (bitbang, scan) | ✅ |
| SPI (hardware) | ✅ |
| UART (+ bridge) | ✅ |
| 1-Wire (scan, DS18B20) | ✅ |
| Pin levels + voltage measuring | ✅ |
| Console password (web + Bluetooth) | ✅ |
| WiFi + web console | ✅ |
| Bluetooth serial + BLE scan | ✅ |
| Over-the-air updates (OTA) | planned |
| Logic analyzer, IR, CAN | planned |
| Board | PlatformIO environment | Bluetooth serial | Console / USB port | Tested on hardware |
|---|---|---|---|---|
| ESP32-WROOM-32 DevKit | esp32dev (default) |
yes (SPP) + BLE | USB (CP210x/CH340) | yes |
| ESP32-S3-DevKitC-1 | esp32-s3-devkitc-1 |
BLE only | port labelled "UART" | builds, not yet run |
| ESP32-C3-DevKitM-1 | esp32-c3-devkitm-1 |
BLE only | native USB (CDC) | builds, not yet run |
WiFi, the web console, all bus modes and the BLE scan are available on every board.
Only Bluetooth serial (bt on) needs Bluetooth Classic, which the S3 and C3 chips do not have.
The S3 and C3 builds share the same code and compile cleanly, but have not been run on real S3/C3 hardware yet. Reports from S3/C3 owners are welcome.
- Open the folder in VS Code; the PlatformIO extension detects
platformio.iniautomatically. - Select your board: click the environment name in the blue status bar at the bottom
(it reads
Default (esp32dev)) and choose the environment from the table above. Skip this step if you use a plain ESP32-WROOM-32 DevKit. - Connect the board via USB.
- In the PlatformIO toolbar: Upload (→), then Serial Monitor (plug icon). Baud rate: 115200.
Or in a terminal:
pio run -e esp32dev -t upload -t monitor
pio run -e esp32-s3-devkitc-1 -t upload -t monitor
pio run -e esp32-c3-devkitm-1 -t upload -t monitorExit the monitor with Ctrl+C.
| Function | ESP32 (WROOM-32) | ESP32-S3 | ESP32-C3 |
|---|---|---|---|
| I2C SDA | 21 | 8 | 6 |
| I2C SCL | 22 | 9 | 7 |
| SPI SCK | 18 | 12 | 4 |
| SPI MISO | 19 | 13 | 5 |
| SPI MOSI | 23 | 11 | 10 |
| SPI CS | 5 | 10 | 2 (strapping pin, idles HIGH) |
| UART TX | 17 | 17 | 21 |
| UART RX | 16 | 18 | 20 |
| 1-Wire | 4 (external 4.7k pull-up to 3.3 V) | 4 | 3 |
| ADC (0 … ~3.1 V) | 34, 35, 36, 39 | 1, 2, 5, 6 | 0, 1 |
| BOOT button | 0 | 0 | 9 |
| LED | 2 | 48 (RGB) | 8 (RGB) |
The command i always prints the pins of the board you are running on.
⚠️ The ESP32 runs at 3.3 V and is NOT 5 V tolerant. Use a level shifter for 5 V targets. Always connect the target's GND to the ESP32's GND.
Notes:
- ESP32-C3: GPIO 2, 8 and 9 are strapping pins. They work as normal I/O, but the target must not force them to a level that changes the boot mode during reset. GPIO 20/21 also carry the boot log, so expect a short burst of data on the UART pins at reset.
- ESP32-S3: the onboard RGB LED is on GPIO 48 (GPIO 38 on DevKitC-1 v1.1). Change
pins::LEDif yours differs. - ESP32-WROVER modules use GPIO 16/17 for PSRAM. Use a different UART pair if you build for one.
The pins are defined per board in include/boards/.
-
Copy
include/boards/esp32.h(oresp32s3.h/esp32c3.h, whichever chip fits) to a new file and adjust the pins. -
Add a
#elif defined(BP_BOARD_MYBOARD)branch to include/config.h. -
Add an environment to
platformio.ini:[env:myboard] board = <PlatformIO board id> build_flags = ${env.build_flags} -DBP_BOARD_MYBOARD
HiZ> m i2c
Mode: I2C
I2C: SDA=GPIO21 SCL=GPIO22, ~100000 Hz, internal pull-ups ON
I2C> scan
Scanning for I2C devices (0x08..0x77) ...
0x50 (W 0xA0 / R 0xA1)
1 device(s) found
I2C> [0xA0 0x00 [0xA1 r:4]
I2C START
TX: 0xA0 ACK
TX: 0x00 ACK
I2C REPEATED START
TX: 0xA1 ACK
RX: 0xFF
RX: 0xFF
RX: 0xFF
RX: 0xFF
I2C STOP
| Command | Meaning |
|---|---|
? |
help (general and for the current mode) |
i |
chip, firmware and pin info |
m [name|nr] |
show / change mode |
P / p |
pull-ups on / off |
= 0x41 |
convert a number (hex/dec/bin/ascii) |
cls |
clear screen |
# / reset |
restart |
| Syntax | Meaning |
|---|---|
[ / ] |
START / STOP (SPI: CS active / inactive) |
0x41 65 0b1 |
write byte (hex / dec / binary) |
0x00:4 |
write byte 4 times |
"text" |
write text as bytes |
r / r:8 |
read 1 / 8 bytes |
&:10 / %:100 |
wait 10 µs / 100 ms |
- I2C:
scan,speed <hz> - SPI:
speed <hz>,spimode <0-3> - UART:
baud <n>,bridge(exit withCtrl+Xor the BOOT button) - 1-Wire:
scan,temp(reads all DS18B20/DS18S20/DS1822)
| Command | Meaning |
|---|---|
v |
logic levels of all bus pins + voltages on the ADC pins |
V |
like v, continuously (any key stops) |
Either connect to your own WiFi ...
HiZ> wifi connect "My WiFi" secret-password
[WiFi] connected
[WiFi] web console: http://192.168.1.42/ or http://buspirate.local/
... or start an access point of its own (e.g. when on the go):
HiZ> wifi ap start the access point (random password on first start)
HiZ> wifi ap mypassword use your own password (min. 8 characters)
HiZ> wifi ap new generate a new random password
The password is printed when the access point starts; run wifi ap again to see it.
Then join the WiFi ESP32-BusPirate and open http://192.168.4.1/.
The setting is stored and restored automatically after a restart.
More commands: wifi (status), wifi scan, wifi on, wifi off, wifi forget.
The web console asks for the console password before it shows anything. Each browser logs in on its own: browsers that are not logged in receive no output and cannot type into the session.
⚠️ WebSocket traffic is not encrypted (plainws://, no HTTPS). Someone who can sniff your network can read the password and the session. Use your own WPA2-protected WiFi or the device's access point, and avoid open or shared networks.
The web UI is fully embedded in the firmware and does not need internet access.
The web console and the Bluetooth serial console are protected by one password. The USB serial console is never protected, because whoever holds the cable already has full access.
- First start: a random 12 character password is created and printed once on the USB console (open the serial monitor right after flashing). Only a salted hash is stored in the flash, never the password.
- Web console: the page shows a password field first.
- Bluetooth: after connecting you are asked for
Password:(the input is not echoed). - Wrong passwords: after 3 failed attempts the login is locked for 2 s, 4 s, 8 s ... up to 5 minutes.
| Command | Meaning |
|---|---|
passwd |
show the status |
passwd <password> |
set your own password (8 to 64 characters; use quotes if it contains spaces) |
passwd new |
generate a new random password and print it once |
passwd off |
switch the password off (not recommended) |
Changing or switching off the password signs out all open web and Bluetooth sessions.
Forgot the password? Run passwd new on the USB console.
Limits to know about: the traffic itself is not encrypted (see above), and Bluetooth pairing itself stays open, only the console behind it is protected.
HiZ> bt on console over Bluetooth serial (SPP) as "ESP32-BusPirate" (ESP32 only)
HiZ> ble scan 10 scan for nearby BLE devices for 10 s
On Android the app Serial Bluetooth Terminal works well. On Windows a COM port appears after pairing. iPhones do not support Bluetooth serial (SPP).
Notes:
- WiFi and Bluetooth work at the same time but share the radio. If you see dropouts, turn one of them off.
- After a
ble scan,bt offonly takes effect after a restart (limitation of the ESP32 Bluetooth stack).
include/config.h version, constants, board selection
include/boards/ pin assignment and chip specifics per board
src/main.cpp setup, mode registration, main loop
src/core/
LineEditor.* terminal input (echo, backspace, history)
Shell.* commands and mode switching
CommandHandler.h interface for global command groups (wifi, bt, v ...)
SyntaxRunner.* bus syntax interpreter
Format.*, Args.h number parsing/printing, argument splitting
src/modes/
Mode.h base class for all modes
HiZMode.*, I2CMode.*, SPIMode.*, UARTMode.*, OneWireMode.*
src/net/
WifiService.* WiFi (station/AP), web server, mDNS, settings
WebConsole.* terminal over WebSocket (port 81), logs in each browser separately
Auth.* console password: hashing, login rate limit, 'passwd' command
WebUi.h embedded HTML UI
src/bt/
BtService.* Bluetooth serial console and BLE scan
src/tools/
PinMonitor.* commands v / V
The shell and the modes only write to a Print/Stream. USB, web and Bluetooth are
simply three streams sharing the same shell (and therefore the same mode).
- Derive a class from
Mode(seeHiZModefor the smallest example). - Create an instance in
src/main.cppand add it to themodes[]array.
Derive a class from CommandHandler and register it in setup() with shell.addHandler(...)
(see PinMonitor for the smallest example).
This project is licensed under Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0). You may use, modify and share it for non-commercial purposes as long as you credit the author. Commercial use needs separate permission from the author.
Note: Creative Commons does not recommend its licenses for software, and CC BY-NC is not an open-source license in the sense of the OSI definition. This repository is publicly readable and free for personal, educational and hobby use, but not "open source" in that strict sense.
The firmware builds on third-party libraries that keep their own licenses, for example the Arduino core for ESP32 and WebSockets (both LGPL 2.1).