280 lines
8.5 KiB
Python

"""
Jumperless Machine Module Demo
Demonstrates the enhanced MicroPython capabilities with filesystem and machine module support
This file can be run in the MicroPython REPL to test all the new features:
1. Machine module (Pin, ADC, PWM) with Jumperless node support
2. Runtime module importing from python_scripts/lib/
3. Filesystem integration
4. Node name support in machine classes
Usage:
1. Copy this file to python_scripts/ on your Jumperless
2. In MicroPython REPL: exec(open('python_scripts/jumperless_machine_demo.py').read())
"""
print("🚀 Jumperless Machine Module Demo")
print("=" * 50)
# Test 1: Import and test filesystem capabilities
print("\n📁 Testing filesystem and module import capabilities...")
try:
import sys
import os
print(f"✓ Python {sys.version}")
print(f"✓ Platform: {sys.platform}")
print("\n📂 Module search paths:")
for i, path in enumerate(sys.path):
print(f" {i}: {path}")
# Test directory listing if available
try:
print("\n📋 Available directories:")
for item in os.listdir('/'):
print(f" /{item}")
except OSError:
print(" (Directory listing not available)")
except ImportError as e:
print(f"❌ Filesystem modules not available: {e}")
# Test 2: Machine module with Jumperless integration
print("\n🔌 Testing machine module with Jumperless nodes...")
try:
from machine import Pin, ADC, PWM
print("✓ Machine module imported successfully")
# Test Pin class with node names
print("\n🔧 Testing Pin class with Jumperless nodes:")
# Test with node numbers
pin1 = Pin(1, Pin.OUT) # Breadboard node 1
print("✓ Created Pin(1) - breadboard node 1")
# Test with node names
try:
pin_d13 = Pin("NANO_D13", Pin.OUT)
print("✓ Created Pin('NANO_D13') - Arduino D13 equivalent")
except:
print("⚠ Pin name lookup not available (expected in current implementation)")
# Test basic GPIO operations
pin1.on()
print("✓ pin1.on() - set high")
pin1.off()
print("✓ pin1.off() - set low")
state = pin1.value()
print(f"✓ pin1.value() = {state}")
# Test ADC with analog pins
print("\n📊 Testing ADC class:")
adc0 = ADC(26) # GPIO 26 = ADC0
print("✓ Created ADC(26) - NANO_A0 equivalent")
reading = adc0.read_u16()
voltage = (reading / 65535) * 3.3
print(f"✓ ADC reading: {reading} ({voltage:.3f}V)")
# Test PWM/DAC functionality
print("\n⚡ Testing PWM/DAC functionality:")
# Top rail DAC
dac_top = PWM(Pin(16)) # TOP_RAIL
print("✓ Created PWM(Pin(16)) - TOP_RAIL DAC")
# Set voltage via PWM duty cycle
# Full scale is -8V to +8V, so 32768 = 0V
dac_top.duty_u16(32768) # 0V
print("✓ Set TOP_RAIL to 0V via PWM duty cycle")
# Set 3.3V (3.3V + 8V = 11.3V, 11.3/16 * 65535 = 46244)
duty_3v3 = int(((3.3 + 8.0) / 16.0) * 65535)
dac_top.duty_u16(duty_3v3)
print(f"✓ Set TOP_RAIL to 3.3V (duty: {duty_3v3})")
except ImportError as e:
print(f"❌ Machine module not available: {e}")
except Exception as e:
print(f"⚠ Machine module error: {e}")
# Test 3: Jumperless-specific functions (should still work)
print("\n🔗 Testing native Jumperless functions...")
try:
# These should be available globally
result = connect(1, 30)
print(f"✓ connect(1, 30) = {result}")
voltage = adc_get(0)
print(f"✓ adc_get(0) = {voltage:.3f}V")
# Test DAC with node names
dac_set(TOP_RAIL, 3.3)
print("✓ dac_set(TOP_RAIL, 3.3) - using node constant")
current_voltage = dac_get(TOP_RAIL)
print(f"✓ dac_get(TOP_RAIL) = {current_voltage:.3f}V")
except NameError as e:
print(f"⚠ Jumperless functions not in global scope: {e}")
print(" (Try: import jumperless; jumperless.connect(1, 30))")
# Test 4: Module importing from filesystem
print("\n📚 Testing runtime module import...")
# Create a simple test module in memory to demonstrate
test_module_code = """
# Example user module for Jumperless
# Place modules like this in python_scripts/lib/ for automatic import
def blink_led(pin_num, times=3):
"""Blink an LED connected to a pin"""
try:
from machine import Pin
import time
led = Pin(pin_num, Pin.OUT)
for i in range(times):
led.on()
time.sleep(0.2)
led.off()
time.sleep(0.2)
print(f"Blinked pin {pin_num} {times} times")
except Exception as e:
print(f"Blink failed: {e}")
def read_analog_sensors():
"""Read all 4 ADC channels"""
try:
from machine import ADC
sensors = []
for channel in range(4):
adc = ADC(26 + channel) # GPIO 26-29
reading = adc.read_u16()
voltage = (reading / 65535) * 3.3
sensors.append(voltage)
return sensors
except Exception as e:
print(f"Sensor reading failed: {e}")
return [0.0, 0.0, 0.0, 0.0]
class JumperlessHelper:
"""Helper class for common Jumperless operations"""
def __init__(self):
self.connections = []
def safe_connect(self, node1, node2):
"""Connect nodes with error handling"""
try:
result = connect(node1, node2)
if result:
self.connections.append((node1, node2))
print(f"✓ Connected {node1}{node2}")
else:
print(f"❌ Failed to connect {node1}{node2}")
return result
except Exception as e:
print(f"❌ Connection error: {e}")
return False
def disconnect_all(self):
"""Disconnect all tracked connections"""
for node1, node2 in self.connections:
try:
disconnect(node1, node2)
print(f"✓ Disconnected {node1}{node2}")
except Exception as e:
print(f"❌ Disconnect error: {e}")
self.connections.clear()
"""
# Make the test module available
print("📝 Creating example user module...")
print(" (In real usage, save as python_scripts/lib/jumperless_utils.py)")
# Execute the module code to make functions available
exec(test_module_code)
print("✓ Example module loaded")
# Test the example functions
print("\n🧪 Testing example module functions...")
try:
# Test LED blink (won't actually blink since no LED, but tests the function)
print("Testing blink_led function:")
blink_led(13, 1) # Pin 13, blink once
# Test sensor reading
print("\nTesting sensor reading:")
sensor_values = read_analog_sensors()
for i, voltage in enumerate(sensor_values):
print(f" ADC{i}: {voltage:.3f}V")
# Test helper class
print("\nTesting JumperlessHelper class:")
helper = JumperlessHelper()
helper.safe_connect(1, 5)
helper.safe_connect(10, 15)
print(f" Tracked connections: {len(helper.connections)}")
helper.disconnect_all()
except Exception as e:
print(f"❌ Example functions error: {e}")
# Test 5: Comprehensive feature summary
print("\n📋 Feature Summary")
print("=" * 50)
features = [
("✓ Filesystem Integration", "sys.path configured for python_scripts/lib/"),
("✓ Machine Module", "Pin, ADC, PWM classes with Jumperless nodes"),
("✓ Node Name Support", "Use 'NANO_D13', 'TOP_RAIL', etc. in machine classes"),
("✓ Runtime Import", "Import .py and .mpy modules from filesystem"),
("✓ Backward Compatibility", "All existing Jumperless functions still work"),
("✓ Enhanced REPL", "Full MicroPython REPL with module support"),
]
for status, description in features:
print(f"{status} {description}")
print("\n🎯 Next Steps:")
print("1. Create python_scripts/lib/ directory on your Jumperless")
print("2. Add your custom .py modules to python_scripts/lib/")
print("3. Use 'import your_module' in REPL or scripts")
print("4. Mix machine module with native Jumperless functions")
print("5. Create reusable hardware abstraction libraries")
print("\n💡 Example Usage:")
print("""
# Traditional Jumperless way:
connect(1, 30)
dac_set(TOP_RAIL, 3.3)
voltage = adc_get(0)
# New machine module way:
from machine import Pin, ADC, PWM
pin = Pin('NANO_D13', Pin.OUT)
adc = ADC('NANO_A0')
dac = PWM(Pin('TOP_RAIL'))
# Both approaches work and can be mixed!
""")
print("🎉 Demo complete! Your Jumperless now has enhanced MicroPython capabilities.")