45 KiB
Example Scripts Reference
Collection of practical, ready-to-use Python scripts for common Jumperless tasks and applications.
Overview
This reference provides complete, working examples that demonstrate the capabilities of the Jumperless system. All scripts are designed to run directly in the MicroPython REPL or be saved as .py
files for repeated use.
Script Categories
- Basic Examples
- Hardware Testing
- Measurement and Monitoring
- Signal Generation
- Interactive Applications
- Circuit Templates
- Advanced Applications
- Utility Scripts
Basic Examples
Hello World
Simple introduction to Jumperless control.
import jumperless
import time
# Display welcome message
jumperless.oled_print("Hello Jumperless!")
# Create a simple connection
jumperless.connect("D2", "A0")
print("Connected D2 to A0")
# Set a voltage
jumperless.dac_set(0, 3.3)
print("DAC0 set to 3.3V")
# Read it back
voltage = jumperless.adc_get(0)
print(f"ADC0 reads: {voltage:.3f}V")
# Clean up
jumperless.nodes_clear()
print("All connections cleared")
LED Blink
Classic blinking LED using GPIO.
import jumperless
import time
# Setup
jumperless.gpio_set_dir(1, True) # Set GPIO 1 as output
jumperless.connect("GPIO_1", "10") # Connect to breadboard hole 10
print("Blinking LED on GPIO 1...")
print("Connect LED from hole 10 to GND with current limiting resistor")
# Blink 10 times
for i in range(10):
jumperless.gpio_set(1, True) # LED on
time.sleep(0.5)
jumperless.gpio_set(1, False) # LED off
time.sleep(0.5)
print(f"Blink {i+1}")
print("Blinking complete")
Button and LED
Interactive button control with LED feedback.
import jumperless
import time
# Setup button input
jumperless.gpio_set_dir(1, False) # GPIO 1 as input
jumperless.gpio_set_pull(1, 1) # Enable pull-up
jumperless.connect("GPIO_1", "15") # Connect button to hole 15
# Setup LED output
jumperless.gpio_set_dir(2, True) # GPIO 2 as output
jumperless.connect("GPIO_2", "10") # Connect LED to hole 10
print("Button and LED Demo")
print("Connect button from hole 15 to GND")
print("Connect LED from hole 10 to GND with resistor")
print("Press Ctrl+C to exit")
led_state = False
try:
while True:
# Read button (LOW when pressed due to pull-up)
button_pressed = jumperless.gpio_get(1) == "LOW"
if button_pressed:
led_state = not led_state # Toggle LED
jumperless.gpio_set(2, led_state)
print(f"Button pressed! LED {'ON' if led_state else 'OFF'}")
time.sleep(0.3) # Debounce delay
time.sleep(0.1)
except KeyboardInterrupt:
print("\nDemo stopped")
jumperless.gpio_set(2, False) # Turn off LED
Hardware Testing
System Diagnostics
Comprehensive hardware test suite.
import jumperless
import time
def test_dacs():
"""Test all DAC channels"""
print("=== Testing DACs ===")
test_voltages = [0.0, 1.0, 2.5, 3.3, -1.0, -2.5]
for channel in range(4):
print(f"Testing DAC {channel}:")
for voltage in test_voltages:
try:
jumperless.dac_set(channel, voltage)
actual = jumperless.dac_get(channel)
error = abs(actual - voltage)
status = "PASS" if error < 0.1 else "FAIL"
print(f" {voltage:+5.1f}V -> {actual:+5.1f}V [{status}]")
time.sleep(0.1)
except Exception as e:
print(f" {voltage:+5.1f}V -> ERROR: {e}")
print()
def test_adcs():
"""Test all ADC channels"""
print("=== Testing ADCs ===")
for channel in range(5):
try:
voltage = jumperless.adc_get(channel)
print(f"ADC {channel}: {voltage:+6.3f}V")
except Exception as e:
print(f"ADC {channel}: ERROR - {e}")
print()
def test_gpio():
"""Test GPIO pins"""
print("=== Testing GPIO ===")
for pin in range(1, 9):
try:
# Test as output
jumperless.gpio_set_dir(pin, True)
jumperless.gpio_set(pin, True)
state_high = jumperless.gpio_get(pin)
jumperless.gpio_set(pin, False)
state_low = jumperless.gpio_get(pin)
# Test as input with pull-up
jumperless.gpio_set_dir(pin, False)
jumperless.gpio_set_pull(pin, 1)
state_pulled = jumperless.gpio_get(pin)
print(f"GPIO {pin}: OUT_H={state_high}, OUT_L={state_low}, IN_PU={state_pulled}")
except Exception as e:
print(f"GPIO {pin}: ERROR - {e}")
print()
def test_current_sensors():
"""Test current monitoring"""
print("=== Testing Current Sensors ===")
for sensor in range(2):
try:
current = jumperless.ina_get_current(sensor)
voltage = jumperless.ina_get_bus_voltage(sensor)
power = jumperless.ina_get_power(sensor)
print(f"INA {sensor}: {current:+7.3f}A, {voltage:+6.2f}V, {power:+7.3f}W")
except Exception as e:
print(f"INA {sensor}: ERROR - {e}")
print()
def test_connections():
"""Test connection system"""
print("=== Testing Connections ===")
test_pairs = [
("1", "2"),
("D2", "A0"),
("GPIO_1", "10"),
("GND", "30")
]
for node1, node2 in test_pairs:
try:
# Connect
jumperless.connect(node1, node2)
connected = jumperless.is_connected(node1, node2)
# Disconnect
jumperless.disconnect(node1, node2)
disconnected = not jumperless.is_connected(node1, node2)
status = "PASS" if connected and disconnected else "FAIL"
print(f"{node1:>8} <-> {node2:<8}: {status}")
except Exception as e:
print(f"{node1:>8} <-> {node2:<8}: ERROR - {e}")
print()
# Run all tests
def run_diagnostics():
print("Jumperless Hardware Diagnostics")
print("=" * 40)
test_dacs()
test_adcs()
test_gpio()
test_current_sensors()
test_connections()
print("Diagnostics complete!")
# Execute tests
run_diagnostics()
Loopback Test
Test DAC to ADC signal path.
import jumperless
import time
def dac_adc_loopback_test():
"""Test DAC output accuracy using ADC loopback"""
print("DAC-ADC Loopback Test")
print("Connecting DAC0 to ADC0...")
# Create loopback connection
jumperless.connect("DAC0", "ADC0")
time.sleep(0.1) # Settle time
test_voltages = [-5.0, -2.5, -1.0, 0.0, 1.0, 2.5, 3.3, 5.0]
print("Voltage DAC Set ADC Read Error")
print("-" * 40)
max_error = 0.0
for voltage in test_voltages:
# Set DAC voltage
jumperless.dac_set(0, voltage)
time.sleep(0.05) # Settling time
# Read back from ADC
measured = jumperless.adc_get(0)
error = abs(measured - voltage)
max_error = max(max_error, error)
print(f"{voltage:+6.1f}V {voltage:+6.1f}V {measured:+6.3f}V {error:+6.3f}V")
print("-" * 40)
print(f"Maximum error: {max_error:.3f}V")
if max_error < 0.1:
print("✓ PASS: Loopback test successful")
else:
print("✗ FAIL: High error detected")
# Clean up
jumperless.disconnect("DAC0", "ADC0")
dac_adc_loopback_test()
Measurement and Monitoring
Voltage Logger
Log voltages to display trends.
import jumperless
import time
def voltage_logger(channel=0, duration=60, interval=1.0):
"""Log voltage measurements over time"""
print(f"Voltage Logger - ADC Channel {channel}")
print(f"Duration: {duration}s, Interval: {interval}s")
print("Time(s) Voltage(V)")
print("-" * 20)
start_time = time.time()
measurements = []
while time.time() - start_time < duration:
elapsed = time.time() - start_time
voltage = jumperless.adc_get(channel)
measurements.append((elapsed, voltage))
print(f"{elapsed:6.1f} {voltage:+8.3f}")
time.sleep(interval)
# Calculate statistics
voltages = [v for t, v in measurements]
avg_voltage = sum(voltages) / len(voltages)
min_voltage = min(voltages)
max_voltage = max(voltages)
print("-" * 20)
print(f"Average: {avg_voltage:+8.3f}V")
print(f"Minimum: {min_voltage:+8.3f}V")
print(f"Maximum: {max_voltage:+8.3f}V")
print(f"Range: {max_voltage - min_voltage:8.3f}V")
return measurements
# Log voltage for 30 seconds
data = voltage_logger(0, 30, 0.5)
Power Monitor
Real-time power consumption monitoring.
import jumperless
import time
def power_monitor(sensor=0, duration=30):
"""Monitor power consumption with statistics"""
print(f"Power Monitor - Sensor {sensor}")
print(f"Monitoring for {duration} seconds...")
print()
print("Time Current Voltage Power")
print("-" * 35)
start_time = time.time()
measurements = []
while time.time() - start_time < duration:
elapsed = time.time() - start_time
current = jumperless.ina_get_current(sensor)
voltage = jumperless.ina_get_bus_voltage(sensor)
power = jumperless.ina_get_power(sensor)
measurements.append({
'time': elapsed,
'current': current,
'voltage': voltage,
'power': power
})
print(f"{elapsed:4.0f}s {current:+7.3f}A {voltage:6.2f}V {power:+7.3f}W")
time.sleep(1)
# Calculate statistics
currents = [m['current'] for m in measurements]
voltages = [m['voltage'] for m in measurements]
powers = [m['power'] for m in measurements]
print("-" * 35)
print("STATISTICS:")
print(f"Average Current: {sum(currents)/len(currents):+7.3f}A")
print(f"Peak Current: {max(currents):+7.3f}A")
print(f"Average Voltage: {sum(voltages)/len(voltages):6.2f}V")
print(f"Average Power: {sum(powers)/len(powers):+7.3f}W")
print(f"Peak Power: {max(powers):+7.3f}W")
# Energy calculation (Wh)
energy_wh = sum(powers) * (1/3600) # Convert to Wh (1 sample per second)
print(f"Energy Used: {energy_wh:7.3f}Wh")
return measurements
# Monitor power for 30 seconds
data = power_monitor(0, 30)
Multi-Channel Scanner
Scan multiple ADC channels continuously.
import jumperless
import time
def multi_channel_scanner(channels=[0, 1, 2], scan_rate=2.0):
"""Continuously scan multiple ADC channels"""
print(f"Multi-Channel Scanner")
print(f"Channels: {channels}, Rate: {scan_rate} scans/sec")
print("Press Ctrl+C to stop")
print()
# Create header
header = "Time(s) "
for ch in channels:
header += f" ADC{ch}(V) "
print(header)
print("-" * len(header))
start_time = time.time()
scan_interval = 1.0 / scan_rate
try:
while True:
elapsed = time.time() - start_time
# Read all channels
voltages = []
for ch in channels:
voltage = jumperless.adc_get(ch)
voltages.append(voltage)
# Display results
line = f"{elapsed:6.1f} "
for voltage in voltages:
line += f"{voltage:+8.3f} "
print(line)
time.sleep(scan_interval)
except KeyboardInterrupt:
print("\nScanning stopped")
# Scan channels 0, 1, 2 at 1 Hz
multi_channel_scanner([0, 1, 2], 1.0)
Signal Generation
Sine Wave Generator
Generate smooth sine waves using DAC.
import jumperless
import math
import time
def sine_wave_generator(channel=0, frequency=1.0, amplitude=2.0, offset=0.0, duration=10.0):
"""Generate sine wave on DAC output"""
print(f"Sine Wave Generator")
print(f"Channel: DAC{channel}")
print(f"Frequency: {frequency} Hz")
print(f"Amplitude: ±{amplitude} V")
print(f"Offset: {offset} V")
print(f"Duration: {duration} s")
# Calculate timing
samples_per_cycle = 50 # Smooth wave
sample_rate = frequency * samples_per_cycle
sample_interval = 1.0 / sample_rate
total_samples = int(duration * sample_rate)
print(f"Sample rate: {sample_rate:.1f} Sa/s")
print("Generating wave...")
start_time = time.time()
for i in range(total_samples):
# Calculate sine value
angle = 2 * math.pi * i / samples_per_cycle
sine_value = math.sin(angle)
voltage = offset + amplitude * sine_value
# Clamp to safe range
voltage = max(-8.0, min(8.0, voltage))
# Set DAC
jumperless.dac_set(channel, voltage)
# Maintain timing
next_time = start_time + (i + 1) * sample_interval
while time.time() < next_time:
pass # Busy wait for precision
# Return to offset
jumperless.dac_set(channel, offset)
print("Wave generation complete")
# Generate 2Hz sine wave for 5 seconds
sine_wave_generator(0, 2.0, 1.5, 0.0, 5.0)
PWM Examples
Various PWM applications.
import jumperless
import time
def led_fade_demo(pin=1):
"""Smooth LED fade using PWM"""
print(f"LED Fade Demo on GPIO {pin}")
# Setup
jumperless.gpio_set_dir(pin, True)
jumperless.connect(f"GPIO_{pin}", "10")
print("Fading LED up and down...")
# Fade up
for brightness in range(0, 101, 2):
duty = brightness / 100.0
jumperless.pwm(pin, 1000, duty)
time.sleep(0.05)
# Fade down
for brightness in range(100, -1, -2):
duty = brightness / 100.0
jumperless.pwm(pin, 1000, duty)
time.sleep(0.05)
jumperless.pwm_stop(pin)
print("Fade complete")
def servo_demo(pin=2):
"""Servo motor control demonstration"""
print(f"Servo Demo on GPIO {pin}")
def set_servo_angle(angle):
# Convert angle (0-180°) to pulse width (1-2ms)
pulse_width = 1.0 + (angle / 180.0) # 1.0-2.0ms
duty_cycle = pulse_width / 20.0 # 20ms period
jumperless.pwm(pin, 50, duty_cycle) # 50Hz
jumperless.connect(f"GPIO_{pin}", "15")
angles = [0, 45, 90, 135, 180, 90, 45, 0]
for angle in angles:
print(f"Moving to {angle}°")
set_servo_angle(angle)
time.sleep(1)
jumperless.pwm_stop(pin)
print("Servo demo complete")
def tone_generator(pin=3, frequencies=[440, 523, 659, 784]):
"""Generate audio tones"""
print(f"Tone Generator on GPIO {pin}")
jumperless.connect(f"GPIO_{pin}", "20")
for freq in frequencies:
print(f"Playing {freq} Hz")
jumperless.pwm(pin, freq, 0.5) # 50% duty cycle
time.sleep(0.5)
jumperless.pwm_stop(pin)
print("Tone generation complete")
# Run PWM demos
led_fade_demo(1)
time.sleep(1)
servo_demo(2)
time.sleep(1)
tone_generator(3, [262, 294, 330, 349, 392, 440, 494, 523]) # C major scale
Arbitrary Waveform Generator
Generate custom waveforms from data.
import jumperless
import time
import math
def triangle_wave(samples=50):
"""Generate triangle wave data"""
wave = []
for i in range(samples):
if i < samples // 2:
# Rising edge
value = 2.0 * i / (samples // 2) - 1.0
else:
# Falling edge
value = 1.0 - 2.0 * (i - samples // 2) / (samples // 2)
wave.append(value)
return wave
def sawtooth_wave(samples=50):
"""Generate sawtooth wave data"""
wave = []
for i in range(samples):
value = 2.0 * i / samples - 1.0
wave.append(value)
return wave
def square_wave(samples=50, duty_cycle=0.5):
"""Generate square wave data"""
wave = []
high_samples = int(samples * duty_cycle)
for i in range(samples):
value = 1.0 if i < high_samples else -1.0
wave.append(value)
return wave
def arbitrary_waveform_generator(channel=0, waveform_data=None, frequency=1.0,
amplitude=2.0, offset=0.0, cycles=5):
"""Generate arbitrary waveform from data array"""
if waveform_data is None:
waveform_data = [math.sin(2 * math.pi * i / 50) for i in range(50)]
print(f"Arbitrary Waveform Generator")
print(f"Channel: DAC{channel}")
print(f"Waveform samples: {len(waveform_data)}")
print(f"Frequency: {frequency} Hz")
print(f"Amplitude: ±{amplitude} V")
print(f"Offset: {offset} V")
print(f"Cycles: {cycles}")
# Calculate timing
samples_per_cycle = len(waveform_data)
sample_rate = frequency * samples_per_cycle
sample_interval = 1.0 / sample_rate
total_samples = cycles * samples_per_cycle
print("Generating waveform...")
start_time = time.time()
for i in range(total_samples):
# Get waveform value (-1.0 to +1.0)
wave_index = i % samples_per_cycle
wave_value = waveform_data[wave_index]
# Scale and offset
voltage = offset + amplitude * wave_value
voltage = max(-8.0, min(8.0, voltage)) # Clamp
# Set DAC
jumperless.dac_set(channel, voltage)
# Maintain timing
next_time = start_time + (i + 1) * sample_interval
while time.time() < next_time:
pass
jumperless.dac_set(channel, offset)
print("Waveform generation complete")
# Generate different waveforms
print("Triangle wave:")
arbitrary_waveform_generator(0, triangle_wave(), 1.0, 1.5, 0.0, 3)
time.sleep(2)
print("\nSawtooth wave:")
arbitrary_waveform_generator(0, sawtooth_wave(), 2.0, 1.0, 0.0, 3)
time.sleep(2)
print("\nSquare wave (25% duty):")
arbitrary_waveform_generator(0, square_wave(50, 0.25), 1.5, 2.0, 0.0, 3)
Interactive Applications
Voltmeter with Probe
Interactive voltmeter using the probe interface.
import jumperless
import time
def probe_voltmeter():
"""Interactive voltmeter using probe"""
print("Probe Voltmeter")
print("Touch any pad with the probe to measure voltage")
print("Press Ctrl+C to exit")
print()
# Storage for measurements
measurements = {}
try:
while True:
print("Waiting for probe touch...")
# Wait for probe touch
pad = jumperless.probe_read()
print(f"Probe touched: {pad}")
# Temporarily connect to ADC
jumperless.connect(str(pad), "ADC0")
time.sleep(0.1) # Allow settling
# Take measurement
voltage = jumperless.adc_get(0)
measurements[str(pad)] = voltage
print(f"Voltage at {pad}: {voltage:+7.3f}V")
# Disconnect
jumperless.disconnect(str(pad), "ADC0")
# Show summary
print("\nMeasurement Summary:")
for pad_name, volt in measurements.items():
print(f" {pad_name:>10}: {volt:+7.3f}V")
print()
except KeyboardInterrupt:
print("\nVoltmeter stopped")
# Final summary
if measurements:
print("\nFinal Results:")
for pad_name, volt in measurements.items():
print(f" {pad_name:>10}: {volt:+7.3f}V")
probe_voltmeter()
Circuit Builder
Interactive circuit building with probe.
import jumperless
import time
def interactive_circuit_builder():
"""Build circuits interactively with the probe"""
print("Interactive Circuit Builder")
print("Use the probe to create connections")
print("Commands:")
print(" - Touch two pads to connect them")
print(" - Press CONNECT button to confirm connection")
print(" - Press REMOVE button to remove last connection")
print(" - Press Ctrl+C to exit")
print()
connections = []
pending_connection = None
try:
while True:
# Check for probe touch
pad = jumperless.probe_read(blocking=False)
if pad:
if pending_connection is None:
pending_connection = str(pad)
print(f"First point: {pad}")
print("Touch second point...")
else:
second_pad = str(pad)
print(f"Second point: {pad}")
print(f"Ready to connect {pending_connection} to {second_pad}")
print("Press CONNECT button to confirm, or touch new pad to cancel")
# Store pending connection
pending_connection = (pending_connection, second_pad)
# Check for button press
button = jumperless.probe_button(blocking=False)
if button == "CONNECT" and pending_connection:
if isinstance(pending_connection, tuple):
node1, node2 = pending_connection
try:
jumperless.connect(node1, node2)
connections.append((node1, node2))
print(f"✓ Connected {node1} to {node2}")
except Exception as e:
print(f"✗ Connection failed: {e}")
else:
print("Need two points to connect")
pending_connection = None
elif button == "REMOVE" and connections:
node1, node2 = connections.pop()
jumperless.disconnect(node1, node2)
print(f"✗ Removed connection {node1} to {node2}")
# Show current connections
if connections:
print(f"\nActive connections ({len(connections)}):")
for i, (n1, n2) in enumerate(connections, 1):
print(f" {i}: {n1} <-> {n2}")
print()
time.sleep(0.1)
except KeyboardInterrupt:
print("\nCircuit builder stopped")
print(f"Final circuit has {len(connections)} connections")
interactive_circuit_builder()
Logic Analyzer
Simple logic analyzer for digital signals.
import jumperless
import time
def simple_logic_analyzer(pins=[1, 2, 3], sample_rate=100, duration=5):
"""Simple logic analyzer for GPIO pins"""
print(f"Simple Logic Analyzer")
print(f"Pins: GPIO {pins}")
print(f"Sample rate: {sample_rate} Hz")
print(f"Duration: {duration} seconds")
print()
# Setup pins as inputs
for pin in pins:
jumperless.gpio_set_dir(pin, False) # Input
jumperless.gpio_set_pull(pin, 0) # No pull resistor
# Calculate timing
sample_interval = 1.0 / sample_rate
total_samples = int(duration * sample_rate)
print("Starting capture...")
print("Time(s) " + " ".join([f"GPIO{p}" for p in pins]))
print("-" * (10 + len(pins) * 7))
start_time = time.time()
samples = []
for i in range(total_samples):
elapsed = time.time() - start_time
# Read all pins
states = []
for pin in pins:
state = jumperless.gpio_get(pin)
states.append("1" if state == "HIGH" else "0")
samples.append((elapsed, states))
# Display every 10th sample
if i % (sample_rate // 10) == 0:
print(f"{elapsed:6.2f} " + " ".join(states))
# Wait for next sample
next_time = start_time + (i + 1) * sample_interval
while time.time() < next_time:
pass
print("\nCapture complete!")
# Analyze transitions
print("\nTransition Analysis:")
for pin_idx, pin in enumerate(pins):
transitions = 0
last_state = samples[0][1][pin_idx]
for _, states in samples[1:]:
if states[pin_idx] != last_state:
transitions += 1
last_state = states[pin_idx]
print(f"GPIO {pin}: {transitions} transitions")
return samples
# Analyze GPIO 1, 2, 3 for 10 seconds at 50 Hz
data = simple_logic_analyzer([1, 2, 3], 50, 10)
Circuit Templates
Arduino Development Setup
Standard connections for Arduino development.
import jumperless
def setup_arduino_development():
"""Setup standard Arduino development connections"""
print("Setting up Arduino Development Environment")
# Clear existing connections
jumperless.nodes_clear()
# Power distribution
print("Setting up power rails...")
jumperless.dac_set(2, 5.0) # TOP_RAIL to 5V
jumperless.dac_set(3, 0.0) # BOTTOM_RAIL to GND
# Connect power to breadboard
jumperless.connect("TOP_RAIL", "1") # 5V to hole 1
jumperless.connect("BOTTOM_RAIL", "30") # GND to hole 30
jumperless.connect("GND", "31") # Additional GND
# I2C connections (standard pins)
print("Setting up I2C...")
jumperless.connect("A4", "20") # SDA
jumperless.connect("A5", "21") # SCL
# SPI connections
print("Setting up SPI...")
jumperless.connect("D10", "10") # SS
jumperless.connect("D11", "11") # MOSI
jumperless.connect("D12", "12") # MISO
jumperless.connect("D13", "13") # SCK
# UART connections (if using software serial)
print("Setting up UART...")
jumperless.connect("D2", "25") # Software Serial RX
jumperless.connect("D3", "26") # Software Serial TX
# Analog connections
print("Setting up analog pins...")
jumperless.connect("A0", "40")
jumperless.connect("A1", "41")
jumperless.connect("A2", "42")
jumperless.connect("A3", "43")
print("Arduino development setup complete!")
print("Available connections:")
print(" Power: 5V on hole 1, GND on holes 30-31")
print(" I2C: SDA on hole 20, SCL on hole 21")
print(" SPI: SS=10, MOSI=11, MISO=12, SCK=13")
print(" UART: RX on hole 25, TX on hole 26")
print(" Analog: A0-A3 on holes 40-43")
setup_arduino_development()
Sensor Testing Platform
Setup for testing various sensors.
import jumperless
def setup_sensor_platform():
"""Setup platform for sensor testing"""
print("Setting up Sensor Testing Platform")
# Clear existing connections
jumperless.nodes_clear()
# Multi-voltage power supply
print("Setting up power supplies...")
jumperless.dac_set(0, 3.3) # 3.3V supply
jumperless.dac_set(1, 5.0) # 5V supply
jumperless.dac_set(2, 3.3) # TOP_RAIL 3.3V
jumperless.dac_set(3, 0.0) # BOTTOM_RAIL GND
# Power distribution
jumperless.connect("DAC0", "1") # 3.3V on hole 1
jumperless.connect("DAC1", "2") # 5.0V on hole 2
jumperless.connect("GND", "30") # GND on hole 30
# I2C sensor bus
print("Setting up I2C sensor bus...")
jumperless.connect("A4", "20") # SDA
jumperless.connect("A5", "21") # SCL
jumperless.connect("DAC0", "22") # 3.3V pullup power
# SPI sensor bus
print("Setting up SPI sensor bus...")
jumperless.connect("D11", "10") # MOSI
jumperless.connect("D12", "11") # MISO
jumperless.connect("D13", "12") # SCK
jumperless.connect("D10", "13") # CS1
jumperless.connect("D9", "14") # CS2
# Analog sensor inputs
print("Setting up analog inputs...")
jumperless.connect("A0", "40") # Analog sensor 1
jumperless.connect("A1", "41") # Analog sensor 2
jumperless.connect("A2", "42") # Analog sensor 3
# Digital sensor inputs
print("Setting up digital inputs...")
jumperless.connect("D2", "50") # Digital sensor 1
jumperless.connect("D3", "51") # Digital sensor 2
jumperless.connect("D4", "52") # Digital sensor 3
# Reference voltages for sensor testing
print("Setting up reference voltages...")
jumperless.connect("ADC0", "45") # Voltage measurement point 1
jumperless.connect("ADC1", "46") # Voltage measurement point 2
print("Sensor testing platform ready!")
print("Power supplies:")
print(" 3.3V: hole 1, hole 22 (I2C pullup)")
print(" 5.0V: hole 2")
print(" GND: hole 30")
print("I2C bus: SDA=20, SCL=21")
print("SPI bus: MOSI=10, MISO=11, SCK=12, CS1=13, CS2=14")
print("Analog inputs: A0=40, A1=41, A2=42")
print("Digital inputs: D2=50, D3=51, D4=52")
print("Voltage monitoring: ADC0=45, ADC1=46")
setup_sensor_platform()
Signal Generator Setup
Multi-channel signal generation platform.
import jumperless
def setup_signal_generator():
"""Setup multi-channel signal generator"""
print("Setting up Signal Generator Platform")
# Clear existing connections
jumperless.nodes_clear()
# Analog outputs
print("Setting up analog outputs...")
jumperless.connect("DAC0", "10") # Analog out 1
jumperless.connect("DAC1", "11") # Analog out 2
# Digital/PWM outputs
print("Setting up digital/PWM outputs...")
jumperless.connect("GPIO_1", "20") # PWM/Digital out 1
jumperless.connect("GPIO_2", "21") # PWM/Digital out 2
jumperless.connect("GPIO_3", "22") # PWM/Digital out 3
jumperless.connect("GPIO_4", "23") # PWM/Digital out 4
# Reference and monitoring
print("Setting up monitoring...")
jumperless.connect("ADC0", "15") # Monitor point 1
jumperless.connect("ADC1", "16") # Monitor point 2
jumperless.connect("GND", "30") # Ground reference
# Initial setup - all outputs off
jumperless.dac_set(0, 0.0)
jumperless.dac_set(1, 0.0)
for gpio in range(1, 5):
jumperless.gpio_set_dir(gpio, True) # Set as output
jumperless.gpio_set(gpio, False) # Set low
print("Signal generator platform ready!")
print("Analog outputs: DAC0=10, DAC1=11")
print("PWM/Digital outputs: GPIO1=20, GPIO2=21, GPIO3=22, GPIO4=23")
print("Monitor points: ADC0=15, ADC1=16")
print("Ground reference: hole 30")
def demo_signal_generator():
"""Demonstrate signal generator capabilities"""
print("\nSignal Generator Demo")
# Test analog outputs
print("Testing analog outputs...")
for voltage in [1.0, 2.0, 3.3, 0.0]:
jumperless.dac_set(0, voltage)
jumperless.dac_set(1, -voltage if voltage > 0 else 0)
print(f"DAC0: {voltage}V, DAC1: {-voltage if voltage > 0 else 0}V")
time.sleep(1)
# Test PWM outputs
print("Testing PWM outputs...")
for gpio in range(1, 5):
frequency = 1000 * gpio # Different frequency for each pin
jumperless.pwm(gpio, frequency, 0.5)
print(f"GPIO{gpio}: {frequency}Hz PWM")
time.sleep(1)
jumperless.pwm_stop(gpio)
print("Demo complete!")
setup_signal_generator()
demo_signal_generator()
Advanced Applications
Automated Test Equipment
Framework for automated component testing.
import jumperless
import time
class AutomatedTester:
def __init__(self):
self.results = []
self.setup_test_environment()
def setup_test_environment(self):
"""Setup connections for testing"""
jumperless.nodes_clear()
# Power supplies
jumperless.dac_set(0, 3.3) # 3.3V supply
jumperless.dac_set(1, 5.0) # 5V supply
jumperless.connect("DAC0", "1")
jumperless.connect("DAC1", "2")
jumperless.connect("GND", "30")
# Test points
jumperless.connect("ADC0", "10") # Voltage measurement
jumperless.connect("ADC1", "11") # Current measurement
print("Test environment ready")
def test_resistor(self, test_voltage=3.3, expected_resistance=1000):
"""Test resistor value"""
print(f"Testing resistor (expected: {expected_resistance}Ω)")
# Apply test voltage across resistor
# Assumes resistor connected between holes 1 and 10
jumperless.dac_set(0, test_voltage)
time.sleep(0.1) # Settle
# Measure voltage across resistor
measured_voltage = jumperless.adc_get(0)
# Calculate current (assuming known series resistor)
# This is simplified - real implementation would use current sensor
voltage_drop = test_voltage - measured_voltage
current = voltage_drop / 1000 # Assuming 1kΩ series resistor
if current > 0:
measured_resistance = measured_voltage / current
else:
measured_resistance = float('inf')
error_percent = abs(measured_resistance - expected_resistance) / expected_resistance * 100
result = {
'component': 'resistor',
'expected': expected_resistance,
'measured': measured_resistance,
'error_percent': error_percent,
'pass': error_percent < 10 # 10% tolerance
}
self.results.append(result)
print(f" Expected: {expected_resistance}Ω")
print(f" Measured: {measured_resistance:.1f}Ω")
print(f" Error: {error_percent:.1f}%")
print(f" Result: {'PASS' if result['pass'] else 'FAIL'}")
return result
def test_capacitor(self, test_voltage=3.3, expected_capacitance=1e-6):
"""Test capacitor value using charge/discharge timing"""
print(f"Testing capacitor (expected: {expected_capacitance*1e6:.1f}µF)")
# Discharge capacitor
jumperless.dac_set(0, 0.0)
time.sleep(0.5)
# Start charging
start_time = time.time()
jumperless.dac_set(0, test_voltage)
# Measure time to reach 63.2% of final voltage (1 time constant)
target_voltage = test_voltage * 0.632
while True:
voltage = jumperless.adc_get(0)
if voltage >= target_voltage:
charge_time = time.time() - start_time
break
if time.time() - start_time > 5: # Timeout
charge_time = float('inf')
break
time.sleep(0.001)
# Calculate capacitance (C = t / R, assuming known resistance)
series_resistance = 1000 # Assume 1kΩ series resistor
if charge_time < float('inf'):
measured_capacitance = charge_time / series_resistance
else:
measured_capacitance = float('inf')
error_percent = abs(measured_capacitance - expected_capacitance) / expected_capacitance * 100
result = {
'component': 'capacitor',
'expected': expected_capacitance,
'measured': measured_capacitance,
'error_percent': error_percent,
'pass': error_percent < 20 # 20% tolerance
}
self.results.append(result)
print(f" Expected: {expected_capacitance*1e6:.1f}µF")
print(f" Measured: {measured_capacitance*1e6:.1f}µF")
print(f" Charge time: {charge_time*1000:.1f}ms")
print(f" Error: {error_percent:.1f}%")
print(f" Result: {'PASS' if result['pass'] else 'FAIL'}")
return result
def test_diode(self, test_current=0.001):
"""Test diode forward voltage"""
print(f"Testing diode forward voltage")
# Apply forward bias
jumperless.dac_set(0, 2.0) # Should be enough for forward bias
time.sleep(0.1)
# Measure forward voltage
forward_voltage = jumperless.adc_get(0)
# Check if voltage is in expected range for silicon diode
expected_min = 0.5
expected_max = 0.8
result = {
'component': 'diode',
'measured_vf': forward_voltage,
'pass': expected_min <= forward_voltage <= expected_max
}
self.results.append(result)
print(f" Forward voltage: {forward_voltage:.3f}V")
print(f" Expected range: {expected_min}-{expected_max}V")
print(f" Result: {'PASS' if result['pass'] else 'FAIL'}")
return result
def generate_report(self):
"""Generate test report"""
print("\n" + "="*50)
print("AUTOMATED TEST REPORT")
print("="*50)
passed = sum(1 for r in self.results if r['pass'])
total = len(self.results)
print(f"Tests completed: {total}")
print(f"Tests passed: {passed}")
print(f"Tests failed: {total - passed}")
print(f"Pass rate: {passed/total*100:.1f}%" if total > 0 else "No tests")
print("\nDetailed Results:")
for i, result in enumerate(self.results, 1):
status = "PASS" if result['pass'] else "FAIL"
print(f" {i}. {result['component'].title()}: {status}")
return self.results
# Example usage
def run_component_tests():
tester = AutomatedTester()
print("Insert component between holes 1 and 10, then press Enter")
input()
print("What component are you testing?")
print("1. Resistor")
print("2. Capacitor")
print("3. Diode")
choice = input("Enter choice (1-3): ")
if choice == "1":
expected = float(input("Expected resistance (Ω): "))
tester.test_resistor(expected_resistance=expected)
elif choice == "2":
expected = float(input("Expected capacitance (µF): ")) * 1e-6
tester.test_capacitor(expected_capacitance=expected)
elif choice == "3":
tester.test_diode()
tester.generate_report()
# Uncomment to run interactive test
# run_component_tests()
Utility Scripts
Connection Backup and Restore
Save and restore connection configurations.
import jumperless
def save_connections(filename="connections.txt"):
"""Save current connections to file"""
print(f"Saving connections to {filename}")
# This is a simplified version - real implementation would
# use the actual connection state from hardware
connections = [
("D2", "A0"),
("GND", "30"),
("GPIO_1", "10")
] # Example connections
try:
with open(filename, 'w') as f:
f.write("# Jumperless Connection Backup\n")
f.write(f"# Saved at: {time.time()}\n")
for node1, node2 in connections:
f.write(f"{node1},{node2}\n")
print(f"✓ Saved {len(connections)} connections")
return True
except Exception as e:
print(f"✗ Save failed: {e}")
return False
def load_connections(filename="connections.txt"):
"""Load connections from file"""
print(f"Loading connections from {filename}")
try:
connections = []
with open(filename, 'r') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
parts = line.split(',')
if len(parts) == 2:
connections.append((parts[0], parts[1]))
# Clear existing connections
jumperless.nodes_clear()
# Create new connections
for node1, node2 in connections:
try:
jumperless.connect(node1, node2)
print(f"✓ Connected {node1} to {node2}")
except Exception as e:
print(f"✗ Failed to connect {node1} to {node2}: {e}")
print(f"Loaded {len(connections)} connections")
return True
except Exception as e:
print(f"✗ Load failed: {e}")
return False
def backup_manager():
"""Interactive backup manager"""
print("Connection Backup Manager")
print("1. Save current connections")
print("2. Load connections from file")
print("3. List backup files")
choice = input("Choice (1-3): ")
if choice == "1":
filename = input("Filename (or Enter for default): ").strip()
if not filename:
filename = "connections.txt"
save_connections(filename)
elif choice == "2":
filename = input("Filename (or Enter for default): ").strip()
if not filename:
filename = "connections.txt"
load_connections(filename)
elif choice == "3":
print("Available backup files:")
# In real implementation, would list actual files
print(" connections.txt")
print(" test_setup.txt")
print(" sensor_platform.txt")
# backup_manager()
Performance Benchmark
Benchmark system performance.
import jumperless
import time
def benchmark_dac_speed():
"""Benchmark DAC update speed"""
print("DAC Speed Benchmark")
iterations = 100
start_time = time.time()
for i in range(iterations):
voltage = 3.3 * (i % 2) # Alternate between 0 and 3.3V
jumperless.dac_set(0, voltage)
end_time = time.time()
total_time = end_time - start_time
rate = iterations / total_time
print(f"Completed {iterations} DAC updates in {total_time:.3f}s")
print(f"Update rate: {rate:.1f} updates/second")
print(f"Time per update: {total_time/iterations*1000:.2f}ms")
def benchmark_adc_speed():
"""Benchmark ADC read speed"""
print("ADC Speed Benchmark")
iterations = 100
start_time = time.time()
voltages = []
for i in range(iterations):
voltage = jumperless.adc_get(0)
voltages.append(voltage)
end_time = time.time()
total_time = end_time - start_time
rate = iterations / total_time
print(f"Completed {iterations} ADC reads in {total_time:.3f}s")
print(f"Read rate: {rate:.1f} reads/second")
print(f"Time per read: {total_time/iterations*1000:.2f}ms")
print(f"Voltage range: {min(voltages):.3f}V to {max(voltages):.3f}V")
def benchmark_gpio_speed():
"""Benchmark GPIO toggle speed"""
print("GPIO Speed Benchmark")
pin = 1
jumperless.gpio_set_dir(pin, True) # Set as output
iterations = 100
start_time = time.time()
for i in range(iterations):
state = bool(i % 2)
jumperless.gpio_set(pin, state)
end_time = time.time()
total_time = end_time - start_time
rate = iterations / total_time
print(f"Completed {iterations} GPIO toggles in {total_time:.3f}s")
print(f"Toggle rate: {rate:.1f} toggles/second")
print(f"Time per toggle: {total_time/iterations*1000:.2f}ms")
def benchmark_connection_speed():
"""Benchmark connection switching speed"""
print("Connection Speed Benchmark")
connections = [
("1", "2"),
("3", "4"),
("5", "6"),
("7", "8")
]
iterations = 20 # Connection switching is slower
start_time = time.time()
for i in range(iterations):
node1, node2 = connections[i % len(connections)]
jumperless.connect(node1, node2)
jumperless.disconnect(node1, node2)
end_time = time.time()
total_time = end_time - start_time
rate = (iterations * 2) / total_time # Connect + disconnect
print(f"Completed {iterations} connect/disconnect cycles in {total_time:.3f}s")
print(f"Operation rate: {rate:.1f} operations/second")
print(f"Time per operation: {total_time/(iterations*2)*1000:.1f}ms")
def run_all_benchmarks():
"""Run complete benchmark suite"""
print("Jumperless Performance Benchmark Suite")
print("="*40)
benchmark_dac_speed()
print()
benchmark_adc_speed()
print()
benchmark_gpio_speed()
print()
benchmark_connection_speed()
print("Benchmark suite complete!")
run_all_benchmarks()
File Management Examples
Since all these scripts are designed to be saved and reused, here's how to manage them effectively:
Save Script Template
# Template for saving scripts in Jumperless
def save_script_to_file(script_content, filename):
"""Save script content to file"""
try:
with open(f"/python_scripts/{filename}", 'w') as f:
f.write(script_content)
print(f"✓ Script saved as {filename}")
except Exception as e:
print(f"✗ Save failed: {e}")
# Example usage:
# save_script_to_file('''
# import jumperless
# jumperless.oled_print("Hello World!")
# ''', "hello_world.py")
Script Launcher
def list_and_run_scripts():
"""List available scripts and run selected one"""
try:
files = jumperless.fs_listdir("/python_scripts")
python_files = [f for f in files.split(',') if f.endswith('.py')]
print("Available Scripts:")
for i, filename in enumerate(python_files, 1):
print(f" {i}. {filename}")
choice = int(input("Select script (number): ")) - 1
if 0 <= choice < len(python_files):
filename = python_files[choice]
print(f"Running {filename}...")
exec(open(f"/python_scripts/{filename}").read())
else:
print("Invalid selection")
except Exception as e:
print(f"Error: {e}")
# Uncomment to use:
# list_and_run_scripts()
These examples provide a comprehensive foundation for working with Jumperless. They can be used as-is, modified for specific needs, or combined to create more complex applications. Each script is designed to be educational, practical, and immediately usable.