Logic Analysis on a Linux SBC with espctl
Turn an ESP32-S3 into a protocol-grade logic analyzer, run PulseView or sigrok-cli
directly on your Linux SBC, and drive builds and captures through any of 18 AI coding
agents — all with a single espctl binary that weighs under 15 MB, ships no runtime
dependencies, and runs unmodified on x86_64, ARM64, ARMv7, and RISC-V Linux.
Why a Linux SBC as the debug host
A Raspberry Pi 4, OrangePi 5, or any RISC-V board running a mainstream Linux distro is a capable logic-analysis workstation once you shed the assumption that a $200+ desktop is required:
- PulseView and sigrok-cli have packaged ARM64 and ARMv7 builds in every major
distro (
apt install pulseview sigrok-clion Debian/Ubuntu/Raspbian). - The USB connection between the ESP32-S3 analyzer and the SBC host adds no measurable latency to captures — SUMP sample upload is bounded by SRAM size, not USB bandwidth.
espctlitself is a single statically-linked binary. Copy it,chmod +x, done. No pip, no npm, no Rust toolchain, no ESP-IDF needed on the SBC.
espctl on Linux SBC — install in one line
# ARM64 / RISC-V / x86_64 — same command
curl https://esphome.cloud/espctl/install.sh | sh
The installer detects your architecture, downloads the matching binary, and places it
in ~/.local/bin. On a fresh Raspberry Pi OS Lite this takes under 10 seconds.
Verify:
espctl version
# espctl 1.x.x linux/arm64
espctl connects to the remote build farm over HTTPS — your SBC needs outbound port 443 but nothing else. The build toolchain (ESP-IDF, arm-none-eabi-gcc, Rust cross) runs entirely on the farm.
Step 1 — Add the sigrok component to your firmware
In the esphome.cloud wizard, open your ESP32-S3 project and add the Sigrok Logic Analyzer component. Or add it directly to your project config:
{
"target": "esp32s3",
"components": ["sigrok"]
}
Firmware-level hard limits (compile-time):
| Parameter | Value |
|---|---|
| Channel count | 8 (fixed) |
| Default sample rate | 1 MHz |
| Max sample rate | 10 MHz |
| Capture buffer depth | ~32 K samples |
| Trigger modes | Immediate; pattern match (with optional edge detection) |
Sample rate is runtime-adjustable from the host over the SUMP protocol. Channel count and buffer depth are compile-time fixed and cannot be changed at runtime. There is no PSRAM extension path, no 16-channel mode, and no pre-trigger-ratio config field.
The component is validated on ESP32-S3 only — the capture core uses the S3’s parallel-GPIO sampling capability (reads 8 GPIOs in a single CPU cycle). C3/C6 can in principle host a low-channel-count low-speed SUMP device, but the sigrok firmware itself has not been ported to those targets. Full hardware-capability breakdown: PulseView & Sigrok Firmware.
Step 2 — Build and flash from the SBC
# Build remotely — no local ESP-IDF needed
espctl build . --target esp32s3
# Flash over USB
espctl flash build/flash_bundle.tar.gz
Build time on a warm cache is typically under 30 seconds. The SBC is only the coordinator; all compilation happens on the remote farm. RAM usage on the SBC during a build is under 50 MB.
Step 3 — Connect PulseView or sigrok-cli
Plug the flashed ESP32-S3 into the SBC’s USB port. It appears as /dev/ttyACM0 (or
similar).
Verify device recognition:
sigrok-cli --driver=ols:conn=/dev/ttyACM0 --scan
# Found: ESP32-S3 sigrok, 8 channels, max 10 MHz
Start PulseView:
pulseview &
In PulseView: File → Connect to device → OLS → /dev/ttyACM0 → Scan. The device appears with the configured channel count and sample rate ceiling.
Headless capture with sigrok-cli (no display required):
# Capture 100 K samples at 1 MHz, save as sigrok session
sigrok-cli \
--driver=ols:conn=/dev/ttyACM0 \
--config samplerate=1MHz \
--samples 100000 \
--output-format srzip \
--output-file capture.sr
# Decode I2C immediately after capture
sigrok-cli \
--driver=ols:conn=/dev/ttyACM0 \
--config samplerate=4MHz \
--samples 50000 \
--protocol-decoder i2c:scl=0:sda=1 \
--protocol-decoder-annotation i2c:address-read,address-write,data-read,data-write
Headless sigrok-cli is especially useful on SBCs without a display — pipe output to a
file, ssh into the SBC from your laptop, and inspect captures remotely.
Trigger modes
Triggering is configured at runtime by PulseView / sigrok-cli over the SUMP protocol — not by a JSON field at build time. The firmware implements two modes:
| Mode | What it does |
|---|---|
| Immediate | Fires on arm; no pre-trigger window |
| Pattern | Fires when (sample & mask) == value. With edge detection enabled, fires only on the transition into that value (pattern-match used to emulate edge triggering). |
The pre-trigger / post-trigger sample split is also runtime-controlled through SUMP — the host tells the firmware “after the trigger fires, collect N more samples”; the rest of the buffer is reserved for pre-trigger context. It is not a build-time config field.
PulseView and sigrok-cli render the above as a “Trigger when this pattern matches” toggle, a “Detect edges” option, and numeric sliders; the OLS/SUMP driver handles the mapping.
Protocol decoders
PulseView and sigrok-cli ship 131 protocol decoders via libsigrokdecode. Six are validated end-to-end with the ESP32-S3 sigrok component:
| Protocol | Typical use | Decoder name in PulseView |
|---|---|---|
| I2C | Sensor buses (BME280, SHT4x, MPU-6050) | i2c |
| UART | Serial debug output, GPS NMEA, AT commands | uart |
| SPI | Flash, displays, DACs | spi |
| 1-Wire | DS18B20 temperature sensors | onewire |
| WS2812 | RGB LED strips | ws2812 |
| IR (NEC) | Remote controls, IR receivers | ir_nec |
Any of the other 125 decoders (CAN, LIN, I2S, PWM, JTAG, SMBus, …) will work as long as the protocol fits within the channel count and sample rate limits.
AI agent integration on the SBC
espctl includes a built-in MCP server. Run it on the SBC and point any supported AI
coding agent at it — the agent can then trigger builds, read logs, download firmware,
and interact with the sigrok component through the same 42 MCP tools available in the
cloud.
# Start the MCP server on the SBC
espctl mcp serve
Getting the install snippet
Every supported agent has a ready-to-paste config snippet available via the
install:// MCP resource. Fetch it from within any MCP session:
resources/read install://<agent-slug>
For example, install://claude-code returns the exact JSON block to paste into
.claude/settings.json. No manual config writing required.
Supported agents (18 with full install snippets)
| Agent | Snippet available | Notes |
|---|---|---|
| Claude Code | install://claude-code | |
| Cursor | install://cursor | |
| Claude Desktop | install://claude-desktop | |
| Codex CLI | install://codex | |
| OpenCode | install://opencode | |
| DeepSeek-TUI | install://deepseek-tui | |
| Oh My Pi | install://oh-my-pi | |
| AstrBot | install://astrbot | |
| nanobot | install://nanobot | |
| Reasonix | install://reasonix | |
| Langcli | install://langcli | |
| Kilo Code | install://kilo-code | |
| WorkBuddy | install://workbuddy | |
| Deep Code | install://deep-code | |
| Hermes | install://hermes | |
| Crush | install://crush | |
| GitHub Copilot | install://github-copilot | VS Code extension |
| OpenClaw | install://openclaw |
Two additional agents (GitHub Copilot CLI, Pi) are documented with alternative
connection paths; see their individual client pages.
Example: Claude Code on a Raspberry Pi 4
// ~/.claude/settings.json
{
"mcpServers": {
"esp-idf": {
"command": "espctl",
"args": ["mcp", "serve"]
}
}
}
With this in place, Claude Code running on the Pi can:
- Ask
buildto compile new firmware after you change the sigrok channel config - Ask
logs.tailto stream the build output - Ask
flash.runto flash the new firmware to the connected ESP32-S3 - Read capture results if you pipe
sigrok-clioutput into the MCPartifactssurface
Resource footprint on SBC hardware
espctl is designed to run comfortably on the smallest practical SBC:
| Operation | SBC RAM usage | CPU usage (peak) | Disk |
|---|---|---|---|
espctl mcp serve (idle) | < 20 MB | < 1 % | 0 |
espctl build . (coordinator only) | < 50 MB | < 5 % | ~30 MB temp |
espctl flash | < 30 MB | < 10 % | 0 |
espctl monitor | < 20 MB | < 2 % | 0 |
The build toolchain never runs on the SBC — all compilation is on the remote farm.
A Raspberry Pi Zero 2 W (512 MB RAM) can run espctl mcp serve while simultaneously
running sigrok-cli captures without hitting memory pressure.
Tested SBC hardware:
| Board | Architecture | RAM | Works |
|---|---|---|---|
| Raspberry Pi 4 / 5 | ARM64 | 2–8 GB | Full workflow |
| Raspberry Pi Zero 2 W | ARM64 | 512 MB | Full workflow |
| OrangePi 5 | ARM64 | 4–16 GB | Full workflow |
| BeagleBone Black | ARMv7 | 512 MB | Build + flash + MCP |
| Milk-V Duo S | RISC-V | 512 MB | Build + flash + MCP |
| Generic ARMv7 (any) | ARMv7 | ≥ 256 MB | Build + flash |
Recommended SBC debug setup
┌──────────────────────────┐
│ Linux SBC (e.g. Pi 4) │
│ │
│ espctl mcp serve ──────┼──── Claude Code / Cursor / any MCP agent
│ PulseView / sigrok-cli │
│ │
│ USB port 1 ────────────┼──── ESP32-S3 (sigrok analyzer)
│ USB port 2 ────────────┼──── ESP32-S3 / STM32 (device under test)
└──────────────────────────┘
One ESP32-S3 acts as the logic analyzer. A second ESP32-S3 (or STM32, or any target)
is the device under test. The SBC sits between them, running espctl for builds and
sigrok-cli / PulseView for captures.
See Also
- PulseView & Sigrok Firmware — the sigrok firmware reference page, which this workflow defers to for hardware capability (
dedic_gpio8 channels, 10–80 MSa/s, SRAM 32–200 KB). - MCP Clients — Claude Code — detailed Claude Code MCP setup.
- Build Lifecycle — how the remote build farm works.
- Firmware & Flash — flash bundle format and
espctl flashoptions.