Automation & LLM Tools
The Jumperless V5 is built to be driven by software — by your own scripts, by desktop apps, and by LLM agents (Cursor, Claude Desktop/Code, etc.). This page is the hub for every way to control the board from outside the menu, and a decision guide for picking the right one.
The full hardware/API surface is documented in the MicroPython API Reference — this page is about transport and tooling, not the individual calls.
USB port structure
The Jumperless enumerates as four USB CDC serial interfaces. On macOS they are
named JLV5portN; on Linux they are sequential /dev/ttyACMx; on Windows they
are sequential COMx.
| Port | macOS suffix | Role |
|---|---|---|
| 1 | JLV5port1 |
Main terminal, menu, > one-liner Python, single-char commands |
| 2 | JLV5port3 |
Arduino UART passthrough |
| 3 | JLV5port5 |
MicroPython Raw REPL — primary transport for scripts and the Agent Skill |
| 4 | JLV5port7 |
USBSer3 machine backchannel — :help (YAML), :cmds, read-only status verbs |
[!TIP] The host helper
scripts/jumperless.py detect(in the Agent Skill repo) auto-finds the Raw REPL port and caches it, so you rarely need to name ports by hand.[!NOTE] I will refer to these ports by their index (1st, 2nd, 3rd, 4th), macOS and Linux claim 2 ports per endpoint (one for each direction) so the numbering is 1,3,5,7
Communication methods
1. > Python one-liners (1st / main port)
Prefix a single line of Python with > on the main terminal. Best for quick
checks and single commands.
> connect(1, 5)
> v = adc_get(0)
> print(f"V = {v:.2f}")
2. MicroPython Raw REPL (3rd port)
The canonical transport for anything beyond a one-liner: full scripts, loops,
guided flows. This is what the Agent Skill's jumperless.py and the MCP server
both speak under the hood.
import time
for i in range(10):
print(i, adc_get(0))
time.sleep(0.5)
3. Arduino tags (2nd port, via UART)
From an Arduino connected to the Jumperless headers:
Serial.print("<p>connect(1, 5)</p>"); // run Python
Serial.print("<j>n</j>"); // menu command
4. Single-character commands (1st port)
Raw characters sent to port 1 trigger immediate menu actions — fast state
dumps, board clears, etc. (J = JSON state, x = clear, n = list nets, …).
5. USBSer3 backchannel (4th port) — read-only telemetry
A dedicated machine port that never blocks and never changes state. It speaks two command forms:
- Single characters dispatch instantly:
Afull status,VADC+current,GGPIO,Nnets,KYAML. :verbs read a newline-terminated line::gpio:s,:leds,:crossbar,:adc,:yaml,:every:1ms:100:gpio:s, …
Every command is gated by an access tag; only read-only queries run here, so an agent can poll the board freely without risk of mutating it.
Self-describing :help (YAML)
The backchannel describes itself. Send :help (or a bare :) and it emits a
YAML document — readable straight in a serial terminal, and parseable with
yaml.safe_load():
---YAML_HELP_START---
ser3_help: 1
protocol:
single_char: "Instant dispatch; no line collection. Multi-char modifiers use ':' verbs."
...
verbs:
- name: "gpio:s"
summary: "48-pin GPIO state snapshot"
args: "[float]"
output: "s{<48 0/1[/f]>}"
example: ":gpio:s"
min_us: 20
...
---YAML_HELP_END---
Targeted help is available too:
| Command | Returns |
|---|---|
:help |
Full YAML help document |
:help:<verb> |
One verb's details (e.g. :help:gpio:s) |
:help:<char> |
A single-char command's long help (e.g. :help:c) |
:help:json |
The same content in JSON |
:cmds / :cmds_all |
Machine command list (JSON) — :cmds_all includes blocked commands and their access tags |
A host harness for the backchannel ships with the firmware repo at
scripts/bench_backchannel.py (drives :bench, times verbs).
MCP server
Jumperless-mcp by LesbianVelociraptor
For MCP-native clients (Claude Desktop, Cursor MCP, …), the Jumperless exposes a Model Context Protocol server: a Rust MCP front-end plus a resident Python library on the device. It presents the board's capabilities as typed tools (connections, power, measurement, GPIO/PWM, OLED, overlays, state, …).
It lives as the mcp/ git submodule inside the canonical automation repo,
so one checkout gives you both the Agent Skill and the MCP server:
git clone --recurse-submodules https://github.com/Architeuthis-Flux/Large-Breadboard-Model.git
cd Large-Breadboard-Model/mcp
cargo install --path . # or use a release binary
Point your MCP client at the built binary:
{
"mcpServers": {
"jumperless": {
"command": "/path/to/Large-Breadboard-Model/mcp/target/release/jumperless-mcp"
}
}
}
Exclusive port: the MCP server holds the USB serial port while running. Don't run
jumperless.py(the Agent Skill transport) against the same board at the same time.
Agent Skill
If your agent supports the Agent Skills standard
(Cursor, Claude Code), install the Jumperless V5 skill. It teaches the agent the
device's capabilities and drives it through scripts/jumperless.py over the Raw
REPL, with progressive-disclosure reference docs loaded only as needed.
- On this site: Jumperless V5 Agent Skill
- Canonical source: Architeuthis-Flux/Large-Breadboard-Model
mkdir -p ~/.cursor/skills # or ~/.claude/skills
cd ~/.cursor/skills
git clone --recurse-submodules \
https://github.com/Architeuthis-Flux/Large-Breadboard-Model.git jumperless-v5
Node Map
This file documents the numeric IDs and common names for all key nodes on the Jumperless V5, based on modules/jumperless/modjumperless.c. Use it to translate between human‑readable names (like D13 or TOP_RAIL) and the internal node numbers.
All constants are available in the MicroPython REPL; you normally do not need the numbers directly, but the mapping is useful for mental models and debugging.
Breadboard rows (1–60)
Rows 1–60 represent the breadboard rows along the main area:
1–30— upper half31–60— lower half
Each row corresponds to a vertical strip of 5 holes on the physical board.
Example:
connect(1, 10) # connect top row 1 to top row 10
connect(35, GND) # connect lower half row 35 to ground
DACs and ADCs
Special nodes and supplies
| Name | Aliases | ID | Notes |
|---|---|---|---|
GND |
GROUND |
100 | Global ground net |
TOP_RAIL |
T_R, TOP_R |
101 | Adjustable top rail |
BOTTOM_RAIL |
BOT_RAIL, B_R |
102 | Adjustable bottom rail |
DAC0 |
DAC_0 |
106 | DAC channel 0 * |
DAC1 |
DAC_1 |
107 | DAC channel 1 |
[!CAUTION]
*Avoid using DAC 0 and ROUTABLE_BUFFER_IN because they're used for probe switch sensing
Current sense
| Name | Aliases | ID |
|---|---|---|
ISENSE_PLUS |
ISENSE_POS, ISENSE_P, INA_P, I_P, CURRENT_SENSE_PLUS, I_POS |
108 |
ISENSE_MINUS |
ISENSE_NEG, ISENSE_N, INA_N, I_N, CURRENT_SENSE_MINUS, I_NEG |
109 |
These two nodes are the ends of a 2 Ω shunt resistor and are internally shorted through that shunt; always use them in series with the circuit being measured.
ADC nodes
| Name | Aliases | ID | Notes |
|---|---|---|---|
ADC0 |
ADC_0, ADC0_8V |
110 | ADC channel 0 (±8 V) |
ADC1 |
ADC_1, ADC1_8V |
111 | ADC channel 1 (±8 V) |
ADC2 |
ADC_2, ADC2_8V |
112 | ADC channel 2 (±8 V) |
ADC3 |
ADC_3, ADC3_8V |
113 | ADC channel 3 (±8 V) |
ADC4 |
ADC_4, ADC4_5V |
114 | ADC channel 4 (5 V range) |
ADC7 |
ADC_7, ADC7_PROBE, PROBE |
115 | Probe ADC channel |
User GPIO pins
These are the main user‑accessible GPIOs.
| Name | Aliases | ID | RP2350B Pin | Notes |
|---|---|---|---|---|
GPIO_1 |
RP_GPIO_1, GPIO1, GP_1, GP1 |
131 | 20 | I'm sorry they're 1-indexed like this |
GPIO_2 |
RP_GPIO_2, GPIO2, GP_2, GP2 |
132 | 21 | |
GPIO_3 |
RP_GPIO_3, GPIO3, GP_3, GP3 |
133 | 22 | |
GPIO_4 |
RP_GPIO_4, GPIO4, GP_4, GP4 |
134 | 23 | |
GPIO_5 |
RP_GPIO_5, GPIO5, GP_5, GP5 |
135 | 24 | |
GPIO_6 |
RP_GPIO_6, GPIO6, GP_6, GP6 |
136 | 25 | |
GPIO_7 |
RP_GPIO_7, GPIO7, GP_7, GP7 |
137 | 25 | |
GPIO_8 |
RP_GPIO_8, GPIO8, GP_8, GP8 |
138 | 27 | |
UART_TX |
RP_UART_TX, TX |
116 | 0 | 2nd serial port passthrough |
UART_RX |
RP_UART_RX, RX |
117 | 1 |
When working at the MicroPython level you will usually use GPIO_1–GPIO_8 and the higher‑level GPIO APIs.
Buffer nodes
These correspond to a routable buffer block:
| Name | Aliases | ID |
|---|---|---|
ROUTABLE_BUFFER_IN |
BUFFER_IN, BUF_IN, BUFF_IN, BUFFIN |
139 |
ROUTABLE_BUFFER_OUT |
BUFFER_OUT, BUF_OUT, BUFF_OUT, BUFFOUT |
140 |
[!CAUTION]
*Avoid using DAC 0 and ROUTABLE_BUFFER_IN because they're used for probe switch sensing
Arduino Nano header
The Nano header pins are mapped as follows:
| Name | Aliases | ID | Routable? | Notes |
|---|---|---|---|---|
NANO_VIN |
VIN |
69 | N | |
NANO_D0 |
D0 |
70 | Y | |
NANO_D1 |
D1 |
71 | Y | |
NANO_D2 |
D2 |
72 | Y | |
NANO_D3 |
D3 |
73 | Y | |
NANO_D4 |
D4 |
74 | Y | |
NANO_D5 |
D5 |
75 | Y | |
NANO_D6 |
D6 |
76 | Y | |
NANO_D7 |
D7 |
77 | Y | |
NANO_D9 |
D9 |
79 | Y | |
NANO_D10 |
D10 |
80 | Y | |
NANO_D11 |
D11 |
81 | Y | |
NANO_D12 |
D12 |
82 | Y | |
NANO_D13 |
D13 |
83 | Y | |
NANO_AREF |
AREF |
85 | Y | |
NANO_A0 |
A0 |
86 | Y | |
NANO_A1 |
A1 |
87 | Y | |
NANO_A2 |
A2 |
88 | Y | |
NANO_A3 |
A3 |
89 | Y | |
NANO_A4 |
A4 |
90 | Y | |
NANO_A5 |
A5 |
91 | Y | |
NANO_A6 |
A6 |
92 | Y | |
NANO_A7 |
A7 |
93 | Y | |
NANO_RESET_0 |
RST0 |
94 | N | Wired directly to RP2350B pin 18 |
NANO_RESET_1 |
RST1 |
95 | N | PSRAM Mod kits use this as CS (pin 19) |
NANO_GND_1 |
N_GND1 |
96 | N | |
NANO_GND_0 |
N_GND0 |
97 | N | |
NANO_3V3 |
98 | N | ||
NANO_5V |
99 | N |
These nodes let you route signals between the RP2350, the breadboard, and any compatible Nano‑footprint dev board (classic Nano, Nano ESP32, Nano RP2040 Connect, etc.).
Rail pads
Special nodes representing where the probe can tap the rails:
| Name | Aliases | ID |
|---|---|---|
TOP_RAIL |
TOP_RAIL_PAD |
101 |
BOTTOM_RAIL |
BOTTOM_RAIL_PAD |
102 |
TOP_RAIL_GND |
TOP_GND_PAD |
104 |
BOTTOM_RAIL_GND |
BOT_RAIL_GND, BOTTOM_GND_PAD |
126 |
Breadboard layout (high‑level)
The board follows a standard half‑size breadboard geometry:
-
Nano header at the top:
- Top row:
D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 GND RST1 D0 D1 - Second row:
D13 3V3 REF A0 A1 A2 A3 A4 A5 A6 A7 5V RST0 GND VIN
- Top row:
-
Top power rail:
TOP_RAILGND
-
Breadboard rows:
- Rows
1–30— upper half, between the top rails and the center gap - Rows
31–60— lower half, between the center gap and the bottom rails
- Rows
-
Bottom power rail:
BOTTOM_RAILGND
An ASCII diagram (from the docs) approximates the layout; the agent should treat rows and rails as in any typical solderless breadboard, with the addition that every hole has an individually controllable RGB LED.
DIP ICs straddling the center gap
A DIP chip (555, op-amp, logic, …) sits across the center gap, with each side in
a different breadboard half. The two halves are independent rows, so the two
sides of the chip map to numerically distant nodes. For a chip whose first pin
sits at upper-half row N, the upper-side pins run N, N+1, … and the
lower-side pins run from the row directly across the gap (N+30).
Worked example — an 8-pin DIP (e.g. a 555) with pin 1 at row 1:
| Pin | Node | Pin | Node |
|---|---|---|---|
| 1 | 1 |
8 | 31 |
| 2 | 2 |
7 | 32 |
| 3 | 3 |
6 | 33 |
| 4 | 4 |
5 | 34 |
Pins 1–4 are on the upper side (rows 1–4); pins 5–8 are across the gap on the lower side (rows 34→31, counting back toward pin 1). Adjust the base row to wherever the chip is actually placed; verify with the probe or a measurement when unsure.
How to use this map
- Prefer named constants like
D13,TOP_RAIL,GPIO_1,ADC0,ISENSE_PLUSwhen generating code. - Use the numeric IDs only when inspecting low‑level debugging output or when matching numeric IDs in
get_state()/get_net_info()results. - When the user describes physical positions (“top rail”, “bottom left rail”, “row 25”), translate them into these node names/IDs before constructing
connect(...)commands.
JSON State Format
The function get_state() returns a JSON string describing the entire board state: power rails, nets, GPIOs, and overlays. set_state(json_str, clear_first=True, from_wokwi=False) applies such a state.
[!NOTE] The entire immediate state of the board is defined in this JSON (or YAML) slot file and can be shared to another Jumperless, saved as a backups, included in tutorials, etc.
This file explains the structure so agents can safely inspect, modify, and re‑apply state.
Top-level structure
A typical get_state() JSON (pretty‑printed) looks like:
{
"power": {
"top_rail": 3.8,
"bottom_rail": 3.8,
"dac0": 3.25,
"dac1": 0.0
},
"nets": [
{
"index": 1,
"name": "GND",
"nodes": ["GND", "21"],
"special": "none"
},
{
"index": 2,
"name": "Top Rail",
"nodes": ["TOP_R", "23"],
"special": "RAIL",
"voltage": 3.8
}
// ...
],
"gpio": [
{
"pin": 1,
"net": null,
"function": "SIO",
"direction": "INPUT",
"pull": "down",
"reading": "unknown",
"floating_read": 1
},
{
"pin": "TX",
"net": 7,
"function": "UART",
"direction": "OUTPUT",
"pull": "down",
"reading": "unknown",
"floating_read": 0
}
],
"overlays": [
{
"name": "border",
"row": 1,
"col": 1,
"width": 30,
"height": 10,
"colors": ["003333", "003333", "..."]
}
]
}
There may be additional keys in future firmware versions; agents should not assume the set of keys is fixed and should preserve unknown keys when round‑tripping.
power section
"power": {
"top_rail": 3.8,
"bottom_rail": 3.8,
"dac0": 3.25,
"dac1": 0.0
}
Fields:
top_rail— voltage (float) configured forTOP_RAILbottom_rail— voltage configured forBOTTOM_RAILdac0,dac1— DAC channel setpoints
When using set_state, changing these values is equivalent to calling dac_set() on the corresponding channels.
nets section
Each item describes a net (set of nodes that are electrically connected inside the crossbar).
Example:
{
"index": 4,
"name": "DAC 0",
"nodes": ["DAC_0", "BUF_IN"],
"special": "DAC",
"voltage": 3.25
}
Fields:
index— numeric net indexname— human‑readable net name (may be auto‑generated or user‑defined)nodes— array of node names (strings), such as"GND","TOP_R","21","D13", etc.- These names correspond to the mapping in
reference/node-map.md. special— optional annotation for special nets; typical values:"none"— normal net"RAIL"— power rail (top or bottom)"DAC"— DAC output net"UART_TX"/"UART_RX"— UART nets- Other firmware‑defined markers
voltage— optional; expected or configured voltage on this net (when known)- Other fields (like
color,anim, etc.) may be present and should be preserved.
Important: nets describes logical groupings of nodes. It is not a direct list of bridges; bridges are derived from the crossbar configuration internally.
gpio section
Each entry describes one logical GPIO:
{
"pin": 1,
"net": null,
"function": "SIO",
"direction": "INPUT",
"pull": "down",
"reading": "unknown",
"floating_read": 1
}
Fields:
pin— either:- An integer
1–8forGPIO_1–GPIO_8 "TX"or"RX"for the UART pinsnet— net index this pin is connected to (ornullif unconnected)function— textual description of function:"SIO"— standard GPIO"UART"— UART TX/RX- Other firmware‑defined roles
direction—"INPUT"or"OUTPUT"pull—"up","down", or"none"reading— textual summary of the last known logic state ("high","low","unknown", etc.)floating_read— boolean (0/1) indicating whether floating detection is enabled
Agents can inspect this section to understand logical GPIO usage, but should generally change GPIO configuration via the MicroPython APIs (gpio_set_dir, gpio_set_pull, etc.) rather than editing this JSON directly.
overlays section
Overlays describe additional graphics drawn on the breadboard RGB LEDs. They are rendered on top of the firmware’s net coloring.
Example:
{
"name": "border",
"row": 1,
"col": 1,
"width": 30,
"height": 10,
"colors": [
"003333", "003333", "...",
"003333", "000000", "...",
"... more hex color strings ..."
]
}
Fields:
name— overlay name (string)row— top row (1–10)col— left column (1–30)width— width in columnsheight— height in rowscolors— flat array of hex color strings without0xprefix, e.g."003333","FF2020"- Length =
width * height - Order is row‑major: top row left→right, then next row down, etc.
"000000"means “transparent” — do not override underlying LED color
Brightness recommendation:
- Avoid full‑scale white
FFFFFF. - Prefer saturated colors with reduced magnitude (~25%): e.g.
2020FF,20FF20,FF2020,404040.
When editing overlays via JSON:
- Always maintain the correct
width * heightnumber of color entries. - Preserve unknown fields if present.
- Ensure that
row,col,width, andheightkeep the overlay within the 5×60 canvas (rows 1–10, columns 1–30).
Often it is easier to use the MicroPython overlay APIs (overlay_set, overlay_clear, etc.) directly instead of editing overlays in the state JSON manually. The JSON is still useful for inspection and for bulk export/import of complex scenes.
Editing state safely
General guidelines:
- Fetch once, apply locally.
- Call
get_state()and parse the JSON in the host environment. -
Keep this as your “baseline” snapshot.
-
Work on a copy.
- Clone the baseline object before modifying it.
-
Preserve unknown fields.
-
Modify only what you care about.
- For power: update
power.top_rail,power.dac0, etc. - For overlays: add or replace specific entries in
overlays. -
Avoid rewriting
netsunless you fully understand the implications; it is often better to useconnect()/disconnect()APIs to modify connectivity. -
Re‑serialize and apply.
- Use a standard JSON encoder.
- Call
set_state(json_string, clear_first=True)when applying a complete, authoritative state. -
If you are only adding overlays or adjusting power but want to preserve dynamic routing changes, you may choose
clear_first=False(if supported and appropriate) or modify only overlays via MicroPython functions. -
Rollback on problems.
- If
set_stateleads to unexpected behavior, re‑apply the saved baseline snapshot.
Example: adjusting top rail voltage via state
Instead of:
dac_set(TOP_RAIL, 5.0)
You can do:
import json
state = json.loads(get_state())
state["power"]["top_rail"] = 5.0
set_state(json.dumps(state))
This approach is useful when batching multiple changes (e.g. updating both rail voltages and overlays) in a single atomic operation.
Example: augmenting overlays
Suppose get_state() returns a state with existing overlays, and you want to add a new “place‑here” marker at row 3, column 10:
import json
state = json.loads(get_state())
# Create a 1×1 overlay with a bright but not full‑scale green
place_here = {
"name": "place_here_row3_col10",
"row": 3,
"col": 10,
"width": 1,
"height": 1,
"colors": ["20FF20"]
}
state.setdefault("overlays", [])
state["overlays"] = [
o for o in state["overlays"] if o.get("name") != place_here["name"]
] + [place_here]
set_state(json.dumps(state))
This pattern:
- Preserves existing overlays.
- Replaces any prior overlay with the same name.
- Leaves other state fields untouched.
Wokwi import (from_wokwi=True)
When from_wokwi=True, set_state() expects json_str to be a Wokwi diagram.json rather than a Jumperless state JSON. The firmware converts the Wokwi representation into bridges, nets, and colors.
Agents can:
- Ask the user to paste a Wokwi JSON.
- Pass it directly to
set_state(wokwi_json, clear_first=True, from_wokwi=True).
After that, a subsequent get_state() will return the standard Jumperless state JSON.
Robustness tips for agents
- Treat
get_state()as authoritative for the current internal configuration, but always cross‑check against the user’s description of external wiring and components. - Always preserve unknown keys when editing state; future firmware versions may add fields.
- Prefer using high‑level MicroPython APIs (
connect,disconnect,dac_set,overlay_set, etc.) for incremental changes, and use state JSON editing for bulk or offline transformations (import/export, heavy refactoring, or pre‑computed overlays).
MicroPython tool reference (subset)
The complete, authoritative list is the MicroPython API Reference. The most common calls for automation:
| Category | Key tools |
|---|---|
| Connections | connect(), disconnect(), nodes_clear(), is_connected(), fast_connect() |
| Slots | nodes_save(slot), switch_slot(slot), get_current_slot() |
| State | get_state(), set_state(json, clear_first=True) |
| Voltage | dac_set(ch, v), dac_get(ch) |
| Measurement | adc_get(ch), ina_get_current(s), ina_get_voltage(s), ina_get_power(s) |
| GPIO / PWM | gpio_set(), gpio_get(), gpio_set_dir(), gpio_set_pull(), pwm(), pwm_stop() |
| WaveGen | wavegen_set_wave(), wavegen_set_freq(), wavegen_set_amplitude(), wavegen_start() |
| UI | oled_print(), oled_clear(), probe_read_blocking(), probe_button(), clickwheel_get_button() |
| LED overlays | overlay_set(), overlay_set_pixel(), overlay_clear(), overlay_clear_all() |
| Net inspection | get_net_info(), get_num_nets(), print_nets(), print_bridges() |
Node addressing (quick form)
- Breadboard rows:
1–60 - Rails / supplies:
TOP_RAIL,BOTTOM_RAIL,GND,DAC0,DAC1 - Arduino:
D0–D13,A0–A7,AREF,RESET - GPIO:
GPIO_1–GPIO_8,UART_TX,UART_RX - Measurement:
ADC0–ADC3,ISENSE_PLUS,ISENSE_MINUS
A mental model for LLM agents
The Jumperless prevents internal shorts, but cannot see external wires or components physically on the breadboard. An agent should maintain a model of what it believes is on the board and raise confidence through measurement and user confirmation.
A lightweight per-component record works well:
{
"id": "comp_001",
"type": "resistor",
"value": 1000,
"pins": [5, 10],
"confidence": 0.95,
"detection_method": "measured",
"notes": "Measured 987Ω between rows 5-10"
}
| Confidence | Source | Meaning |
|---|---|---|
| 1.0 | measured |
Electrically verified |
| 0.9 | user_confirmed |
User explicitly confirmed |
| 0.7 | user_stated |
User mentioned it casually |
| 0.5 | inferred |
Guessed from context |
| 0.3 | assumed |
Default assumption |
Workflows
Safe power-up. Before energizing an unknown board, ask what's on it, build a
low-confidence model, then verify key rows with an ADC before connecting power —
a hidden user wire between two rows can turn TOP_RAIL + GND into a dead
short.
Identify with the probe. Use probe_read_blocking() to let the user point
at a node, then route an ADC to it and measure.
Characterize as a black box. Drive a node with the WaveGen / DAC and sweep while reading an ADC.
Batch edits via state. Fetch get_state(), mutate the JSON in Python, and
re-apply with set_state() — one atomic round-trip instead of many calls.
Undo via a scratch slot. Before destructive ops like nodes_clear(), save
to an unused slot (e.g. nodes_save(7)); restore with switch_slot(7).
Safety guidelines
- Voltage range. ADC0–ADC3 are buffered for ±8V; the board is ±9V tolerant overall.
- Short protection. The firmware refuses dangerous internal connections
(e.g.
TOP_RAILdirectly toGND), but cannot see external wiring. - Confirm power. The board is USB-powered (no barrel jack); ask if unsure.
- Crossbar resistance. ~ 20–40Ω per default
connect()path (~ 80Ω with a single path). Measure voltage at the destination to compensate for drop. - Settling time. Allow a few ms after routing/DAC changes (50–100 ms after
nodes_clear()/set_state()) before measuring.
Implementation status
| Feature | Status |
|---|---|
connect(), disconnect(), is_connected() |
Implemented |
dac_set(), adc_get(), ina_*() |
Implemented |
gpio_*(), pwm() |
Implemented |
oled_print(), probe_*() |
Implemented |
| WaveGen tools | Implemented |
| Slot management | Implemented |
get_state() / set_state() snapshot |
Implemented |
adc_get_stats() (averaged sampling) |
Available via the MCP server |
| Slot backup for undo | Implemented (nodes_save(7) before destructive ops) |
USBSer3 :help self-describing backchannel |
Implemented (firmware) |