mirror of
https://github.com/Architeuthis-Flux/JumperlessV5.git
synced 2025-09-05 10:47:58 +00:00
453 lines
17 KiB
Python
453 lines
17 KiB
Python
"""
|
|
ADC (Analog-to-Digital Converter) Reference
|
|
==========================================
|
|
|
|
Complete reference for all ADC functions in the Jumperless MicroPython module.
|
|
This file demonstrates every ADC-related function with practical examples.
|
|
|
|
Functions demonstrated:
|
|
- adc_get(channel) - Read ADC input voltage
|
|
- get_adc() - Alias for adc_get()
|
|
|
|
ADC Channels:
|
|
- 0-4: ADC channels 0-4
|
|
- Voltage range: Typically 0V to 3.3V (depends on hardware)
|
|
|
|
Usage:
|
|
exec(open('micropython_examples/adc_reference.py').read())
|
|
"""
|
|
|
|
import time
|
|
|
|
def adc_basic_operations():
|
|
"""Demonstrate basic ADC operations"""
|
|
|
|
print("╭─────────────────────────────────────────────────────────────────────────────╮")
|
|
print("│ ADC BASIC OPERATIONS │")
|
|
print("╰─────────────────────────────────────────────────────────────────────────────╯")
|
|
|
|
oled_clear()
|
|
oled_print("ADC Basic Demo")
|
|
|
|
print("\n☺ Reading all ADC channels:")
|
|
|
|
# Read all ADC channels
|
|
for channel in range(5):
|
|
voltage = adc_get(channel)
|
|
print(" adc_get(" + str(channel) + ") = " + str(voltage) + "V")
|
|
|
|
oled_clear()
|
|
oled_print("ADC" + str(channel) + ": " + str(voltage) + "V")
|
|
time.sleep(0.8)
|
|
|
|
# Using alias function
|
|
print("\n☺ Using alias function:")
|
|
voltage = get_adc(0)
|
|
print(" get_adc(0) = " + str(voltage) + "V (alias function)")
|
|
|
|
oled_clear()
|
|
oled_print("ADC0: " + str(voltage) + "V")
|
|
time.sleep(1)
|
|
|
|
print("✓ Basic ADC operations complete")
|
|
|
|
def adc_continuous_monitoring():
|
|
"""Demonstrate continuous ADC monitoring"""
|
|
|
|
print("\n╭─────────────────────────────────────────────────────────────────────────────╮")
|
|
print("│ CONTINUOUS ADC MONITORING │")
|
|
print("╰─────────────────────────────────────────────────────────────────────────────╯")
|
|
|
|
oled_clear()
|
|
oled_print("ADC Monitoring")
|
|
|
|
print("\n☺ Monitoring ADC channels (20 samples):")
|
|
print(" Sample | ADC0 | ADC1 | ADC2 | ADC3 | ADC4")
|
|
print(" -------|----------|----------|----------|----------|----------")
|
|
|
|
for sample in range(20):
|
|
readings = []
|
|
for channel in range(5):
|
|
voltage = adc_get(channel)
|
|
readings.append(voltage)
|
|
|
|
# Format readings for display
|
|
readings_str = " | ".join([str(round(r, 3)) + "V" for r in readings])
|
|
print(" " + str(sample + 1).rjust(6) + " | " + readings_str)
|
|
|
|
# Show current sample on OLED
|
|
oled_clear()
|
|
oled_print("Sample " + str(sample + 1) + "/20")
|
|
time.sleep(0.2)
|
|
|
|
print("✓ Continuous monitoring complete")
|
|
|
|
def adc_statistics():
|
|
"""Calculate ADC statistics"""
|
|
|
|
print("\n╭─────────────────────────────────────────────────────────────────────────────╮")
|
|
print("│ ADC STATISTICS │")
|
|
print("╰─────────────────────────────────────────────────────────────────────────────╯")
|
|
|
|
oled_clear()
|
|
oled_print("ADC Statistics")
|
|
|
|
print("\n☺ Collecting statistics for each ADC channel:")
|
|
|
|
num_samples = 50
|
|
|
|
for channel in range(5):
|
|
print("\n ADC" + str(channel) + " statistics (" + str(num_samples) + " samples):")
|
|
|
|
# Collect readings
|
|
readings = []
|
|
min_val = float('inf')
|
|
max_val = float('-inf')
|
|
|
|
for sample in range(num_samples):
|
|
voltage = adc_get(channel)
|
|
readings.append(voltage)
|
|
|
|
if voltage < min_val:
|
|
min_val = voltage
|
|
if voltage > max_val:
|
|
max_val = voltage
|
|
|
|
# Show progress
|
|
if sample % 10 == 0:
|
|
oled_clear()
|
|
oled_print("ADC" + str(channel) + " " + str(sample) + "/" + str(num_samples))
|
|
|
|
time.sleep(0.02)
|
|
|
|
# Calculate statistics
|
|
avg_val = sum(readings) / len(readings)
|
|
|
|
# Calculate standard deviation
|
|
variance = sum((x - avg_val) ** 2 for x in readings) / len(readings)
|
|
std_dev = variance ** 0.5
|
|
|
|
# Calculate noise (peak-to-peak)
|
|
noise_pp = max_val - min_val
|
|
|
|
print(" Average: " + str(round(avg_val, 4)) + "V")
|
|
print(" Minimum: " + str(round(min_val, 4)) + "V")
|
|
print(" Maximum: " + str(round(max_val, 4)) + "V")
|
|
print(" Std Dev: " + str(round(std_dev, 4)) + "V")
|
|
print(" Noise (p-p): " + str(round(noise_pp, 4)) + "V")
|
|
|
|
# Show final results on OLED
|
|
oled_clear()
|
|
oled_print("ADC" + str(channel) + " Avg: " + str(round(avg_val, 3)) + "V")
|
|
time.sleep(1)
|
|
|
|
print("✓ Statistics collection complete")
|
|
|
|
def adc_calibration_test():
|
|
"""Test ADC calibration using known DAC voltages"""
|
|
|
|
print("\n╭─────────────────────────────────────────────────────────────────────────────╮")
|
|
print("│ ADC CALIBRATION TEST │")
|
|
print("╰─────────────────────────────────────────────────────────────────────────────╯")
|
|
|
|
oled_clear()
|
|
oled_print("ADC Calibration")
|
|
|
|
print("\n☺ Testing ADC accuracy using DAC reference:")
|
|
print(" This test connects DAC0 to ADC0 to compare voltages")
|
|
|
|
# Clear any existing connections
|
|
nodes_clear()
|
|
|
|
# Connect DAC0 to ADC0 for calibration
|
|
connect(DAC0, ADC0)
|
|
print(" Connected DAC0 to ADC0")
|
|
|
|
# Test voltages
|
|
test_voltages = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]
|
|
|
|
print("\n DAC Set | DAC Read | ADC Read | Error | Error %")
|
|
print(" ---------|----------|----------|----------|----------")
|
|
|
|
for target_voltage in test_voltages:
|
|
# Set DAC voltage
|
|
dac_set(DAC0, target_voltage)
|
|
time.sleep(0.1) # Allow settling
|
|
|
|
# Read both DAC and ADC
|
|
dac_actual = dac_get(DAC0)
|
|
adc_reading = adc_get(0)
|
|
|
|
# Calculate error
|
|
error = adc_reading - dac_actual
|
|
error_percent = (error / dac_actual) * 100 if dac_actual > 0 else 0
|
|
|
|
print(" " + str(target_voltage) + "V | " + str(dac_actual) + "V | " + str(adc_reading) + "V | " + str(error) + "V | " + str(error_percent) + "%")
|
|
|
|
oled_clear()
|
|
oled_print("Test: " + str(target_voltage) + "V")
|
|
time.sleep(0.5)
|
|
|
|
# Clean up
|
|
dac_set(DAC0, 0.0)
|
|
disconnect(DAC0, ADC0)
|
|
|
|
print(" ✓ Calibration test complete")
|
|
print(" ✓ DAC0 disconnected from ADC0")
|
|
|
|
def adc_voltage_divider_test():
|
|
"""Test ADC with voltage divider circuits"""
|
|
|
|
print("\n╭─────────────────────────────────────────────────────────────────────────────╮")
|
|
print("│ VOLTAGE DIVIDER TEST │")
|
|
print("╰─────────────────────────────────────────────────────────────────────────────╯")
|
|
|
|
oled_clear()
|
|
oled_print("Voltage Divider Test")
|
|
|
|
print("\n☺ Testing ADC with different voltage sources:")
|
|
print(" Connect voltage sources to ADC inputs for testing")
|
|
|
|
# Set up different voltage sources using DACs
|
|
voltage_sources = [
|
|
(DAC0, 1.0, "1V Reference"),
|
|
(DAC1, 2.0, "2V Reference"),
|
|
(TOP_RAIL, 3.3, "3.3V Logic"),
|
|
(BOTTOM_RAIL, 1.8, "1.8V Logic")
|
|
]
|
|
|
|
print("\n Setting up voltage sources:")
|
|
for source, voltage, description in voltage_sources:
|
|
dac_set(source, voltage)
|
|
actual = dac_get(source)
|
|
print(" " + description + ": " + str(actual) + "V")
|
|
|
|
# Connect sources to ADC inputs via breadboard
|
|
print("\n Connecting sources to ADC inputs:")
|
|
connect(DAC0, 10) # 1V to breadboard
|
|
connect(DAC1, 20) # 2V to breadboard
|
|
connect(TOP_RAIL, 30) # 3.3V to breadboard
|
|
connect(BOTTOM_RAIL, 40) # 1.8V to breadboard
|
|
|
|
# Connect ADC inputs to breadboard
|
|
connect(ADC0, 15) # ADC0 to breadboard
|
|
connect(ADC1, 25) # ADC1 to breadboard
|
|
connect(ADC2, 35) # ADC2 to breadboard
|
|
connect(ADC3, 45) # ADC3 to breadboard
|
|
|
|
print(" Manual connections needed:")
|
|
print(" Connect hole 10 to hole 15 (1V → ADC0)")
|
|
print(" Connect hole 20 to hole 25 (2V → ADC1)")
|
|
print(" Connect hole 30 to hole 35 (3.3V → ADC2)")
|
|
print(" Connect hole 40 to hole 45 (1.8V → ADC3)")
|
|
|
|
print("\n Press Enter when connections are made...")
|
|
input()
|
|
|
|
# Read all ADC channels
|
|
print("\n Reading ADC channels:")
|
|
for channel in range(4):
|
|
voltage = adc_get(channel)
|
|
print(" ADC" + str(channel) + ": " + str(voltage) + "V")
|
|
|
|
oled_clear()
|
|
oled_print("ADC" + str(channel) + ": " + str(voltage) + "V")
|
|
time.sleep(1)
|
|
|
|
# Clean up
|
|
nodes_clear()
|
|
for source, _, _ in voltage_sources:
|
|
dac_set(source, 0.0)
|
|
|
|
print(" ✓ Voltage divider test complete")
|
|
|
|
def adc_noise_analysis():
|
|
"""Analyze ADC noise characteristics"""
|
|
|
|
print("\n╭─────────────────────────────────────────────────────────────────────────────╮")
|
|
print("│ ADC NOISE ANALYSIS │")
|
|
print("╰─────────────────────────────────────────────────────────────────────────────╯")
|
|
|
|
oled_clear()
|
|
oled_print("Noise Analysis")
|
|
|
|
print("\n☺ Analyzing ADC noise with stable reference:")
|
|
|
|
# Use DAC0 as stable reference
|
|
reference_voltage = 2.5
|
|
dac_set(DAC0, reference_voltage)
|
|
connect(DAC0, ADC0)
|
|
|
|
print(" Reference voltage: " + str(reference_voltage) + "V")
|
|
print(" Collecting 100 samples...")
|
|
|
|
# Collect many samples
|
|
samples = []
|
|
for i in range(100):
|
|
voltage = adc_get(0)
|
|
samples.append(voltage)
|
|
|
|
if i % 10 == 0:
|
|
oled_clear()
|
|
oled_print("Sample " + str(i + 1) + "/100")
|
|
|
|
time.sleep(0.01)
|
|
|
|
# Analyze noise
|
|
avg_voltage = sum(samples) / len(samples)
|
|
min_voltage = min(samples)
|
|
max_voltage = max(samples)
|
|
|
|
# Calculate RMS noise
|
|
rms_noise = (sum((x - avg_voltage) ** 2 for x in samples) / len(samples)) ** 0.5
|
|
|
|
# Peak-to-peak noise
|
|
pp_noise = max_voltage - min_voltage
|
|
|
|
print("\n Noise Analysis Results:")
|
|
print(" Average voltage: " + str(round(avg_voltage, 5)) + "V")
|
|
print(" Minimum voltage: " + str(round(min_voltage, 5)) + "V")
|
|
print(" Maximum voltage: " + str(round(max_voltage, 5)) + "V")
|
|
print(" RMS noise: " + str(round(rms_noise * 1000, 3)) + "mV")
|
|
print(" Peak-to-peak noise: " + str(round(pp_noise * 1000, 3)) + "mV")
|
|
|
|
# Show noise histogram (simplified)
|
|
print("\n Noise distribution (simplified histogram):")
|
|
|
|
# Create bins for histogram
|
|
bins = 10
|
|
bin_width = pp_noise / bins
|
|
histogram = [0] * bins
|
|
|
|
for sample in samples:
|
|
bin_index = int((sample - min_voltage) / bin_width)
|
|
if bin_index >= bins:
|
|
bin_index = bins - 1
|
|
histogram[bin_index] += 1
|
|
|
|
for i, count in enumerate(histogram):
|
|
bin_voltage = min_voltage + i * bin_width
|
|
bar = "█" * (count // 2) # Scale down for display
|
|
print(" " + str(round(bin_voltage, 4)) + "V: " + bar + " (" + str(count) + ")")
|
|
|
|
# Clean up
|
|
dac_set(DAC0, 0.0)
|
|
disconnect(DAC0, ADC0)
|
|
|
|
oled_clear()
|
|
oled_print("Noise: " + str(round(rms_noise * 1000, 1)) + "mV RMS")
|
|
time.sleep(2)
|
|
|
|
print(" ✓ Noise analysis complete")
|
|
|
|
def adc_speed_test():
|
|
"""Test ADC sampling speed"""
|
|
|
|
print("\n╭─────────────────────────────────────────────────────────────────────────────╮")
|
|
print("│ ADC SPEED TEST │")
|
|
print("╰─────────────────────────────────────────────────────────────────────────────╯")
|
|
|
|
oled_clear()
|
|
oled_print("Speed Test")
|
|
|
|
print("\n☺ Testing ADC sampling speed:")
|
|
|
|
# Test single channel speed
|
|
print(" Testing single channel (ADC0) speed:")
|
|
|
|
num_samples = 1000
|
|
start_time = time.time()
|
|
|
|
for i in range(num_samples):
|
|
voltage = adc_get(0)
|
|
|
|
if i % 100 == 0:
|
|
oled_clear()
|
|
oled_print("Sample " + str(i + 1) + "/" + str(num_samples))
|
|
|
|
end_time = time.time()
|
|
duration = end_time - start_time
|
|
sample_rate = num_samples / duration
|
|
|
|
print(" Samples: " + str(num_samples))
|
|
print(" Duration: " + str(round(duration, 3)) + " seconds")
|
|
print(" Sample rate: " + str(round(sample_rate, 1)) + " samples/second")
|
|
|
|
# Test all channels speed
|
|
print("\n Testing all channels speed:")
|
|
|
|
num_cycles = 200
|
|
start_time = time.time()
|
|
|
|
for cycle in range(num_cycles):
|
|
for channel in range(5):
|
|
voltage = adc_get(channel)
|
|
|
|
if cycle % 20 == 0:
|
|
oled_clear()
|
|
oled_print("Cycle " + str(cycle + 1) + "/" + str(num_cycles))
|
|
|
|
end_time = time.time()
|
|
duration = end_time - start_time
|
|
total_samples = num_cycles * 5
|
|
sample_rate = total_samples / duration
|
|
|
|
print(" Cycles: " + str(num_cycles))
|
|
print(" Total samples: " + str(total_samples))
|
|
print(" Duration: " + str(round(duration, 3)) + " seconds")
|
|
print(" Sample rate: " + str(round(sample_rate, 1)) + " samples/second")
|
|
|
|
oled_clear()
|
|
oled_print("Speed: " + str(round(sample_rate, 0)) + " S/s")
|
|
time.sleep(2)
|
|
|
|
print(" ✓ Speed test complete")
|
|
|
|
def run_all_adc_demos():
|
|
"""Run all ADC demonstration functions"""
|
|
|
|
print("🚀 Starting Complete ADC Reference Demonstration")
|
|
print("═" * 75)
|
|
|
|
demos = [
|
|
("Basic Operations", adc_basic_operations),
|
|
("Continuous Monitoring", adc_continuous_monitoring),
|
|
("Statistics", adc_statistics),
|
|
("Calibration Test", adc_calibration_test),
|
|
("Voltage Divider Test", adc_voltage_divider_test),
|
|
("Noise Analysis", adc_noise_analysis),
|
|
("Speed Test", adc_speed_test)
|
|
]
|
|
|
|
for name, demo_func in demos:
|
|
print("\n📍 Running: " + name)
|
|
print("─" * 50)
|
|
try:
|
|
demo_func()
|
|
print("✓ " + name + " completed successfully")
|
|
except Exception as e:
|
|
print("❌ " + name + " failed: " + str(e))
|
|
|
|
time.sleep(2)
|
|
|
|
oled_clear()
|
|
oled_print("ADC Reference Complete!")
|
|
print("\n🎉 All ADC demonstrations complete!")
|
|
print("═" * 75)
|
|
|
|
def adc_quick_test():
|
|
"""Quick test of ADC functions"""
|
|
|
|
print("⚡ Quick ADC Test")
|
|
print("─" * 20)
|
|
|
|
# Test all channels briefly
|
|
for channel in range(5):
|
|
voltage = adc_get(channel)
|
|
print("ADC" + str(channel) + ": " + str(voltage) + "V")
|
|
|
|
print("✓ Quick ADC test complete")
|
|
|
|
# Run the demonstration
|
|
if __name__ == "__main__":
|
|
run_all_adc_demos() |