SUS Serial Monitor & Plotter
A serial monitor that keeps up with your board.
Multi-port terminal, live plotter and ESP32 backtrace decoding — inside VS Code, wired into PlatformIO.
English · Русский

Contents
Why
Most serial monitors hand you a text stream and stop there. That is fine until the board reboots in the middle of a log, panics with a raw Backtrace: 0x400d1a2b:0x3ffb1f30, or you need two boards side by side on one timeline.
This extension is built for that part of the job:
- it owns the port itself — so board reset,
setup() output and multiple ports on a shared clock all work, instead of being lost to a wrapped CLI monitor;
- it reads your
platformio.ini — port and baud rate come from the project, and the port is handed back automatically while you flash;
- it decodes ESP32 backtraces into
function → file:line from the ELF your build already produced.
Features
- 📟 Terminal — RX/TX over UART with millisecond timestamps, autoscroll and colour-coded RX / TX / system lines
- 🔌 Multiple ports at once — two or more boards in one panel, every line and every plot series tagged with a coloured port label (
P1, P2, …), on one shared timeline
- 🔎 Live filter — hides non-matching lines as they arrive, and the ones already on screen
- 📈 Live plotter (Chart.js) — plots numbers found in incoming lines, several series per port and several ports on one chart
- 🖼️ Chart export — PNG snapshot and CSV of the raw points for Excel or pandas
- 💾 Real-time file logging — every line is appended to a file as it arrives, not only when you press save
- 📊 Debug statistics — per-port idle time and round-trip time, plus counters for errors, crashes and reboots
- 🧩 Backtrace decoding —
Backtrace: lines are resolved to function → file:line by a bundled DWARF parser, no external toolchain call
- 🔄 Board reset per port — DTR/RTS pulse from the port chip, and the control lines are left deasserted so a physical RESET runs your firmware instead of dropping into the bootloader
- ⚙️ PlatformIO integration — port and speed from
platformio.ini, automatic release and reconnect around upload tasks
- 🎨 Six themes — VS Code Dark/Light, Monokai, Dracula, Solarized Dark, Hacker (Matrix), remembered between sessions
- 📄 Export and copy — terminal to
.txt, or the whole log to the clipboard
- ⚡ Native port access — the port is opened by the
serialport module in the extension host, not by a wrapped CLI
Requirements
| Requirement |
Notes |
| VS Code |
1.84 or newer. |
platformio.ini in the folder |
The extension activates on it. Without one it stays dormant and the project integration is unavailable. |
| PlatformIO IDE |
Not required. It is only needed for the build tasks the monitor synchronises with. |
| Device driver |
The usual one for your board (CP210x, CH340, FTDI and friends), installed in the OS. |
| Native module |
serialport ships with the extension, built through N-API so it works across Electron versions. See Troubleshooting if a port refuses to open. |
Quick start
- Open a folder that contains a
platformio.ini.
- Put the cursor in any editor and press Ctrl+K M (Cmd+K M on macOS) — the monitor opens and connects to the board in one step. It is a chord: hold Ctrl, press K, release, press M.
- Type a command in the field at the bottom and press Enter. The line ending is selectable,
\r\n by default.
- Numbers in incoming lines show up on the Плоттер tab automatically.
- To add a second board, press + Добавить порт in the toolbar and pick it from the list.
Nothing arriving? Run SUS Monitor: показать журнал. Port errors and symbol-loading problems are written there and to the terminal, so that is where the reason lives — port did not open, firmware.elf not found, upload task not recognised.
Commands
Available from the Command Palette (Ctrl+Shift+P); typing SUS brings up all three. The titles are currently in Russian — see Known limitations.
| In the palette |
What it does |
SUS Monitor: открыть монитор |
Opens the panel without touching any port |
SUS Monitor: открыть и подключиться к плате |
Opens and connects using platformio.ini (Ctrl+K M, editor focus required) |
SUS Monitor: показать журнал |
Opens the SUS Monitor diagnostic channel in the Output panel |
The panel also has an icon in the editor title bar while platformio.ini is the active file.
Interface
| Element |
Purpose |
| + Добавить порт |
Picks a port from a QuickPick list — boards first — and connects it as a new session |
| Baud rate |
Speed for the next port you connect; already-open ports keep theirs |
| Тема |
Theme selector |
| Port chips |
One per connected port: colour tag, speed, reset (↺) and disconnect (✕) |
| 🧩 .elf/.map |
Loads a symbol file for backtrace decoding by hand; .elf gives file and line, .map only names |
| 🔴 Запись в файл |
Starts and stops real-time logging to a file |
| Монитор / Плоттер |
Tab switch |
| Автоскролл / Время |
Terminal behaviour toggles |
| Filter field |
Hides log lines that do not contain the substring |
| Точек |
How many recent points the plotter keeps, 50 by default |
| 🖼️ PNG / 📄 CSV |
Chart export, shown on the plotter tab |
| RX counter |
Live traffic across all ports: bytes, lines, bytes per second |
| 📊 Статистика |
Opens the debug statistics panel |
| Очистить |
Clears terminal, chart and counters; ports stay connected |
| Копировать |
Copies the whole terminal log to the clipboard |
| Сохранить лог |
Exports the log to a .txt file once |
Target port for the command, line ending (none, \n, \r, \r\n — default), the command field itself and Отправить.
Multiple ports at once
Each + Добавить порт creates an independent connection, as many as the OS will grant.
- Every port keeps the baud rate that was selected when it was connected.
- Terminal and plotter are shared, but each line and series carries the colour and tag of its port — two devices line up on one timestamp scale.
- Отправить в picks which port the next command goes to.
- Reset (↺) and disconnect (✕) act on one port, from its own chip.
- Idle time and RTT are measured per port, so a single hung device is visible instead of a silent panel.
- Error, crash and reboot counters are shared across all ports (see Known limitations).
Plotter
- Numbers are parsed out of every line, separated by whitespace or commas.
- Each position in the line becomes its own series per port (
P1 · S1, P1 · S2, P2 · S1, …), coloured from the current theme's palette.
- A missing value leaves a gap rather than a drop to zero.
- History depth is the Точек field, 50 by default.
- PNG saves the current canvas; CSV exports every point of every series with its timestamp.
ESP32 debugging
Errors, reboots and crashes are classified and counted as they arrive.
| Counter |
What matches |
| Ошибок в логе |
error, ошибка, exception, fail, failed, panic, паника |
| Крашей (Backtrace) |
a Backtrace: line, Guru Meditation, fatal exception, abort() was called, assert failed |
| Обнаружено перезагрузок |
ESP32/Arduino boot markers: rst:0x, ets Jun, ets Jul, rebooting, reset reason, boot:0x13, power on reset |
When a Backtrace: line appears, its addresses are decoded in place under the line:
Backtrace:0x400d1fb9:0x3ffb21a0 0x400d2c85:0x3ffb21c0
[DECODE] 0x400d1fb9 → loop() at main.cpp:142
Symbols are picked up on their own — the newest firmware.elf in .pio/build is loaded when the panel opens, so there is nothing to point at by hand. The 🧩 .elf/.map button is there for the cases where you want a different build.
Decoding is done by a bundled DWARF parser that reads DWARF 2–4. Current ESP-IDF versions emit DWARF 5; on those builds a backtrace degrades to symbol +0xoffset from the ELF symbol table instead of an exact line. Routing this through the toolchain's own addr2line is the first item on the roadmap.
monitor_port and monitor_speed are read from platformio.ini, honouring [env] inheritance and default_envs.
- With no
monitor_port set, the first port that looks like a board wins — matched on the USB VID of the usual suspects (CP210x 10c4, CH340 1a86, FTDI 0403, Arduino 2341, Espressif 303a, Adafruit 239a) and on the device name. If nothing looks like a board, the first available port is used.
- When a PlatformIO upload task starts, the port is released so the bootloader can take it.
- When the task ends, the monitor reconnects with retries, because a board does not come back to the OS instantly. If the upload failed, the port stays closed.
- Opening a port leaves DTR and RTS deasserted. Both lines at the same level leave the auto-reset circuit alone, so pressing RESET on the board runs your firmware. With DTR asserted and RTS clear — what the Windows driver defaults to — the same press lands in
rst:0x1 (POWERON),boot:0x2 (DOWNLOAD(USB/UART0)) instead.
Themes
| Theme |
Style |
| 🌙 VS Code Dark |
Dark, default |
| ☀️ VS Code Light |
Light |
| 🍬 Monokai |
The classic editor dark theme |
| 🧛 Dracula |
Purple and pink accents |
| 🌊 Solarized Dark |
Muted, low contrast |
| 💻 Hacker (Matrix) |
Monochrome green terminal |
Switching a theme repaints the interface, the plot palette and the Chart.js axes. Port tag colours stay fixed on purpose, so a board keeps its identity across themes.
Known limitations
- The interface, the command titles and the log messages are in Russian. Everything is icon- and keyboard-driven, so it is workable either way, but English localisation is on the roadmap.
- Backtrace decoding covers DWARF 2–4; DWARF 5 units are skipped and the address falls back to symbol-table resolution, giving a name without a line number.
- One symbol file is shared by all ports — two boards running different builds cannot both be decoded precisely at the same time.
- Error, crash and reboot counters are totals across all ports, unlike idle time and RTT which are per port.
- Warnings are not classified or counted, only errors, crashes and reboots.
- All plot series share one chart; there is no per-port chart.
- The extension activates on
platformio.ini only — Arduino CLI and bare folders are not recognised yet.
Troubleshooting
| Symptom |
Cause and fix |
Порт занят другой программой |
Something else holds the port — usually the PlatformIO monitor terminal or a running upload. Close it and reconnect. |
No native build was found for platform=… runtime=electron abi=… |
The bundled serialport binary does not match your editor's Electron. Rebuild it against the version from Help → About: npx @electron/rebuild -v <Electron version> |
| Permission denied on Linux |
Add your user to the dialout group and re-login. |
Backtrace shows symbol +0xoffset |
The build uses DWARF 5. The function name is correct, the line number is not available yet — see the roadmap. |
| Ctrl+K M does nothing |
Open SUS Monitor: показать журнал first: if there is no Команда susSerialMonitor.openAndConnect line, the keypress never reached the extension. Likely causes, in order: focus is not in an editor (the binding declares editorTextFocus); the chord was typed too slowly and VS Code dropped it; the built-in Change Language Mode command, which also ships on Ctrl+K M, won the key. Check Ctrl+K Ctrl+S → filter ctrl+k m → right-click → "Show Same Keybindings", and rebind if something else owns it. |
| Nothing happens at all |
Open SUS Monitor: показать журнал. Every silent fallback writes its reason there. |
Also available without VS Code
The same monitor builds into a single self-contained HTML file that runs on the Web Serial API — double-click it in Chrome or Edge, no install, no Node. Both targets are generated from one shared core, so features land in both. See the developer README for build instructions.
Roadmap
Ordered roughly by how often the absence of each one gets in the way.
| Planned |
What it changes |
| DWARF 5 backtraces via the toolchain |
Resolve addresses through the PlatformIO toolchain's addr2line when available, falling back to the bundled parser. This is what makes exact file:line work on current ESP-IDF builds. |
| English UI localisation |
Move interface strings into l10n bundles so the palette, toolbar and log follow the editor language. |
| HEX view |
A byte-level view for binary protocols, next to the text terminal. |
| Command history |
Arrow-key recall in the send field, plus saved snippets per project. |
| Warning classification |
A fourth counter next to errors, crashes and reboots. |
| Port profiles |
Remember baud rate, line ending and filter per port, per workspace. |
| Configurable plot parsing |
Plot key:value pairs and named series, so the legend reads like your firmware rather than S1, S2. |
| Per-port counters and charts |
Split error/crash/reboot counters, and optionally the chart, by source port. |
| Arduino CLI support |
Read sketch.yaml the way platformio.ini is read now. |
Ideas and bug reports are welcome at github.com/<OWNER>/<REPO>/issues.
License
MIT
| |