Operates a Jumperless V5 breadboard for hardware-in-the-loop prototyping and debugging. Uses MicroPython REPL to route connections, set rails/DACs, perform measurements, control GPIO/PWM/OLED/LED overlays, and run guided test scripts. Use when the user mentions Jumperless, breadboard wiring, circuit testing, hardware debugging, or voltage/current/resistance measurements on physical hardware.
This skill controls real Jumperless V5 hardware via MicroPython REPL.
Working directory for all commands:
/Users/kevinsanto/Documents/GitHub/Large Breadboard Model
python scripts/jumperless.py ... — execute it directly. The user should only be asked to perform physical actions (place/move parts, press probe/clickwheel).connect() / / : wait at least 2–10 ms ( to ) before reading ADC or INA values.disconnect()dac_set()time.sleep_ms(2)time.sleep_ms(10)nodes_clear() or set_state(): wait 50–100 ms.get_state() and restore if needed.Always keep these in mind — even in the middle of a specific task, a different peripheral may be the better tool:
| Capability | Key APIs | When to reach for it |
|---|---|---|
| Virtual wiring | connect(), disconnect(), fast_connect(), nodes_clear() | Any routing change on the crossbar |
| Voltage measurement | adc_get(ch) with ADC0–ADC3 (±8V), ADC4 (5V), ADC7/PROBE | Checking node voltages; always route ADC to node first |
| Current measurement | ina_get_current(sensor), ina_get_bus_voltage(sensor) | Put ISENSE_PLUS/ISENSE_MINUS in series; 2Ω shunt |
| Power measurement | ina_get_power(sensor) | Quick power draw check on a rail |
| Programmable voltage | dac_set(ch, v) — DAC0, DAC1, TOP_RAIL, BOTTOM_RAIL (±8V) | Supplying test voltages, driving circuits, sweeps |
| Resistance estimation | DAC + INA + ADC combined (see measurement workflow) | Use adaptive DAC voltage for best accuracy |
| Digital I/O | gpio_set(), gpio_get(), gpio_set_dir(), gpio_set_pull() | Driving/reading logic signals on GPIO_1–GPIO_8 |
| PWM output | pwm(pin, freq, duty), pwm_stop(pin) | Generating clock/PWM signals |
| UART passthrough | UART_TX, UART_RX nodes (routable) | Talking to Arduino/Nano or serial peripherals |
| LED guidance | overlay_set(), overlay_set_pixel(), overlay_clear() | Visual cues on breadboard; use reduced-brightness colors |
| OLED display | oled_print(), oled_clear() | Showing measurement results or step instructions |
| Probe input | probe_read_blocking(), probe_button() | User touching a specific pad, button-gated steps |
| Clickwheel | clickwheel_get_button(), clickwheel_get_position() | User menu/scroll/confirm interactions |
| State snapshot | get_state() / set_state() | Bulk save/restore, Wokwi import, batch edits |
| Net inspection | get_net_info(), is_connected(), print_nets() | Debugging unexpected routing |
| Filesystem | jfs.open(), jfs.listdir(), jfs.exists() | Reading/writing files on the device |
| Arduino reset | arduino_reset() | Resetting a Nano-header MCU |
| Slots | nodes_save(slot), switch_slot(slot) | Storing/recalling circuit configurations |
| Context | context_get(), context_toggle() | python context rolls back on exit; global persists |
Think creatively: If measuring resistance, consider whether INA-based, ADC-based, or mixed approaches suit the range best. If debugging a circuit, you can probe multiple nodes with different ADC channels simultaneously. If a user needs a clock signal, reach for PWM instead of bit-banging GPIO.
Before any hardware interaction, ensure connectivity:
pip install pyserial
python scripts/jumperless.py detect
python scripts/jumperless.py exec "print('ok from jumperless')"
If detect succeeds, the port is cached in .jumperless_port for subsequent calls.
Prefer these modes in order:
python scripts/jumperless.py exec "connect(1, D4)"
python scripts/jumperless.py exec --file scripts/session.py
python scripts/jumperless.py exec --stdin <<'PYEOF'
import time
connect(ADC0, 5)
time.sleep(0.05)
v = adc_get(0)
disconnect(ADC0, -1)
print(v)
PYEOF
For complex logic, write a temporary .py file and use --file. Do not cram long multi-line logic into shell-quoted one-liners.
Use --timeout N when scripts take longer than the default 8 seconds (e.g. continuous monitors, guided flows).
Loop scripts run on the device in MicroPython. The host exec process exits as soon as it finishes sending the script — the serial port is already free. The MicroPython loop keeps running on the Jumperless itself.
To stop it and send a new version:
1. Write the updated script to the file.
2. Run exec with the updated file.
enter_raw_repl() automatically sends a double Ctrl-C (\x03\x03) to the device before sending any new code, interrupting whatever MicroPython loop is currently running.
python scripts/jumperless.py exec --file scripts/my_loop.py --timeout 300
That's it — no process killing needed.
3. Start every loop script with a cleanup header.
The interrupted script may have left connections, overlays, or OLED content mid-run. Always reset to a known state at the top:
import time
nodes_clear()
overlay_clear_all()
oled_clear()
time.sleep(0.05) # let crossbar settle after clear
Background long-running loops with block_until_ms: 0 so the shell doesn't block waiting for them to finish.
Build these into every script. The crossbar routing fabric and DAC output stages need time to stabilize.
import time
# After making connections
connect(ADC0, 5)
connect(DAC1, ISENSE_PLUS)
time.sleep(0.05) # 50ms settle
# After changing DAC/rail voltage
dac_set(TOP_RAIL, 3.3)
time.sleep(0.02) # 20ms for DAC to reach setpoint
# After bulk state changes
set_state(new_state)
time.sleep(0.1) # 100ms for full state application
# For multi-sample measurements, small inter-sample delay
for _ in range(16):
v = adc_get(0)
samples.append(v)
time.sleep(0.01) # 10ms between samples
Whenever the user needs to place, move, or remove something physical, run an overlay script before asking. The board shows them exactly where to go; OLED echoes the instruction in text.
The LED canvas is rows 1–10, cols 1–30:
Breadboard row N → overlay col N (top half, N 1–30) or col N−30 (bottom half, N 31–60). The 5 holes A–E in each strip correspond to overlay rows 1–5 (top) or 6–10 (bottom).
Single component / pin — use place_here() + oled_print():
import time
# Mark a single hole bright red, tell user on OLED
overlay_set_pixel(3, 10, 0xFF2020) # direct: row 3, col 10
# — or using animations helper if loaded —
place_here("target_pin", 3, 10, 0xFF2020)
oled_clear()
oled_print("Place R1 pin 1")
oled_print("Row 10, top half")
IC spanning multiple rows — use highlight_range() for the body, place_here() per pin:
# IC body across breadboard rows 5-12 (top half → overlay cols 5-12)
highlight_range("ic_body", 1, 1, 0x203030) # single overlay row, cols 5-12
# Pin 1 marker
place_here("ic_pin1", 2, 5, 0xFF2020)
oled_clear()
oled_print("Place 555 timer")
oled_print("Pin 1 at row 5")
Span of rows (e.g. resistor leg to leg):
# Highlight rows 5 and 15 where resistor legs go
place_here("r1_a", 1, 5, 0xFF8000)
place_here("r1_b", 1, 15, 0xFF8000)
oled_clear()
oled_print("Place R1: row 5 to 15")
Removal / "move this wire":
# Use a different color (e.g. red pulsing) to mark what to remove
highlight_row("remove_wire", 3, 0xFF2020)
oled_clear()
oled_print("Remove wire at row 3")
After the user confirms placement (probe button, clickwheel, or verbal confirmation), clear the guidance overlays so they don't obscure net colors:
overlay_clear("target_pin")
overlay_clear("ic_body")
# — or wipe everything —
overlay_clear_all()
oled_clear()
When using jumperless.py guide, run a matching overlay script immediately before each button-wait so the board lights up with the current step's target location. Use overlay_clear_all() at the start of each step to remove the previous step's marks.
Choose based on the task, then read only the files needed. But stay aware of the full capabilities table above — better solutions may combine peripherals across workflows.
Connectivity / rewiring
reference/node-map.md → reference/api/connections-routing.mdfast_connect() / fast_disconnect() for batch operations (skips LED updates)Measurement (V/I/R, sweeps)
reference/api/measurements-power.mdscripts/measurements.py, measureR.pyconnect(), ~80Ω with duplicates=0) and 2Ω ISENSE shuntVisual guidance (LEDs, OLED) — mandatory any time you ask for physical action
reference/api/ui-interaction-system.md → scripts/animations.py0x2020FF, not 0x0000FF)0x000000 = transparent in overlays; always overlay_clear_all() after step completesState surgery / batch edits
reference/state-format.md → reference/api/state-nets-filesystem.mdGuided human-in-the-loop flows
python scripts/jumperless.py guide --file steps.txtOnly load reference/api-reference.md when a task spans multiple API domains.
For transport/hanging issues, load reference/repl-runtime-playbook.md.
# Snapshot full state
python scripts/jumperless.py state
# Execute a script file
python scripts/jumperless.py exec --file scripts/session.py
# List device filesystem
python scripts/jumperless.py fs
# Longer timeout for continuous scripts
python scripts/jumperless.py exec --file scripts/measureR.py --timeout 60
import time
connect(ADC0, 5)
time.sleep(0.05)
samples = [adc_get(0) for _ in range(8)]
v_avg = sum(samples) / len(samples)
print("V at row 5:", v_avg)
disconnect(ADC0, -1)
measureR.py)if R_prev is None: v_set = 2.0
elif R_prev < 200: v_set = 0.5
elif R_prev < 1000: v_set = 1.5
elif R_prev < 5000: v_set = 2.5