mirror of
https://github.com/Architeuthis-Flux/JumperlessV5.git
synced 2025-09-05 10:47:58 +00:00
528 lines
18 KiB
Python
528 lines
18 KiB
Python
"""
|
|
╭─────────────────────────────────────────────────────────────────╮
|
|
│ DAC Reference Guide │
|
|
╰─────────────────────────────────────────────────────────────────╯
|
|
|
|
Complete Digital-to-Analog Converter (DAC) functions reference.
|
|
Covers all DAC operations, voltage control, and advanced patterns.
|
|
|
|
🔧 DAC Channels:
|
|
- DAC0 (0): Primary DAC output
|
|
- DAC1 (1): Secondary DAC output
|
|
- TOP_RAIL (2): Top power rail
|
|
- BOTTOM_RAIL (3): Bottom power rail
|
|
|
|
⚡ Voltage Range: -8.0V to +8.0V
|
|
🎯 Resolution: 12-bit (4096 levels)
|
|
|
|
📋 Usage:
|
|
exec(open('examples/micropython_examples/dac_reference.py').read())
|
|
run_all_dac_demos()
|
|
"""
|
|
|
|
import time
|
|
|
|
def dac_basic_operations():
|
|
"""Demonstrate basic DAC operations"""
|
|
print("╭─────────────────────────────────────────────────────────────────╮")
|
|
print("│ 📊 DAC Basic Operations │")
|
|
print("╰─────────────────────────────────────────────────────────────────╯")
|
|
|
|
oled_clear()
|
|
oled_print("DAC Basic Ops")
|
|
|
|
print("\n🔧 Basic DAC Functions:")
|
|
print(" • dac_set(channel, voltage) - Set DAC output voltage")
|
|
print(" • dac_get(channel) - Get current DAC voltage")
|
|
print(" • set_dac(channel, voltage) - Alternative syntax")
|
|
print(" • get_dac(channel) - Alternative syntax")
|
|
|
|
# Test basic operations on each channel
|
|
channels = [
|
|
(DAC0, "DAC0"),
|
|
(DAC1, "DAC1"),
|
|
(TOP_RAIL, "TOP_RAIL"),
|
|
(BOTTOM_RAIL, "BOTTOM_RAIL")
|
|
]
|
|
|
|
test_voltages = [0.0, 1.0, 2.5, 3.3, 5.0, -1.0, -2.5]
|
|
|
|
for channel, name in channels:
|
|
print("\n📊 Testing " + name + ":")
|
|
oled_clear()
|
|
oled_print("Testing " + name)
|
|
|
|
for voltage in test_voltages:
|
|
print(" Setting " + str(voltage) + "V...")
|
|
dac_set(channel, voltage)
|
|
time.sleep(0.2)
|
|
|
|
# Read back and verify
|
|
actual = dac_get(channel)
|
|
error = abs(actual - voltage)
|
|
status = "✓" if error < 0.1 else "⚠️"
|
|
|
|
print(" " + status + " Set: " + str(voltage) + "V, Read: " + str(round(actual, 3)) + "V")
|
|
|
|
oled_clear()
|
|
oled_print(name + ": " + str(round(actual, 2)) + "V")
|
|
time.sleep(0.3)
|
|
|
|
# Reset all channels
|
|
print("\n🔄 Resetting all channels to 0V...")
|
|
for channel, name in channels:
|
|
dac_set(channel, 0.0)
|
|
|
|
print("✅ Basic DAC operations complete!")
|
|
|
|
def dac_voltage_sweeping():
|
|
"""Demonstrate voltage sweeping on DAC channels"""
|
|
print("🌊 DAC Voltage Sweeping Demo")
|
|
|
|
oled_clear()
|
|
oled_print("Voltage Sweep")
|
|
|
|
# Sweep configurations
|
|
sweeps = [
|
|
(DAC0, 0.0, 3.3, 0.1, "DAC0 Low Sweep"),
|
|
(DAC1, 0.0, 5.0, 0.2, "DAC1 Mid Sweep"),
|
|
(TOP_RAIL, -2.0, 2.0, 0.1, "TOP_RAIL Bipolar"),
|
|
(BOTTOM_RAIL, 0.0, 8.0, 0.4, "BOTTOM_RAIL High Sweep")
|
|
]
|
|
|
|
for channel, start, end, step, name in sweeps:
|
|
print("\n🌊 " + name + ":")
|
|
print(" Range: " + str(start) + "V to " + str(end) + "V, Step: " + str(step) + "V")
|
|
|
|
oled_clear()
|
|
oled_print(name)
|
|
|
|
# Sweep up
|
|
voltage = start
|
|
while voltage <= end:
|
|
dac_set(channel, voltage)
|
|
actual = dac_get(channel)
|
|
|
|
print(" " + str(round(voltage, 1)) + "V → " + str(round(actual, 3)) + "V")
|
|
|
|
oled_clear()
|
|
oled_print(str(round(actual, 2)) + "V")
|
|
|
|
voltage += step
|
|
time.sleep(0.1)
|
|
|
|
# Sweep down
|
|
voltage = end
|
|
while voltage >= start:
|
|
dac_set(channel, voltage)
|
|
actual = dac_get(channel)
|
|
|
|
oled_clear()
|
|
oled_print(str(round(actual, 2)) + "V")
|
|
|
|
voltage -= step
|
|
time.sleep(0.1)
|
|
|
|
# Reset
|
|
dac_set(channel, 0.0)
|
|
time.sleep(0.5)
|
|
|
|
print("\n✅ Voltage sweeping complete!")
|
|
|
|
def dac_precision_testing():
|
|
"""Test DAC precision and accuracy"""
|
|
print("🎯 DAC Precision Testing")
|
|
|
|
oled_clear()
|
|
oled_print("Precision Test")
|
|
|
|
# Test precision at different voltage levels
|
|
test_points = [
|
|
0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.3, 4.0, 5.0,
|
|
-0.5, -1.0, -1.5, -2.0, -2.5
|
|
]
|
|
|
|
channels = [(DAC0, "DAC0"), (DAC1, "DAC1")]
|
|
|
|
for channel, name in channels:
|
|
print("\n🎯 Testing " + name + " precision:")
|
|
errors = []
|
|
|
|
for target_voltage in test_points:
|
|
# Set voltage
|
|
dac_set(channel, target_voltage)
|
|
time.sleep(0.1) # Allow settling
|
|
|
|
# Take multiple readings
|
|
readings = []
|
|
for _ in range(5):
|
|
reading = dac_get(channel)
|
|
readings.append(reading)
|
|
time.sleep(0.01)
|
|
|
|
# Calculate statistics
|
|
avg_reading = sum(readings) / len(readings)
|
|
error = abs(avg_reading - target_voltage)
|
|
errors.append(error)
|
|
|
|
# Check repeatability
|
|
max_reading = max(readings)
|
|
min_reading = min(readings)
|
|
repeatability = max_reading - min_reading
|
|
|
|
print(" Target: " + str(target_voltage) + "V")
|
|
print(" Average: " + str(round(avg_reading, 4)) + "V")
|
|
print(" Error: " + str(round(error, 4)) + "V")
|
|
print(" Repeatability: " + str(round(repeatability, 4)) + "V")
|
|
|
|
oled_clear()
|
|
oled_print(name + " Test")
|
|
time.sleep(0.2)
|
|
|
|
# Overall statistics
|
|
max_error = max(errors)
|
|
avg_error = sum(errors) / len(errors)
|
|
|
|
print(" 📊 " + name + " Summary:")
|
|
print(" Max error: " + str(round(max_error, 4)) + "V")
|
|
print(" Avg error: " + str(round(avg_error, 4)) + "V")
|
|
print(" Test points: " + str(len(test_points)))
|
|
|
|
# Reset
|
|
dac_set(channel, 0.0)
|
|
|
|
print("\n✅ Precision testing complete!")
|
|
|
|
def dac_waveform_generation():
|
|
"""Generate various waveforms using DAC"""
|
|
print("🌊 DAC Waveform Generation")
|
|
|
|
oled_clear()
|
|
oled_print("Waveform Gen")
|
|
|
|
# Waveform parameters
|
|
amplitude = 2.0
|
|
offset = 0.0
|
|
steps = 50
|
|
delay = 0.05
|
|
|
|
# Generate sine wave
|
|
print("\n🌊 Generating sine wave on DAC0...")
|
|
oled_clear()
|
|
oled_print("Sine Wave")
|
|
|
|
for cycle in range(2): # 2 complete cycles
|
|
for i in range(steps):
|
|
angle = (i * 2 * 3.14159) / steps
|
|
voltage = offset + amplitude * ((2 * 3.14159 * angle) / (2 * 3.14159) -
|
|
(2 * 3.14159 * angle) ** 3 / (6 * (2 * 3.14159) ** 3)) # Rough sine approximation
|
|
# Simpler sine approximation
|
|
if i < steps // 4:
|
|
voltage = offset + amplitude * (4 * i / steps)
|
|
elif i < 3 * steps // 4:
|
|
voltage = offset + amplitude * (2 - 4 * i / steps)
|
|
else:
|
|
voltage = offset + amplitude * (4 * i / steps - 4)
|
|
|
|
dac_set(DAC0, voltage)
|
|
time.sleep(delay)
|
|
|
|
dac_set(DAC0, 0.0)
|
|
|
|
# Generate triangle wave
|
|
print("\n📐 Generating triangle wave on DAC1...")
|
|
oled_clear()
|
|
oled_print("Triangle Wave")
|
|
|
|
for cycle in range(2):
|
|
# Rising edge
|
|
for i in range(steps // 2):
|
|
voltage = offset + amplitude * (2 * i / steps)
|
|
dac_set(DAC1, voltage)
|
|
time.sleep(delay)
|
|
|
|
# Falling edge
|
|
for i in range(steps // 2):
|
|
voltage = offset + amplitude * (1 - 2 * i / steps)
|
|
dac_set(DAC1, voltage)
|
|
time.sleep(delay)
|
|
|
|
dac_set(DAC1, 0.0)
|
|
|
|
# Generate square wave
|
|
print("\n⬜ Generating square wave on TOP_RAIL...")
|
|
oled_clear()
|
|
oled_print("Square Wave")
|
|
|
|
for cycle in range(4):
|
|
# High level
|
|
dac_set(TOP_RAIL, offset + amplitude)
|
|
time.sleep(delay * 10)
|
|
|
|
# Low level
|
|
dac_set(TOP_RAIL, offset - amplitude)
|
|
time.sleep(delay * 10)
|
|
|
|
dac_set(TOP_RAIL, 0.0)
|
|
|
|
print("\n✅ Waveform generation complete!")
|
|
|
|
def dac_channel_comparison():
|
|
"""Compare different DAC channels"""
|
|
print("📊 DAC Channel Comparison")
|
|
|
|
oled_clear()
|
|
oled_print("Channel Compare")
|
|
|
|
# Test same voltage on all channels
|
|
test_voltage = 2.5
|
|
channels = [
|
|
(DAC0, "DAC0"),
|
|
(DAC1, "DAC1"),
|
|
(TOP_RAIL, "TOP_RAIL"),
|
|
(BOTTOM_RAIL, "BOTTOM_RAIL")
|
|
]
|
|
|
|
print("\n📊 Setting all channels to " + str(test_voltage) + "V:")
|
|
|
|
results = []
|
|
for channel, name in channels:
|
|
dac_set(channel, test_voltage)
|
|
time.sleep(0.1)
|
|
|
|
actual = dac_get(channel)
|
|
error = abs(actual - test_voltage)
|
|
results.append((name, actual, error))
|
|
|
|
print(" " + name + ": " + str(round(actual, 4)) + "V (error: " + str(round(error, 4)) + "V)")
|
|
|
|
# Find best and worst
|
|
best_channel = min(results, key=lambda x: x[2])
|
|
worst_channel = max(results, key=lambda x: x[2])
|
|
|
|
print("\n📈 Channel Comparison Results:")
|
|
print(" Best accuracy: " + best_channel[0] + " (error: " + str(round(best_channel[2], 4)) + "V)")
|
|
print(" Worst accuracy: " + worst_channel[0] + " (error: " + str(round(worst_channel[2], 4)) + "V)")
|
|
|
|
# Test voltage range for each channel
|
|
print("\n📊 Testing voltage ranges:")
|
|
|
|
for channel, name in channels:
|
|
print(" Testing " + name + " range:")
|
|
oled_clear()
|
|
oled_print(name + " Range")
|
|
|
|
# Test positive range
|
|
max_positive = 0.0
|
|
for voltage in [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]:
|
|
dac_set(channel, voltage)
|
|
time.sleep(0.1)
|
|
actual = dac_get(channel)
|
|
if abs(actual - voltage) < 0.5: # Within reasonable range
|
|
max_positive = voltage
|
|
|
|
# Test negative range
|
|
max_negative = 0.0
|
|
for voltage in [-1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0]:
|
|
dac_set(channel, voltage)
|
|
time.sleep(0.1)
|
|
actual = dac_get(channel)
|
|
if abs(actual - voltage) < 0.5: # Within reasonable range
|
|
max_negative = voltage
|
|
|
|
print(" Positive range: 0V to " + str(max_positive) + "V")
|
|
print(" Negative range: 0V to " + str(max_negative) + "V")
|
|
|
|
# Reset
|
|
dac_set(channel, 0.0)
|
|
|
|
print("\n✅ Channel comparison complete!")
|
|
|
|
def dac_power_rail_demo():
|
|
"""Demonstrate power rail configuration"""
|
|
print("⚡ DAC Power Rail Configuration")
|
|
|
|
oled_clear()
|
|
oled_print("Power Rails")
|
|
|
|
# Common power rail voltages
|
|
rail_configs = [
|
|
(TOP_RAIL, 3.3, "3.3V Logic"),
|
|
(BOTTOM_RAIL, 5.0, "5V Logic"),
|
|
(TOP_RAIL, 1.8, "1.8V Low Power"),
|
|
(BOTTOM_RAIL, 12.0, "12V Motor Supply"),
|
|
(TOP_RAIL, -5.0, "Negative Supply"),
|
|
(BOTTOM_RAIL, 0.0, "Ground Reference")
|
|
]
|
|
|
|
for rail, voltage, description in rail_configs:
|
|
rail_name = "TOP_RAIL" if rail == TOP_RAIL else "BOTTOM_RAIL"
|
|
|
|
print("\n⚡ " + description + ":")
|
|
print(" Setting " + rail_name + " to " + str(voltage) + "V")
|
|
|
|
oled_clear()
|
|
oled_print(rail_name + ": " + str(voltage) + "V")
|
|
|
|
dac_set(rail, voltage)
|
|
time.sleep(0.5)
|
|
|
|
actual = dac_get(rail)
|
|
error = abs(actual - voltage)
|
|
|
|
print(" Actual: " + str(round(actual, 3)) + "V")
|
|
print(" Error: " + str(round(error, 3)) + "V")
|
|
|
|
time.sleep(1)
|
|
|
|
# Reset rails
|
|
print("\n🔄 Resetting power rails to safe values...")
|
|
dac_set(TOP_RAIL, 0.0)
|
|
dac_set(BOTTOM_RAIL, 0.0)
|
|
|
|
oled_clear()
|
|
oled_print("Rails Reset")
|
|
|
|
print("✅ Power rail demo complete!")
|
|
|
|
def dac_alternative_syntax():
|
|
"""Demonstrate alternative DAC function syntax"""
|
|
print("🔄 DAC Alternative Syntax Demo")
|
|
|
|
oled_clear()
|
|
oled_print("Alt Syntax")
|
|
|
|
print("\n🔄 DAC functions have alternative syntax:")
|
|
print(" dac_set() ≡ set_dac()")
|
|
print(" dac_get() ≡ get_dac()")
|
|
|
|
# Test both syntaxes
|
|
test_pairs = [
|
|
(DAC0, 2.5, "DAC0"),
|
|
(DAC1, 1.8, "DAC1")
|
|
]
|
|
|
|
for channel, voltage, name in test_pairs:
|
|
print("\n📊 Testing " + name + " with both syntaxes:")
|
|
|
|
# Using dac_set/dac_get
|
|
print(" Using dac_set/dac_get:")
|
|
dac_set(channel, voltage)
|
|
reading1 = dac_get(channel)
|
|
print(" dac_set(" + str(channel) + ", " + str(voltage) + ")")
|
|
print(" dac_get(" + str(channel) + ") = " + str(round(reading1, 3)) + "V")
|
|
|
|
time.sleep(0.5)
|
|
|
|
# Using set_dac/get_dac
|
|
print(" Using set_dac/get_dac:")
|
|
set_dac(channel, voltage + 0.1) # Slightly different to show change
|
|
reading2 = get_dac(channel)
|
|
print(" set_dac(" + str(channel) + ", " + str(voltage + 0.1) + ")")
|
|
print(" get_dac(" + str(channel) + ") = " + str(round(reading2, 3)) + "V")
|
|
|
|
oled_clear()
|
|
oled_print(name + " OK")
|
|
time.sleep(1)
|
|
|
|
# Reset
|
|
dac_set(channel, 0.0)
|
|
|
|
print("\n✅ Alternative syntax demo complete!")
|
|
|
|
def quick_dac_test():
|
|
"""Quick DAC functionality test"""
|
|
print("⚡ Quick DAC Test")
|
|
|
|
oled_clear()
|
|
oled_print("Quick Test")
|
|
|
|
# Test each channel quickly
|
|
channels = [DAC0, DAC1, TOP_RAIL, BOTTOM_RAIL]
|
|
channel_names = ["DAC0", "DAC1", "TOP_RAIL", "BOTTOM_RAIL"]
|
|
|
|
for channel, name in zip(channels, channel_names):
|
|
print(" Testing " + name + "...")
|
|
|
|
# Set voltage
|
|
dac_set(channel, 2.0)
|
|
time.sleep(0.1)
|
|
|
|
# Read back
|
|
actual = dac_get(channel)
|
|
|
|
# Check
|
|
if abs(actual - 2.0) < 0.1:
|
|
print(" ✅ " + name + ": " + str(round(actual, 3)) + "V")
|
|
else:
|
|
print(" ❌ " + name + ": " + str(round(actual, 3)) + "V (expected 2.0V)")
|
|
|
|
oled_clear()
|
|
oled_print(name + " OK")
|
|
time.sleep(0.3)
|
|
|
|
# Reset
|
|
dac_set(channel, 0.0)
|
|
|
|
print("✅ Quick DAC test complete!")
|
|
|
|
def run_all_dac_demos():
|
|
"""Run all DAC demonstration functions"""
|
|
print("╭─────────────────────────────────────────────────────────────────╮")
|
|
print("│ 📊 Complete DAC Reference │")
|
|
print("╰─────────────────────────────────────────────────────────────────╯")
|
|
|
|
demos = [
|
|
("Quick Test", quick_dac_test),
|
|
("Basic Operations", dac_basic_operations),
|
|
("Alternative Syntax", dac_alternative_syntax),
|
|
("Voltage Sweeping", dac_voltage_sweeping),
|
|
("Precision Testing", dac_precision_testing),
|
|
("Channel Comparison", dac_channel_comparison),
|
|
("Power Rail Demo", dac_power_rail_demo),
|
|
("Waveform Generation", dac_waveform_generation)
|
|
]
|
|
|
|
print("\n🎯 DAC Reference Guide - All Functions")
|
|
print(" This demo covers every DAC function in the jumperless module")
|
|
print(" Press Ctrl+C during any demo to skip to the next one")
|
|
|
|
for name, demo_func in demos:
|
|
print("\n" + "="*60)
|
|
print("🎯 Running: " + name)
|
|
print("="*60)
|
|
|
|
try:
|
|
demo_func()
|
|
except KeyboardInterrupt:
|
|
print("⏭️ Skipping to next demo...")
|
|
continue
|
|
|
|
if name != "Waveform Generation": # Don't pause after last demo
|
|
print("\n📋 Press Enter for next demo...")
|
|
try:
|
|
input()
|
|
except KeyboardInterrupt:
|
|
break
|
|
|
|
print("\n✅ Complete DAC reference guide finished!")
|
|
print("📚 All DAC functions demonstrated:")
|
|
print(" • dac_set() / set_dac() - Set DAC voltage")
|
|
print(" • dac_get() / get_dac() - Read DAC voltage")
|
|
print(" • All channels: DAC0, DAC1, TOP_RAIL, BOTTOM_RAIL")
|
|
print(" • Voltage range: -8.0V to +8.0V")
|
|
|
|
if __name__ == "__main__":
|
|
print("DAC Reference Guide loaded!")
|
|
print("\nAvailable functions:")
|
|
print(" dac_basic_operations() - Basic DAC set/get operations")
|
|
print(" dac_voltage_sweeping() - Voltage sweep demonstrations")
|
|
print(" dac_precision_testing() - Precision and accuracy testing")
|
|
print(" dac_waveform_generation() - Generate sine, triangle, square waves")
|
|
print(" dac_channel_comparison() - Compare all DAC channels")
|
|
print(" dac_power_rail_demo() - Power rail configuration examples")
|
|
print(" dac_alternative_syntax() - Alternative function syntax")
|
|
print(" quick_dac_test() - Quick functionality test")
|
|
print(" run_all_dac_demos() - Run complete DAC reference guide")
|
|
else:
|
|
print("DAC reference loaded. Try run_all_dac_demos() for complete guide!") |