What it does
PinScope is a browser console for embedded boards that speak a small
JSON wire protocol. You flash a firmware sketch onto the board (one of
three variants ship with the repo: serial, BLE, MQTT). You open
pinscope.html in any modern browser. The page connects
over the transport you chose and gives you a live view of every digital
and analog pin, plus everything the firmware can do with them.
It is single-file by design. Once the page loads, it makes no further network requests. You can serve it from a Raspberry Pi, drop it on a USB stick, save it to a thumb drive for offline field work, embed it inside a CI run, or pin it to localhost. It runs anywhere a Chromium browser does.
What you get
Pin Control
Click any digital pin's mode badge to cycle through input, input-pullup, output, PWM, or interrupt-counting FREQ mode. Outputs toggle on click; PWM pins get a duty slider.
Strip Chart
Up to 14 channels at once with per-trace stats, calibration in real units, threshold alerts, CSV one-shot and streaming export, PNG snapshots, capture and replay.
FFT & Spectrogram
Magnitude spectrum and rolling waterfall for any analog or virtual channel. Hann, Hamming, and Blackman windows. Log or linear scaling.
I2C Scanner
SCAN BUS highlights every responding I2C address on a 16×8 grid. Read or write any register. Four polling slots feed I2C registers into virtual channels at up to 50 Hz.
Sensor Library
One-click presets for TMP102, TMP117, MCP9808, DS3231, INA219, APDS-9301, PCF8591. Sensible defaults and unit-conversion math pre-filled.
Cross-pin Math
Derive a virtual channel from any expression of other channels.
Differential measurements, magnitude of XY pairs, unit
conversions, anything new Function() can compile.
Calibration Wizard
Two-point fit. Apply a known reference, click CAPTURE LOW. Apply the high reference, CAPTURE HIGH. PinScope computes slope and offset and shows a live preview.
Scope Trigger
Rising, falling, above, or below threshold. Configurable pre and post windows. The chart freezes onto the captured event with a red fire line and threshold marker.
Baseline & Diff
Load a previously captured run as a faded ghost trace overlay. Toggle a live-minus-baseline diff trace on top. Catch regressions between hardware revisions.
Scripted Automation
A sandboxed JS subset for repeatable test sequences. Loops, awaits, asserts, all blocked from touching anything outside the device. Source auto-saves to the session.
Plugin System
Load extensions that get their own panel on every device card. Sandboxed iframes, postMessage bridge, persistent per-device state. Four example plugins ship with the repo.
Session Diff
Compare your current device's config against a saved JSON file. Calibrations changed, alerts added or removed, scripts edited, plugin state changed: see exactly what differs.
Supported boards
| Board | Serial | BLE | WiFi / MQTT |
|---|---|---|---|
| Arduino Uno R3 (any AVR) | Yes | No | Via bridge |
| Arduino Nano 33 IoT | Yes | Yes | Yes |
| Arduino Uno R4 WiFi | Yes | Yes | Via bridge |
| Arduino Uno Q | Yes | Experimental | Via bridge |
Any board that speaks the wire protocol over a transport PinScope
understands will work. The provided pinscope.ino firmware
detects the host MCU at compile time and adapts the ADC resolution,
name, and capability set automatically.
Quick start
git clone https://github.com/mbparks/pinscope.git
cd pinscope
open pinscope.html # macOS
xdg-open pinscope.html # Linux
start pinscope.html # Windows
No install for the browser side. The Arduino firmwares need arduino-cli or the Arduino IDE 2.x. See the bring-up walkthrough for board-specific setup.
Design principles
PinScope is built around a few rules that produced everything else. They are worth knowing if you want to extend it or fork it.
- One file, no build.
pinscope.htmlis around 6300 lines of HTML, CSS, and JavaScript in one document. It has no runtime dependencies, fetches nothing, runs fromfile://or any static server. - Wire protocol is trivial. JSON objects, one per line, over whatever transport you have. Any embedded developer can speak it from a fresh sketch in an hour.
- The firmware is dumb. All visualization, math, calibration, alerts, and analysis live in the browser. The board just reads and writes pins and reports state.
- Sessions persist. Every device card's full configuration, calibrations, alerts, math, plugin state, all of it, round-trips through a JSON file. No surprises on reload.
- Plugins are sandboxed. Extensions run inside iframes with no DOM access outside their panel. The host never runs plugin code with privileges.
- The aesthetic is intentional. Amber on black, monospace, dense, sparse. PinScope is a tool you use in the garage at 11 PM with a soldering iron next to it. It should look like one.
Learn more
- Full feature reference
- Plugin API and example plugins
- Hardware bring-up walkthrough (Arduino Uno Q on macOS)
- Source on GitHub
- Contributing