Initial commit: merge nuescan, pymso, pybbd202, and pypewpewhops into scanengine-3
- Merged four separate hardware control projects into unified platform - Created unified requirements.txt with all dependencies - Added comprehensive .gitignore - Added project overview README Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
msodev/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for acquisition mode get/set functions.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test acquisition mode functions on oscilloscope at 192.168.10.105"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip)
|
||||
|
||||
try:
|
||||
# Connect to scope
|
||||
scope.connect()
|
||||
print(f"✓ Connected to {scope.identify()}\n")
|
||||
|
||||
# Get current acquisition mode
|
||||
print("Getting current acquisition mode...")
|
||||
current_mode = scope.get_acquire_mode()
|
||||
print(f"✓ Current acquisition mode: {current_mode}\n")
|
||||
|
||||
# Test setting different acquisition modes
|
||||
print("Testing acquisition mode changes:")
|
||||
test_modes = ['SAMple', 'HIRes', 'AVErage', 'PEAKdetect', 'ENVelope']
|
||||
|
||||
for mode in test_modes:
|
||||
print(f"\n Setting mode to: {mode}")
|
||||
scope.set_acquire_mode(mode)
|
||||
|
||||
# Verify the change
|
||||
actual_mode = scope.get_acquire_mode()
|
||||
if actual_mode == mode:
|
||||
print(f" ✓ Verified: {actual_mode}")
|
||||
else:
|
||||
print(f" ✗ Mismatch: expected {mode}, got {actual_mode}")
|
||||
|
||||
# Restore original mode
|
||||
print(f"\nRestoring original mode: {current_mode}")
|
||||
scope.set_acquire_mode(current_mode)
|
||||
print(f"✓ Restored to: {scope.get_acquire_mode()}")
|
||||
|
||||
# Test invalid mode
|
||||
print("\nTesting invalid mode (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_acquire_mode("INVALID")
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Error: {type(e).__name__}: {e}")
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\n✓ Disconnected from oscilloscope")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+257
@@ -0,0 +1,257 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for channel control functionality.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test channel control functions on oscilloscope at 192.168.10.105"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip)
|
||||
|
||||
try:
|
||||
# Connect to scope
|
||||
scope.connect()
|
||||
print(f"Connected to {scope.identify()}\n")
|
||||
|
||||
# Test with CH1
|
||||
test_channel = 1
|
||||
print(f"=== Testing Channel {test_channel} ===\n")
|
||||
|
||||
# Query all channel parameters
|
||||
print("Querying all channel parameters...")
|
||||
all_params = scope.query_channel(test_channel)
|
||||
print(f"CH{test_channel} parameters: {all_params[:100]}...\n")
|
||||
|
||||
# Get current settings to restore later
|
||||
print("Getting current channel settings...")
|
||||
current_bandwidth = scope.get_channel_bandwidth(test_channel)
|
||||
current_coupling = scope.get_channel_coupling(test_channel)
|
||||
current_termination = scope.get_channel_termination(test_channel)
|
||||
current_scale = scope.get_channel_scale(test_channel)
|
||||
current_offset = scope.get_channel_offset(test_channel)
|
||||
current_position = scope.get_channel_position(test_channel)
|
||||
current_label_name = scope.get_channel_label_name(test_channel)
|
||||
current_label_color = scope.get_channel_label_color(test_channel)
|
||||
current_label_font_size = scope.get_channel_label_font_size(test_channel)
|
||||
current_label_font_type = scope.get_channel_label_font_type(test_channel)
|
||||
current_label_xpos = scope.get_channel_label_xpos(test_channel)
|
||||
current_label_ypos = scope.get_channel_label_ypos(test_channel)
|
||||
|
||||
print(f" Current bandwidth: {current_bandwidth}")
|
||||
print(f" Current coupling: {current_coupling}")
|
||||
print(f" Current termination: {current_termination} ohms")
|
||||
print(f" Current scale: {current_scale} V/div")
|
||||
print(f" Current offset: {current_offset} V")
|
||||
print(f" Current position: {current_position} divisions")
|
||||
print(f" Current label name: {current_label_name}")
|
||||
print(f" Current label color: {current_label_color}")
|
||||
print(f" Current label font size: {current_label_font_size} pt")
|
||||
print(f" Current label font type: {current_label_font_type}")
|
||||
print(f" Current label X position: {current_label_xpos} px")
|
||||
print(f" Current label Y position: {current_label_ypos} px\n")
|
||||
|
||||
# Test coupling modes
|
||||
print("Testing coupling modes:")
|
||||
for coupling in ['DC', 'AC']:
|
||||
print(f" Setting coupling to {coupling}...")
|
||||
scope.set_channel_coupling(test_channel, coupling)
|
||||
actual = scope.get_channel_coupling(test_channel)
|
||||
print(f" Actual coupling: {actual}")
|
||||
|
||||
# Test termination
|
||||
print("\nTesting termination settings:")
|
||||
for term in [50, 1000000]:
|
||||
print(f" Setting termination to {term} ohms...")
|
||||
scope.set_channel_termination(test_channel, term)
|
||||
actual = scope.get_channel_termination(test_channel)
|
||||
print(f" Actual termination: {actual} ohms")
|
||||
|
||||
# Test vertical scale
|
||||
print("\nTesting vertical scale:")
|
||||
test_scales = [0.1, 0.5, 1.0, 2.0]
|
||||
for scale in test_scales:
|
||||
print(f" Setting scale to {scale} V/div...")
|
||||
scope.set_channel_scale(test_channel, scale)
|
||||
actual = scope.get_channel_scale(test_channel)
|
||||
print(f" Actual scale: {actual} V/div")
|
||||
|
||||
# Test vertical offset
|
||||
print("\nTesting vertical offset:")
|
||||
test_offsets = [0.0, 0.5, -0.5, 1.0]
|
||||
for offset in test_offsets:
|
||||
print(f" Setting offset to {offset} V...")
|
||||
scope.set_channel_offset(test_channel, offset)
|
||||
actual = scope.get_channel_offset(test_channel)
|
||||
print(f" Actual offset: {actual} V")
|
||||
|
||||
# Test vertical position
|
||||
print("\nTesting vertical position:")
|
||||
test_positions = [0.0, 1.0, -1.0, 2.5]
|
||||
for position in test_positions:
|
||||
print(f" Setting position to {position} divisions...")
|
||||
scope.set_channel_position(test_channel, position)
|
||||
actual = scope.get_channel_position(test_channel)
|
||||
print(f" Actual position: {actual} divisions")
|
||||
|
||||
# Test label name
|
||||
print("\nTesting label name:")
|
||||
test_names = ["Test Signal", "CH1-Custom", "Probe Input"]
|
||||
for name in test_names:
|
||||
print(f" Setting label to '{name}'...")
|
||||
scope.set_channel_label_name(test_channel, name)
|
||||
actual = scope.get_channel_label_name(test_channel)
|
||||
print(f" Actual label: {actual}")
|
||||
|
||||
# Test label color
|
||||
print("\nTesting label color:")
|
||||
test_colors = ["#FF0000", "#00FF00", "#0000FF", "#FFFF00"]
|
||||
for color in test_colors:
|
||||
print(f" Setting color to {color}...")
|
||||
scope.set_channel_label_color(test_channel, color)
|
||||
actual = scope.get_channel_label_color(test_channel)
|
||||
print(f" Actual color: {actual}")
|
||||
|
||||
# Test label font size
|
||||
print("\nTesting label font size:")
|
||||
test_sizes = [10, 12, 14, 16]
|
||||
for size in test_sizes:
|
||||
print(f" Setting font size to {size} pt...")
|
||||
scope.set_channel_label_font_size(test_channel, size)
|
||||
actual = scope.get_channel_label_font_size(test_channel)
|
||||
print(f" Actual font size: {actual} pt")
|
||||
|
||||
# Test label font type
|
||||
print("\nTesting label font type:")
|
||||
test_fonts = ["Arial", "Helvetica", "Courier"]
|
||||
for font in test_fonts:
|
||||
print(f" Setting font to {font}...")
|
||||
scope.set_channel_label_font_type(test_channel, font)
|
||||
actual = scope.get_channel_label_font_type(test_channel)
|
||||
print(f" Actual font: {actual}")
|
||||
|
||||
# Test label position
|
||||
print("\nTesting label X position:")
|
||||
test_xpos = [100, 200, 300]
|
||||
for xpos in test_xpos:
|
||||
print(f" Setting X position to {xpos} px...")
|
||||
scope.set_channel_label_xpos(test_channel, xpos)
|
||||
actual = scope.get_channel_label_xpos(test_channel)
|
||||
print(f" Actual X position: {actual} px")
|
||||
|
||||
print("\nTesting label Y position:")
|
||||
test_ypos = [50, 100, 150]
|
||||
for ypos in test_ypos:
|
||||
print(f" Setting Y position to {ypos} px...")
|
||||
scope.set_channel_label_ypos(test_channel, ypos)
|
||||
actual = scope.get_channel_label_ypos(test_channel)
|
||||
print(f" Actual Y position: {actual} px")
|
||||
|
||||
# Test using string channel format
|
||||
print("\nTesting with string channel format ('CH2'):")
|
||||
print(" Setting CH2 coupling to AC...")
|
||||
scope.set_channel_coupling('CH2', 'AC')
|
||||
actual = scope.get_channel_coupling('CH2')
|
||||
print(f" Actual CH2 coupling: {actual}")
|
||||
|
||||
print(" Setting CH2 scale to 0.5 V/div...")
|
||||
scope.set_channel_scale('CH2', 0.5)
|
||||
actual = scope.get_channel_scale('CH2')
|
||||
print(f" Actual CH2 scale: {actual} V/div")
|
||||
|
||||
# Restore original settings
|
||||
print(f"\nRestoring original settings for CH{test_channel}...")
|
||||
scope.set_channel_coupling(test_channel, current_coupling)
|
||||
scope.set_channel_termination(test_channel, current_termination)
|
||||
scope.set_channel_scale(test_channel, current_scale)
|
||||
scope.set_channel_offset(test_channel, current_offset)
|
||||
scope.set_channel_position(test_channel, current_position)
|
||||
scope.set_channel_label_name(test_channel, current_label_name)
|
||||
scope.set_channel_label_color(test_channel, current_label_color)
|
||||
scope.set_channel_label_font_size(test_channel, current_label_font_size)
|
||||
scope.set_channel_label_font_type(test_channel, current_label_font_type)
|
||||
scope.set_channel_label_xpos(test_channel, current_label_xpos)
|
||||
scope.set_channel_label_ypos(test_channel, current_label_ypos)
|
||||
print(f" Restored coupling: {scope.get_channel_coupling(test_channel)}")
|
||||
print(f" Restored termination: {scope.get_channel_termination(test_channel)} ohms")
|
||||
print(f" Restored scale: {scope.get_channel_scale(test_channel)} V/div")
|
||||
|
||||
# Test invalid inputs
|
||||
print("\n=== Testing Error Handling ===\n")
|
||||
|
||||
print("Testing invalid channel number (should raise ValueError)...")
|
||||
try:
|
||||
scope.get_channel_coupling(5)
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid channel string (should raise ValueError)...")
|
||||
try:
|
||||
scope.get_channel_coupling('CH5')
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid coupling (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_channel_coupling(1, 'INVALID')
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid termination (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_channel_termination(1, 75)
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid scale (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_channel_scale(1, -1.0)
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid color format (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_channel_label_color(1, "FF0000") # Missing #
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid font size (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_channel_label_font_size(1, -5)
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid X position (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_channel_label_xpos(1, -10)
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\n=== All tests completed successfully! ===")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\nDisconnected from oscilloscope")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to connect to a Tektronix oscilloscope via raw sockets.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test connection to oscilloscope at 192.168.10.105"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
scope_port = 4000
|
||||
|
||||
print(f"Attempting to connect to oscilloscope at {scope_ip}:{scope_port}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip, port=scope_port, timeout=5.0)
|
||||
|
||||
try:
|
||||
# Attempt connection
|
||||
scope.connect()
|
||||
print(f"✓ Successfully connected to {scope_ip}:{scope_port}")
|
||||
print(f"✓ Connection status: {scope.is_connected}")
|
||||
|
||||
# Get instrument identification
|
||||
print("\nQuerying instrument identification...")
|
||||
idn = scope.identify()
|
||||
print(f"✓ Instrument ID: {idn}")
|
||||
|
||||
# Test a simple query
|
||||
print("\nTesting SCPI query...")
|
||||
response = scope.query("*OPT?")
|
||||
print(f"✓ Installed options: {response}")
|
||||
|
||||
# Test a write command
|
||||
print("\nTesting SCPI write command...")
|
||||
scope.write("*CLS")
|
||||
print("✓ Cleared status registers")
|
||||
|
||||
except ValueError as e:
|
||||
print(f"✗ Configuration error: {e}")
|
||||
except ConnectionError as e:
|
||||
print(f"✗ Connection failed: {e}")
|
||||
print("\nTroubleshooting tips:")
|
||||
print(" - Verify the oscilloscope IP address is correct")
|
||||
print(" - Check network connectivity (try: ping 192.168.10.105)")
|
||||
print(" - Ensure the oscilloscope has LXI/socket server enabled")
|
||||
print(" - Verify port 4000 is correct (check scope network settings)")
|
||||
except RuntimeError as e:
|
||||
print(f"✗ Runtime error: {e}")
|
||||
except Exception as e:
|
||||
print(f"✗ Unexpected error: {type(e).__name__}: {e}")
|
||||
finally:
|
||||
# Always disconnect
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\n✓ Disconnected from oscilloscope")
|
||||
else:
|
||||
print("\n✗ Not connected")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for FastFrame functionality.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test FastFrame functions on oscilloscope at 192.168.10.105"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip)
|
||||
|
||||
try:
|
||||
# Connect to scope
|
||||
scope.connect()
|
||||
print(f"✓ Connected to {scope.identify()}\n")
|
||||
|
||||
# Get current FastFrame state
|
||||
print("Getting current FastFrame state...")
|
||||
current_state = scope.get_fastframe_state()
|
||||
print(f"✓ Current FastFrame state: {current_state} ({'active' if current_state else 'off'})\n")
|
||||
|
||||
# Get current frame count
|
||||
print("Getting current frame count...")
|
||||
current_count = scope.get_fastframe_count()
|
||||
print(f"✓ Current frame count: {current_count}\n")
|
||||
|
||||
# Test enabling FastFrame
|
||||
print("Enabling FastFrame...")
|
||||
scope.set_fastframe_state(1)
|
||||
state = scope.get_fastframe_state()
|
||||
print(f"✓ FastFrame state: {state} ({'active' if state else 'off'})\n")
|
||||
|
||||
# Test setting frame count
|
||||
print("Setting frame count to 100...")
|
||||
scope.set_fastframe_count(100)
|
||||
count = scope.get_fastframe_count()
|
||||
print(f"✓ Frame count: {count}\n")
|
||||
|
||||
# Test using boolean for state
|
||||
print("Testing boolean state (True)...")
|
||||
scope.set_fastframe_state(True)
|
||||
state = scope.get_fastframe_state()
|
||||
print(f"✓ FastFrame state: {state} ({'active' if state else 'off'})\n")
|
||||
|
||||
print("Testing boolean state (False)...")
|
||||
scope.set_fastframe_state(False)
|
||||
state = scope.get_fastframe_state()
|
||||
print(f"✓ FastFrame state: {state} ({'active' if state else 'off'})\n")
|
||||
|
||||
# Test different frame counts
|
||||
print("Testing different frame counts:")
|
||||
test_counts = [10, 50, 200, 500]
|
||||
for test_count in test_counts:
|
||||
print(f" Setting count to {test_count}...")
|
||||
scope.set_fastframe_count(test_count)
|
||||
actual_count = scope.get_fastframe_count()
|
||||
if actual_count == test_count:
|
||||
print(f" ✓ Verified: {actual_count}")
|
||||
else:
|
||||
print(f" ✗ Mismatch: expected {test_count}, got {actual_count}")
|
||||
|
||||
# Restore original settings
|
||||
print(f"\nRestoring original settings...")
|
||||
scope.set_fastframe_state(current_state)
|
||||
scope.set_fastframe_count(current_count)
|
||||
print(f"✓ Restored FastFrame state: {scope.get_fastframe_state()}")
|
||||
print(f"✓ Restored frame count: {scope.get_fastframe_count()}")
|
||||
|
||||
# Test invalid inputs
|
||||
print("\nTesting invalid state (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_fastframe_state(2)
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid frame count (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_fastframe_count(-1)
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Error: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\n✓ Disconnected from oscilloscope")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+292
@@ -0,0 +1,292 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for FastFrame waveform acquisition.
|
||||
|
||||
Tests acquiring 1000 FastFrame records from a 1MHz square wave on CH1.
|
||||
Signal: 1MHz square wave, +250mV to -250mV
|
||||
Records: 1000 frames, 2500 points each
|
||||
"""
|
||||
|
||||
import time
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test FastFrame acquisition with 1MHz square wave on CH1"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip, timeout=20.0)
|
||||
|
||||
try:
|
||||
# Connect to scope
|
||||
scope.connect()
|
||||
print(f"Connected to {scope.identify()}\n")
|
||||
|
||||
print("=== Configuring Oscilloscope ===\n")
|
||||
|
||||
# Configure CH1 for the signal
|
||||
print("Configuring CH1...")
|
||||
print(" Setting vertical scale to 100mV/div...")
|
||||
scope.set_channel_scale(1, 0.1) # 100mV/div for ±250mV signal
|
||||
print(" Setting vertical offset to 0V...")
|
||||
scope.set_channel_offset(1, 0.0)
|
||||
print(" Setting coupling to DC...")
|
||||
scope.set_channel_coupling(1, 'DC')
|
||||
print(" Setting termination to 50 ohms...")
|
||||
scope.set_channel_termination(1, 50)
|
||||
|
||||
# Verify settings
|
||||
actual_scale = scope.get_channel_scale(1)
|
||||
actual_offset = scope.get_channel_offset(1)
|
||||
actual_coupling = scope.get_channel_coupling(1)
|
||||
actual_term = scope.get_channel_termination(1)
|
||||
print(f" Verified: {actual_scale}V/div, {actual_offset}V offset, {actual_coupling} coupling, {actual_term}Ω\n")
|
||||
|
||||
# Configure horizontal timebase
|
||||
# For 1MHz square wave (1µs period), let's capture ~4 cycles (4µs)
|
||||
# 4µs over 10 divisions = 400ns/div
|
||||
print("Configuring horizontal timebase...")
|
||||
print(" Setting time scale to 400ns/div (4µs total for ~4 cycles of 1MHz)...")
|
||||
scope.set_time_scale(400e-9) # 400ns/div
|
||||
print(" Setting record length to 2500 points...")
|
||||
scope.set_record_length(2500)
|
||||
|
||||
# Verify settings
|
||||
actual_time_scale = scope.get_time_scale()
|
||||
actual_record_length = scope.get_record_length()
|
||||
actual_sample_rate = scope.get_sample_rate()
|
||||
print(f" Verified: {actual_time_scale*1e9:.0f}ns/div, {actual_record_length} points")
|
||||
print(f" Sample rate: {actual_sample_rate/1e6:.1f} MS/s\n")
|
||||
|
||||
# Configure trigger
|
||||
print("Configuring trigger...")
|
||||
print(" Setting trigger source to CH1...")
|
||||
scope.set_trigger_source('CH1')
|
||||
print(" Setting trigger level to +100mV...")
|
||||
scope.set_trigger_level(1, 0.1) # +100mV
|
||||
print(" Setting trigger slope to rising...")
|
||||
scope.set_trigger_slope('RISE')
|
||||
print(" Setting trigger mode to NORMAL...")
|
||||
scope.set_trigger_mode('NORMAL')
|
||||
print(" Setting trigger coupling to DC...")
|
||||
scope.set_trigger_coupling('DC')
|
||||
|
||||
# Verify trigger settings
|
||||
actual_trigger_source = scope.get_trigger_source()
|
||||
actual_trigger_level = scope.get_trigger_level(1)
|
||||
actual_trigger_slope = scope.get_trigger_slope()
|
||||
actual_trigger_mode = scope.get_trigger_mode()
|
||||
print(f" Verified: {actual_trigger_source}, {actual_trigger_level}V, {actual_trigger_slope}, {actual_trigger_mode}\n")
|
||||
|
||||
# Configure FastFrame
|
||||
print("Configuring FastFrame...")
|
||||
print(" Enabling FastFrame...")
|
||||
scope.set_fastframe_state(True)
|
||||
print(" Setting frame count to 1000...")
|
||||
scope.set_fastframe_count(1000)
|
||||
|
||||
# Verify FastFrame settings
|
||||
ff_state = scope.get_fastframe_state()
|
||||
ff_count = scope.get_fastframe_count()
|
||||
print(f" Verified: FastFrame {'enabled' if ff_state else 'disabled'}, {ff_count} frames\n")
|
||||
|
||||
# Configure waveform transfer
|
||||
print("Configuring waveform transfer...")
|
||||
scope.set_data_encoding('RIBinary')
|
||||
scope.set_wfmoutpre_encoding('BINary')
|
||||
scope.set_wfmoutpre_byte_count(1)
|
||||
scope.set_wfmoutpre_byte_order('MSB')
|
||||
scope.set_data_source('CH1')
|
||||
|
||||
# Verify configuration
|
||||
actual_encoding = scope.get_data_encoding()
|
||||
actual_source = scope.get_data_source()
|
||||
print(f" Verified: {actual_encoding} encoding, source {actual_source}")
|
||||
print(" Data transfer configured for 8-bit signed binary\n")
|
||||
|
||||
print("=== Acquiring FastFrame Records ===\n")
|
||||
|
||||
# Wait for FastFrame settings to take effect
|
||||
print("Waiting for FastFrame configuration to settle...")
|
||||
time.sleep(0.5)
|
||||
|
||||
# Start acquisition - this arms the scope and begins acquiring triggered frames
|
||||
print("Starting acquisition (arming scope)...")
|
||||
scope.write("ACQuire:STATE RUN")
|
||||
print(" Scope is now armed and acquiring triggered events")
|
||||
|
||||
# Wait and poll for acquisition to complete
|
||||
print(f" Waiting for {ff_count} triggers to be acquired...")
|
||||
print(" (Polling acquisition state...)")
|
||||
|
||||
# Poll for up to 10 seconds
|
||||
for i in range(100):
|
||||
time.sleep(0.1)
|
||||
state = scope.query("ACQuire:STATE?")
|
||||
if i % 10 == 0: # Print every second
|
||||
print(f" Polling... state: {state.strip()}")
|
||||
# Check if we've acquired enough frames
|
||||
if i > 20: # After 2 seconds minimum
|
||||
break
|
||||
|
||||
# Stop acquisition
|
||||
print(" Stopping acquisition...")
|
||||
scope.write("ACQuire:STATE STOP")
|
||||
|
||||
# Verify we have frames
|
||||
time.sleep(0.2)
|
||||
print("✓ Acquisition stopped, scope should now have all 1000 frames\n")
|
||||
|
||||
# Clear any leftover data in the receive buffer
|
||||
print("Clearing receive buffer...")
|
||||
scope.socket.setblocking(False)
|
||||
try:
|
||||
while True:
|
||||
junk = scope.socket.recv(4096)
|
||||
if not junk:
|
||||
break
|
||||
print(f" Cleared {len(junk)} bytes of junk data")
|
||||
except:
|
||||
pass
|
||||
scope.socket.setblocking(True)
|
||||
print(" Buffer cleared\n")
|
||||
|
||||
# Test transferring a single frame first
|
||||
print("Testing single frame transfer first...")
|
||||
try:
|
||||
scope.set_fastframe_selected(1)
|
||||
print(" Selected frame 1")
|
||||
test_curve = scope.transfer_curve()
|
||||
print(f" ✓ Successfully transferred {len(test_curve)} bytes")
|
||||
test_waveform = scope.parse_curve_data(test_curve, byte_count=1, signed=True, byte_order='MSB')
|
||||
print(f" ✓ Parsed {len(test_waveform)} samples")
|
||||
print(f" First 10 values: {test_waveform[:10]}\n")
|
||||
except Exception as e:
|
||||
print(f" ✗ Single frame test failed: {e}")
|
||||
print(" Cannot proceed with bulk transfer\n")
|
||||
raise
|
||||
|
||||
# Now transfer all 1000 frames
|
||||
print(f"Transferring {ff_count} frames from scope...")
|
||||
print("This may take a while...\n")
|
||||
|
||||
start_time = time.time()
|
||||
all_waveforms = []
|
||||
|
||||
for frame_num in range(1, ff_count + 1):
|
||||
# Show progress every 100 frames
|
||||
if frame_num % 100 == 0 or frame_num == 1:
|
||||
elapsed = time.time() - start_time
|
||||
if frame_num > 1:
|
||||
rate = frame_num / elapsed
|
||||
eta = (ff_count - frame_num) / rate
|
||||
print(f" Frame {frame_num}/{ff_count} - Elapsed: {elapsed:.1f}s - Rate: {rate:.1f} frames/s - ETA: {eta:.1f}s")
|
||||
else:
|
||||
print(f" Frame {frame_num}/{ff_count}...")
|
||||
|
||||
# Select this frame
|
||||
scope.set_fastframe_selected(frame_num)
|
||||
|
||||
# Verify frame selection for first frame
|
||||
if frame_num == 1:
|
||||
actual_frame = scope.get_fastframe_selected()
|
||||
if actual_frame != frame_num:
|
||||
print(f" Warning: Frame mismatch - requested {frame_num}, got {actual_frame}")
|
||||
|
||||
# Transfer curve data directly with longer timeout
|
||||
old_timeout = scope.socket.gettimeout()
|
||||
scope.socket.settimeout(30.0)
|
||||
|
||||
try:
|
||||
curve_bytes = scope.transfer_curve()
|
||||
waveform = scope.parse_curve_data(curve_bytes, byte_count=1, signed=True, byte_order='MSB')
|
||||
all_waveforms.append(waveform)
|
||||
finally:
|
||||
scope.socket.settimeout(old_timeout)
|
||||
|
||||
end_time = time.time()
|
||||
total_time = end_time - start_time
|
||||
|
||||
print(f"\n✓ Acquired all {ff_count} frames in {total_time:.2f} seconds")
|
||||
print(f" Average rate: {ff_count / total_time:.2f} frames/second")
|
||||
print(f" Average time per frame: {total_time / ff_count * 1000:.2f} ms\n")
|
||||
|
||||
# Analyze the acquired data
|
||||
print("=== Waveform Statistics ===\n")
|
||||
|
||||
# Check that all frames have the expected length
|
||||
frame_lengths = [len(wf) for wf in all_waveforms]
|
||||
print(f"Frame lengths: {min(frame_lengths)} to {max(frame_lengths)} points")
|
||||
|
||||
# Calculate statistics for first frame
|
||||
first_frame = all_waveforms[0]
|
||||
print(f"\nFirst frame (frame 1):")
|
||||
print(f" Samples: {len(first_frame)}")
|
||||
print(f" Min ADC value: {min(first_frame)}")
|
||||
print(f" Max ADC value: {max(first_frame)}")
|
||||
print(f" Average ADC value: {sum(first_frame) / len(first_frame):.2f}")
|
||||
print(f" First 20 values: {first_frame[:20]}")
|
||||
|
||||
# Calculate statistics for middle frame
|
||||
mid_frame_idx = ff_count // 2
|
||||
mid_frame = all_waveforms[mid_frame_idx]
|
||||
print(f"\nMiddle frame (frame {mid_frame_idx + 1}):")
|
||||
print(f" Samples: {len(mid_frame)}")
|
||||
print(f" Min ADC value: {min(mid_frame)}")
|
||||
print(f" Max ADC value: {max(mid_frame)}")
|
||||
print(f" Average ADC value: {sum(mid_frame) / len(mid_frame):.2f}")
|
||||
|
||||
# Calculate statistics for last frame
|
||||
last_frame = all_waveforms[-1]
|
||||
print(f"\nLast frame (frame {ff_count}):")
|
||||
print(f" Samples: {len(last_frame)}")
|
||||
print(f" Min ADC value: {min(last_frame)}")
|
||||
print(f" Max ADC value: {max(last_frame)}")
|
||||
print(f" Average ADC value: {sum(last_frame) / len(last_frame):.2f}")
|
||||
|
||||
# Calculate overall statistics
|
||||
all_values = [val for wf in all_waveforms for val in wf]
|
||||
print(f"\nOverall statistics (all {ff_count} frames, {len(all_values)} total samples):")
|
||||
print(f" Min ADC value: {min(all_values)}")
|
||||
print(f" Max ADC value: {max(all_values)}")
|
||||
print(f" Average ADC value: {sum(all_values) / len(all_values):.2f}")
|
||||
print(f" Total data transferred: {len(all_values)} bytes")
|
||||
print(f" Transfer rate: {len(all_values) / total_time / 1024 / 1024:.2f} MB/s")
|
||||
|
||||
# Check for square wave characteristics
|
||||
print(f"\nSquare wave detection:")
|
||||
# A square wave should have values clustered around two levels
|
||||
positive_samples = sum(1 for v in first_frame if v > 0)
|
||||
negative_samples = sum(1 for v in first_frame if v < 0)
|
||||
zero_samples = sum(1 for v in first_frame if v == 0)
|
||||
print(f" Frame 1: {positive_samples} positive, {negative_samples} negative, {zero_samples} zero samples")
|
||||
|
||||
# Estimate duty cycle from first frame
|
||||
if len(first_frame) > 0:
|
||||
duty_cycle = (positive_samples / len(first_frame)) * 100
|
||||
print(f" Estimated duty cycle: {duty_cycle:.1f}%")
|
||||
|
||||
print("\n=== FastFrame Acquisition Test Completed Successfully! ===")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nError: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
# Try to disable FastFrame before disconnecting
|
||||
try:
|
||||
print("\nDisabling FastFrame...")
|
||||
scope.set_fastframe_state(False)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
scope.disconnect()
|
||||
print("Disconnected from oscilloscope")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,155 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to verify FastFrame packed transfer hypothesis.
|
||||
|
||||
Tests if all FastFrame records come in a single CURVe? transfer,
|
||||
similar to WFMv3 file format.
|
||||
"""
|
||||
|
||||
import time
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test FastFrame packed transfer"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
num_frames = 1000
|
||||
target_record_length = 5000
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip, timeout=20.0)
|
||||
|
||||
try:
|
||||
scope.connect()
|
||||
print(f"Connected to {scope.identify()}\n")
|
||||
|
||||
# Configure CH1 for 1MHz square wave ±250mV
|
||||
print("Configuring CH1...")
|
||||
scope.set_channel_scale(1, 0.1) # 100mV/div
|
||||
scope.set_channel_offset(1, 0.0)
|
||||
scope.set_channel_coupling(1, 'DC')
|
||||
scope.set_channel_termination(1, 50)
|
||||
|
||||
# Configure horizontal for 5000 point record length
|
||||
# At 6.25 GS/s: 5000 points / 6.25e9 = 800ns window = 80ns/div
|
||||
print("Configuring horizontal for 5000 point record length...")
|
||||
scope.set_record_length(target_record_length)
|
||||
scope.set_time_scale(80e-9) # 80ns/div = 800ns window at 6.25 GS/s
|
||||
|
||||
# Check actual settings
|
||||
actual_record_length = scope.get_record_length()
|
||||
actual_time_scale = scope.get_time_scale()
|
||||
actual_sample_rate = scope.get_sample_rate()
|
||||
print(f" Record length: {actual_record_length}")
|
||||
print(f" Time scale: {actual_time_scale*1e9:.0f} ns/div")
|
||||
print(f" Sample rate: {actual_sample_rate/1e6:.1f} MS/s")
|
||||
|
||||
# Configure trigger
|
||||
print("Configuring trigger...")
|
||||
scope.set_trigger_source('CH1')
|
||||
scope.set_trigger_level(1, 0.1)
|
||||
scope.set_trigger_slope('RISE')
|
||||
scope.set_trigger_mode('NORMAL')
|
||||
|
||||
# Configure FastFrame
|
||||
print(f"Configuring FastFrame for {num_frames} frames...")
|
||||
scope.set_fastframe_state(True)
|
||||
scope.set_fastframe_count(num_frames)
|
||||
|
||||
# Check record length AFTER enabling FastFrame
|
||||
actual_record_length_ff = scope.get_record_length()
|
||||
actual_sample_rate_ff = scope.get_sample_rate()
|
||||
print(f" Record length after FastFrame: {actual_record_length_ff}")
|
||||
print(f" Sample rate after FastFrame: {actual_sample_rate_ff/1e6:.1f} MS/s")
|
||||
|
||||
ff_state = scope.get_fastframe_state()
|
||||
ff_count = scope.get_fastframe_count()
|
||||
print(f" FastFrame: {'enabled' if ff_state else 'disabled'}, {ff_count} frames\n")
|
||||
|
||||
# Configure waveform transfer
|
||||
print("Configuring waveform transfer...")
|
||||
scope.set_data_encoding('RIBinary')
|
||||
scope.set_wfmoutpre_encoding('BINary')
|
||||
scope.set_wfmoutpre_byte_count(1)
|
||||
scope.set_wfmoutpre_byte_order('MSB')
|
||||
scope.set_data_source('CH1')
|
||||
|
||||
# Acquire data
|
||||
print("\nAcquiring FastFrame data...")
|
||||
time.sleep(0.5)
|
||||
scope.write("ACQuire:STATE RUN")
|
||||
|
||||
# Wait for triggers (no polling - just wait)
|
||||
print(" Waiting for triggers...")
|
||||
time.sleep(3)
|
||||
|
||||
scope.write("ACQuire:STATE STOP")
|
||||
time.sleep(0.5)
|
||||
print(" Acquisition stopped\n")
|
||||
|
||||
# Transfer all frames individually
|
||||
print(f"\n=== Transferring {num_frames} Frames Individually ===\n")
|
||||
|
||||
all_waveforms = []
|
||||
start_time = time.time()
|
||||
|
||||
for frame_num in range(1, num_frames + 1):
|
||||
# Progress every 100 frames
|
||||
if frame_num == 1 or frame_num % 100 == 0:
|
||||
elapsed = time.time() - start_time
|
||||
if frame_num > 1:
|
||||
rate = frame_num / elapsed
|
||||
eta = (num_frames - frame_num) / rate
|
||||
print(f" Frame {frame_num}/{num_frames} - {elapsed:.1f}s elapsed - {rate:.1f} fps - ETA {eta:.1f}s")
|
||||
else:
|
||||
print(f" Frame {frame_num}/{num_frames}...")
|
||||
|
||||
# Select frame and wait for it to take effect
|
||||
scope.set_fastframe_selected(frame_num)
|
||||
time.sleep(0.01) # Small delay for command processing
|
||||
|
||||
# Transfer curve data
|
||||
curve_bytes = scope.transfer_curve()
|
||||
waveform = scope.parse_curve_data(curve_bytes, byte_count=1, signed=True, byte_order='MSB')
|
||||
all_waveforms.append(waveform)
|
||||
|
||||
end_time = time.time()
|
||||
total_time = end_time - start_time
|
||||
|
||||
print(f"\n=== Transfer Complete ===")
|
||||
print(f"Frames transferred: {len(all_waveforms)}")
|
||||
print(f"Points per frame: {len(all_waveforms[0])}")
|
||||
print(f"Total time: {total_time:.2f}s")
|
||||
print(f"Rate: {num_frames / total_time:.1f} frames/s")
|
||||
print(f"Total data: {sum(len(wf) for wf in all_waveforms)} samples")
|
||||
print(f"Throughput: {sum(len(wf) for wf in all_waveforms) / total_time / 1e6:.2f} MS/s")
|
||||
|
||||
# Show statistics for selected frames
|
||||
print(f"\n=== Frame Statistics ===")
|
||||
for frame_idx in [0, num_frames//2, num_frames-1]:
|
||||
wf = all_waveforms[frame_idx]
|
||||
print(f"\nFrame {frame_idx + 1}:")
|
||||
print(f" Samples: {len(wf)}")
|
||||
print(f" Min: {min(wf)}, Max: {max(wf)}, Avg: {sum(wf)/len(wf):.1f}")
|
||||
print(f" First 10: {wf[:10]}")
|
||||
|
||||
print("\n=== Test Complete ===")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nError: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
try:
|
||||
scope.set_fastframe_state(False)
|
||||
except:
|
||||
pass
|
||||
scope.disconnect()
|
||||
print("\nDisconnected")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple FastFrame test - minimal setup.
|
||||
"""
|
||||
|
||||
import time
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to {scope_ip}...")
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip, timeout=20.0)
|
||||
|
||||
try:
|
||||
scope.connect()
|
||||
print(f"Connected: {scope.identify()}\n")
|
||||
|
||||
# Configure CH1 (same as failing test)
|
||||
print("Configuring CH1...")
|
||||
scope.set_channel_scale(1, 0.1)
|
||||
scope.set_channel_offset(1, 0.0)
|
||||
scope.set_channel_coupling(1, 'DC')
|
||||
scope.set_channel_termination(1, 50)
|
||||
|
||||
# Configure horizontal (same as failing test)
|
||||
print("Configuring horizontal...")
|
||||
scope.set_record_length(5000)
|
||||
scope.set_time_scale(80e-9)
|
||||
actual_record_length = scope.get_record_length()
|
||||
actual_time_scale = scope.get_time_scale()
|
||||
actual_sample_rate = scope.get_sample_rate()
|
||||
print(f" Record: {actual_record_length}, Time: {actual_time_scale*1e9:.0f}ns/div, Rate: {actual_sample_rate/1e6:.1f}MS/s")
|
||||
|
||||
# Configure trigger (same as failing test)
|
||||
print("Configuring trigger...")
|
||||
scope.set_trigger_source('CH1')
|
||||
scope.set_trigger_level(1, 0.1)
|
||||
scope.set_trigger_slope('RISE')
|
||||
scope.set_trigger_mode('NORMAL')
|
||||
scope.set_trigger_coupling('DC')
|
||||
|
||||
# Enable FastFrame with 1000 frames
|
||||
print("Enabling FastFrame (1000 frames)...")
|
||||
scope.set_fastframe_state(True)
|
||||
scope.set_fastframe_count(1000)
|
||||
|
||||
ff_state = scope.get_fastframe_state()
|
||||
ff_count = scope.get_fastframe_count()
|
||||
print(f" State: {ff_state}, Count: {ff_count}")
|
||||
|
||||
# Configure data transfer (same as failing test)
|
||||
print("Configuring data transfer...")
|
||||
scope.set_data_encoding('RIBinary')
|
||||
scope.set_wfmoutpre_encoding('BINary')
|
||||
scope.set_wfmoutpre_byte_count(1)
|
||||
scope.set_wfmoutpre_byte_order('MSB')
|
||||
scope.set_data_source('CH1')
|
||||
|
||||
# Acquire
|
||||
print("Acquiring...")
|
||||
scope.write("ACQuire:STATE RUN")
|
||||
time.sleep(2) # Wait for triggers
|
||||
scope.write("ACQuire:STATE STOP")
|
||||
time.sleep(0.5)
|
||||
|
||||
# Check record length
|
||||
record_len = scope.get_record_length()
|
||||
print(f"Record length: {record_len}")
|
||||
|
||||
# Test: Send single CURVe? and read ALL frames
|
||||
print(f"\nTesting: Send one CURVe? and read all {ff_count} frames...")
|
||||
scope.set_fastframe_selected(1) # Start from frame 1
|
||||
scope.write("CURVe?")
|
||||
|
||||
all_waveforms = []
|
||||
start_time = time.time()
|
||||
|
||||
for frame_num in range(1, ff_count + 1):
|
||||
if frame_num == 1 or frame_num % 100 == 0:
|
||||
elapsed = time.time() - start_time
|
||||
if frame_num > 1:
|
||||
rate = frame_num / elapsed
|
||||
print(f" Frame {frame_num}/{ff_count} - {rate:.1f} fps")
|
||||
else:
|
||||
print(f" Frame {frame_num}/{ff_count}...")
|
||||
|
||||
# Read one frame using read_raw (no new CURVe? command)
|
||||
curve_bytes = scope.read_raw()
|
||||
waveform = scope.parse_curve_data(curve_bytes, byte_count=1, signed=True)
|
||||
all_waveforms.append(waveform)
|
||||
|
||||
end_time = time.time()
|
||||
total_time = end_time - start_time
|
||||
|
||||
print(f"\nTransferred {len(all_waveforms)} frames in {total_time:.2f}s")
|
||||
print(f"Rate: {ff_count / total_time:.1f} frames/s")
|
||||
print(f"Points per frame: {len(all_waveforms[0])}")
|
||||
print(f"First frame: min={min(all_waveforms[0])}, max={max(all_waveforms[0])}")
|
||||
print(f"Last frame: min={min(all_waveforms[-1])}, max={max(all_waveforms[-1])}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nError: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
try:
|
||||
scope.set_fastframe_state(False)
|
||||
print("FastFrame disabled")
|
||||
except:
|
||||
pass
|
||||
scope.disconnect()
|
||||
print("Disconnected")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for horizontal mode control functionality.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test horizontal mode functions on oscilloscope at 192.168.10.105"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip)
|
||||
|
||||
try:
|
||||
# Connect to scope
|
||||
scope.connect()
|
||||
print(f"✓ Connected to {scope.identify()}\n")
|
||||
|
||||
# Get current horizontal settings
|
||||
print("Getting current horizontal settings...")
|
||||
current_record_length = scope.get_record_length()
|
||||
current_sample_rate = scope.get_sample_rate()
|
||||
current_time_scale = scope.get_time_scale()
|
||||
print(f"✓ Current record length: {current_record_length} samples")
|
||||
print(f"✓ Current sample rate: {current_sample_rate} S/s")
|
||||
print(f"✓ Current time scale: {current_time_scale} s/div\n")
|
||||
|
||||
# Test setting record length
|
||||
print("Testing record length changes:")
|
||||
test_lengths = [1000, 10000, 100000]
|
||||
for length in test_lengths:
|
||||
print(f" Setting record length to {length}...")
|
||||
scope.set_record_length(length)
|
||||
actual_length = scope.get_record_length()
|
||||
print(f" ✓ Actual record length: {actual_length}")
|
||||
|
||||
# Test setting sample rate
|
||||
print("\nTesting sample rate changes:")
|
||||
test_rates = [1e6, 10e6, 100e6] # 1 MS/s, 10 MS/s, 100 MS/s
|
||||
for rate in test_rates:
|
||||
print(f" Setting sample rate to {rate:.0f} S/s...")
|
||||
scope.set_sample_rate(rate)
|
||||
actual_rate = scope.get_sample_rate()
|
||||
print(f" ✓ Actual sample rate: {actual_rate:.0f} S/s")
|
||||
|
||||
# Test setting time scale
|
||||
print("\nTesting time scale changes:")
|
||||
test_scales = [1e-6, 10e-6, 100e-6, 1e-3] # 1 µs/div, 10 µs/div, 100 µs/div, 1 ms/div
|
||||
for scale in test_scales:
|
||||
print(f" Setting time scale to {scale:.6f} s/div...")
|
||||
scope.set_time_scale(scale)
|
||||
actual_scale = scope.get_time_scale()
|
||||
print(f" ✓ Actual time scale: {actual_scale:.6f} s/div")
|
||||
|
||||
# Restore original settings
|
||||
print(f"\nRestoring original settings...")
|
||||
scope.set_record_length(current_record_length)
|
||||
scope.set_sample_rate(current_sample_rate)
|
||||
scope.set_time_scale(current_time_scale)
|
||||
print(f"✓ Restored record length: {scope.get_record_length()}")
|
||||
print(f"✓ Restored sample rate: {scope.get_sample_rate()}")
|
||||
print(f"✓ Restored time scale: {scope.get_time_scale()}")
|
||||
|
||||
# Test invalid inputs
|
||||
print("\nTesting invalid record length (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_record_length(-1)
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid sample rate (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_sample_rate(0)
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid time scale (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_time_scale(-1.0)
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Error: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\n✓ Disconnected from oscilloscope")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple curve transfer test - no FastFrame.
|
||||
"""
|
||||
|
||||
import time
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to {scope_ip}...")
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip, timeout=20.0)
|
||||
|
||||
try:
|
||||
scope.connect()
|
||||
print(f"Connected: {scope.identify()}\n")
|
||||
|
||||
# Make sure FastFrame is OFF
|
||||
print("Disabling FastFrame...")
|
||||
scope.set_fastframe_state(False)
|
||||
|
||||
# Configure simple acquisition
|
||||
print("Configuring acquisition...")
|
||||
scope.set_data_encoding('RIBinary')
|
||||
scope.set_data_source('CH1')
|
||||
|
||||
# Single acquisition
|
||||
print("Running single acquisition...")
|
||||
scope.write("ACQuire:STATE RUN")
|
||||
time.sleep(0.5)
|
||||
scope.write("ACQuire:STATE STOP")
|
||||
time.sleep(0.2)
|
||||
|
||||
# Transfer curve
|
||||
print("Transferring curve data...")
|
||||
curve_bytes = scope.transfer_curve()
|
||||
print(f"Received {len(curve_bytes)} bytes")
|
||||
|
||||
# Parse
|
||||
waveform = scope.parse_curve_data(curve_bytes, byte_count=1, signed=True)
|
||||
print(f"Parsed {len(waveform)} samples")
|
||||
print(f"Min: {min(waveform)}, Max: {max(waveform)}")
|
||||
print(f"First 10: {waveform[:10]}")
|
||||
|
||||
print("\nSuccess!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nError: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("Disconnected")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple test to debug query timeout issues.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
import time
|
||||
|
||||
|
||||
def main():
|
||||
"""Test simple queries with the oscilloscope"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip, timeout=10.0)
|
||||
|
||||
try:
|
||||
# Connect
|
||||
scope.connect()
|
||||
print("✓ Connected")
|
||||
|
||||
# Wait a moment to ensure connection is stable
|
||||
time.sleep(0.5)
|
||||
|
||||
# Try a simple query
|
||||
print("\nSending *IDN? query...")
|
||||
idn = scope.query("*IDN?")
|
||||
print(f"✓ Response: {idn}")
|
||||
|
||||
# Try acquisition mode query
|
||||
print("\nSending ACQuire:MODe? query...")
|
||||
mode = scope.query("ACQuire:MODe?")
|
||||
print(f"✓ Current mode: {mode}")
|
||||
|
||||
# Set mode to sample using short form
|
||||
print("\nSetting mode to SAM (short form)...")
|
||||
scope.set_acquire_mode("SAM")
|
||||
|
||||
# Verify
|
||||
mode = scope.get_acquire_mode()
|
||||
print(f"✓ Mode is now: {mode}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Error: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\n✓ Disconnected")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple test to verify basic waveform acquisition works.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test single waveform acquisition from CH1"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
print(f"Connecting to {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip, timeout=15.0)
|
||||
|
||||
try:
|
||||
scope.connect()
|
||||
print(f"✓ Connected to {scope.identify()}\n")
|
||||
|
||||
# Check current settings
|
||||
print("Current settings:")
|
||||
print(f" Data encoding: {scope.get_data_encoding()}")
|
||||
print(f" Data source: {scope.get_data_source()}")
|
||||
print(f" Record length: {scope.get_record_length()}")
|
||||
print(f" FastFrame state: {scope.get_fastframe_state()}\n")
|
||||
|
||||
# Ensure FastFrame is off
|
||||
if scope.get_fastframe_state():
|
||||
print("Disabling FastFrame...")
|
||||
scope.set_fastframe_state(False)
|
||||
|
||||
# Set data source to CH1
|
||||
print("Setting data source to CH1...")
|
||||
scope.set_data_source('CH1')
|
||||
|
||||
# Try to acquire a single waveform
|
||||
print("\nAttempting to acquire waveform from CH1...")
|
||||
print("(This will timeout if the scope isn't responding properly)\n")
|
||||
|
||||
waveform = scope.acquire_waveform('CH1')
|
||||
|
||||
print(f"✓ SUCCESS! Acquired {len(waveform)} samples")
|
||||
print(f" First 10 values: {waveform[:10]}")
|
||||
print(f" Min: {min(waveform)}, Max: {max(waveform)}")
|
||||
print(f" Average: {sum(waveform)/len(waveform):.2f}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ Error: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\n✓ Disconnected")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for transfer_fastframe() method.
|
||||
|
||||
Tests bulk FastFrame transfer with 1MHz square wave on CH1.
|
||||
Signal: 1MHz square wave, +125mV to -125mV
|
||||
"""
|
||||
|
||||
import time
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
scope_ip = "192.168.10.105"
|
||||
num_frames = 1000
|
||||
|
||||
print(f"Connecting to {scope_ip}...")
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip, timeout=30.0)
|
||||
|
||||
try:
|
||||
scope.connect()
|
||||
print(f"Connected: {scope.identify()}\n")
|
||||
|
||||
# Configure CH1
|
||||
print("Configuring CH1...")
|
||||
scope.set_channel_scale(1, 0.1) # 100mV/div
|
||||
scope.set_channel_offset(1, 0.0)
|
||||
scope.set_channel_coupling(1, 'DC')
|
||||
scope.set_channel_termination(1, 50)
|
||||
|
||||
# Configure horizontal
|
||||
print("Configuring horizontal...")
|
||||
scope.set_record_length(5000)
|
||||
scope.set_time_scale(80e-9) # 80ns/div
|
||||
|
||||
# Configure trigger
|
||||
print("Configuring trigger...")
|
||||
scope.set_trigger_source('CH1')
|
||||
scope.set_trigger_level(1, 0.05) # 50mV
|
||||
scope.set_trigger_slope('RISE')
|
||||
scope.set_trigger_mode('NORMAL')
|
||||
|
||||
# Configure FastFrame
|
||||
print(f"Configuring FastFrame ({num_frames} frames)...")
|
||||
scope.set_fastframe_state(True)
|
||||
scope.set_fastframe_count(num_frames)
|
||||
|
||||
# Verify settings
|
||||
ff_count = scope.get_fastframe_count()
|
||||
record_len = scope.get_record_length()
|
||||
print(f" Frames: {ff_count}, Record length: {record_len}")
|
||||
|
||||
# Configure data transfer
|
||||
print("Configuring data transfer...")
|
||||
scope.set_data_encoding('RIBinary')
|
||||
scope.set_data_source('CH1')
|
||||
|
||||
# Acquire
|
||||
print("\nAcquiring FastFrame data...")
|
||||
scope.write("ACQuire:STATE RUN")
|
||||
time.sleep(2) # Wait for triggers
|
||||
scope.write("ACQuire:STATE STOP")
|
||||
time.sleep(0.5)
|
||||
print(" Acquisition complete")
|
||||
|
||||
# Transfer all frames using the new method
|
||||
print(f"\nTransferring {ff_count} frames using transfer_fastframe()...")
|
||||
start_time = time.time()
|
||||
|
||||
waveforms = scope.transfer_fastframe(parse=True, byte_count=1, signed=True)
|
||||
|
||||
end_time = time.time()
|
||||
total_time = end_time - start_time
|
||||
|
||||
# Results
|
||||
print(f"\n=== Transfer Complete ===")
|
||||
print(f"Frames received: {len(waveforms)}")
|
||||
print(f"Points per frame: {len(waveforms[0])}")
|
||||
print(f"Total samples: {sum(len(wf) for wf in waveforms)}")
|
||||
print(f"Transfer time: {total_time:.3f}s")
|
||||
print(f"Frame rate: {len(waveforms) / total_time:.1f} frames/s")
|
||||
print(f"Sample rate: {sum(len(wf) for wf in waveforms) / total_time / 1e6:.2f} MS/s")
|
||||
|
||||
# Waveform statistics
|
||||
print(f"\n=== Waveform Statistics ===")
|
||||
print(f"Frame 1: min={min(waveforms[0])}, max={max(waveforms[0])}, avg={sum(waveforms[0])/len(waveforms[0]):.1f}")
|
||||
print(f"Frame {len(waveforms)//2}: min={min(waveforms[len(waveforms)//2])}, max={max(waveforms[len(waveforms)//2])}")
|
||||
print(f"Frame {len(waveforms)}: min={min(waveforms[-1])}, max={max(waveforms[-1])}")
|
||||
|
||||
# Check for square wave
|
||||
first_frame = waveforms[0]
|
||||
positive = sum(1 for v in first_frame if v > 0)
|
||||
negative = sum(1 for v in first_frame if v < 0)
|
||||
print(f"\nSquare wave check (frame 1): {positive} positive, {negative} negative samples")
|
||||
print(f"Duty cycle estimate: {positive / len(first_frame) * 100:.1f}%")
|
||||
|
||||
print("\n=== Success! ===")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nError: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
try:
|
||||
scope.set_fastframe_state(False)
|
||||
print("\nFastFrame disabled")
|
||||
except:
|
||||
pass
|
||||
scope.disconnect()
|
||||
print("Disconnected")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for trigger control functionality.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test trigger functions on oscilloscope at 192.168.10.105"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip)
|
||||
|
||||
try:
|
||||
# Connect to scope
|
||||
scope.connect()
|
||||
print(f"✓ Connected to {scope.identify()}\n")
|
||||
|
||||
# Get current trigger settings
|
||||
print("Getting current trigger settings...")
|
||||
current_coupling = scope.get_trigger_coupling()
|
||||
current_slope = scope.get_trigger_slope()
|
||||
current_source = scope.get_trigger_source()
|
||||
current_mode = scope.get_trigger_mode()
|
||||
print(f"✓ Current trigger coupling: {current_coupling}")
|
||||
print(f"✓ Current trigger slope: {current_slope}")
|
||||
print(f"✓ Current trigger source: {current_source}")
|
||||
print(f"✓ Current trigger mode: {current_mode}")
|
||||
|
||||
# Get trigger level for current source
|
||||
# Extract channel number from source
|
||||
if current_source.startswith('CH'):
|
||||
channel = int(current_source[2])
|
||||
current_level = scope.get_trigger_level(channel)
|
||||
print(f"✓ Current trigger level for {current_source}: {current_level} V\n")
|
||||
else:
|
||||
current_level = 0.0
|
||||
channel = 1
|
||||
print(f" (Source is {current_source}, not a channel)\n")
|
||||
|
||||
# Test trigger coupling
|
||||
print("Testing trigger coupling modes:")
|
||||
test_couplings = ['DC', 'HFRej', 'LFRej', 'NOISErej']
|
||||
for coupling in test_couplings:
|
||||
print(f" Setting coupling to {coupling}...")
|
||||
scope.set_trigger_coupling(coupling)
|
||||
actual_coupling = scope.get_trigger_coupling()
|
||||
print(f" ✓ Actual coupling: {actual_coupling}")
|
||||
|
||||
# Test trigger slope
|
||||
print("\nTesting trigger slope modes:")
|
||||
test_slopes = ['RISe', 'FALL', 'EITher']
|
||||
for slope in test_slopes:
|
||||
print(f" Setting slope to {slope}...")
|
||||
scope.set_trigger_slope(slope)
|
||||
actual_slope = scope.get_trigger_slope()
|
||||
print(f" ✓ Actual slope: {actual_slope}")
|
||||
|
||||
# Test trigger source
|
||||
print("\nTesting trigger source selection:")
|
||||
test_sources = ['CH1', 'CH2', 'CH3', 'CH4']
|
||||
for source in test_sources:
|
||||
print(f" Setting source to {source}...")
|
||||
scope.set_trigger_source(source)
|
||||
actual_source = scope.get_trigger_source()
|
||||
print(f" ✓ Actual source: {actual_source}")
|
||||
|
||||
# Test trigger source with integer
|
||||
print("\nTesting trigger source with integer (2)...")
|
||||
scope.set_trigger_source(2)
|
||||
actual_source = scope.get_trigger_source()
|
||||
print(f"✓ Actual source: {actual_source}")
|
||||
|
||||
# Test trigger level
|
||||
print("\nTesting trigger level settings:")
|
||||
test_levels = [0.0, 0.5, 1.0, -0.5, 2.5]
|
||||
for level in test_levels:
|
||||
print(f" Setting CH1 trigger level to {level} V...")
|
||||
scope.set_trigger_level(1, level)
|
||||
actual_level = scope.get_trigger_level(1)
|
||||
print(f" ✓ Actual level: {actual_level} V")
|
||||
|
||||
# Test trigger level with channel string
|
||||
print("\nTesting trigger level with channel string ('CH2')...")
|
||||
scope.set_trigger_level('CH2', 1.5)
|
||||
actual_level = scope.get_trigger_level('CH2')
|
||||
print(f"✓ Actual level: {actual_level} V")
|
||||
|
||||
# Test trigger mode
|
||||
print("\nTesting trigger modes:")
|
||||
test_modes = ['AUTO', 'NORMal']
|
||||
for mode in test_modes:
|
||||
print(f" Setting trigger mode to {mode}...")
|
||||
scope.set_trigger_mode(mode)
|
||||
actual_mode = scope.get_trigger_mode()
|
||||
print(f" ✓ Actual mode: {actual_mode}")
|
||||
|
||||
# Restore original settings
|
||||
print(f"\nRestoring original trigger settings...")
|
||||
scope.set_trigger_coupling(current_coupling)
|
||||
scope.set_trigger_slope(current_slope)
|
||||
scope.set_trigger_source(current_source)
|
||||
scope.set_trigger_mode(current_mode)
|
||||
if current_source.startswith('CH'):
|
||||
scope.set_trigger_level(channel, current_level)
|
||||
print(f"✓ Restored trigger coupling: {scope.get_trigger_coupling()}")
|
||||
print(f"✓ Restored trigger slope: {scope.get_trigger_slope()}")
|
||||
print(f"✓ Restored trigger source: {scope.get_trigger_source()}")
|
||||
print(f"✓ Restored trigger mode: {scope.get_trigger_mode()}")
|
||||
|
||||
# Test invalid inputs
|
||||
print("\nTesting invalid coupling (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_trigger_coupling("INVALID")
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid slope (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_trigger_slope("INVALID")
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid source (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_trigger_source("CH5")
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid channel for trigger level (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_trigger_level(5, 0.0)
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid trigger mode (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_trigger_mode("INVALID")
|
||||
print("✗ ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f"✓ Correctly raised ValueError: {e}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ Error: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\n✓ Disconnected from oscilloscope")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+273
@@ -0,0 +1,273 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for waveform transfer functionality.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Test waveform transfer functions on oscilloscope at 192.168.10.105"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip)
|
||||
|
||||
try:
|
||||
# Connect to scope
|
||||
scope.connect()
|
||||
print(f"Connected to {scope.identify()}\n")
|
||||
|
||||
# Save current settings
|
||||
print("Saving current waveform transfer settings...")
|
||||
current_data_encoding = scope.get_data_encoding()
|
||||
current_data_source = scope.get_data_source()
|
||||
current_wfmoutpre_encoding = scope.get_wfmoutpre_encoding()
|
||||
current_byte_count = scope.get_wfmoutpre_byte_count()
|
||||
current_byte_order = scope.get_wfmoutpre_byte_order()
|
||||
print(f" Current data encoding: {current_data_encoding}")
|
||||
print(f" Current data source: {current_data_source}")
|
||||
print(f" Current WFMOutpre encoding: {current_wfmoutpre_encoding}")
|
||||
print(f" Current byte count: {current_byte_count}")
|
||||
print(f" Current byte order: {current_byte_order}\n")
|
||||
|
||||
# Test setting data encoding
|
||||
print("Testing data encoding settings:")
|
||||
test_encodings = ['ASCIi', 'RIBinary', 'RPBinary']
|
||||
for encoding in test_encodings:
|
||||
print(f" Setting data encoding to {encoding}...")
|
||||
scope.set_data_encoding(encoding)
|
||||
actual = scope.get_data_encoding()
|
||||
print(f" Actual encoding: {actual}")
|
||||
|
||||
# Test setting data source
|
||||
print("\nTesting data source selection:")
|
||||
for source in ['CH1', 'CH2', 'CH3', 'CH4']:
|
||||
print(f" Setting data source to {source}...")
|
||||
scope.set_data_source(source)
|
||||
actual = scope.get_data_source()
|
||||
print(f" Actual source: {actual}")
|
||||
|
||||
# Test with integer source
|
||||
print("\nTesting data source with integer (2)...")
|
||||
scope.set_data_source(2)
|
||||
actual = scope.get_data_source()
|
||||
print(f" Actual source: {actual}")
|
||||
|
||||
# Test waveform preamble encoding
|
||||
print("\nTesting waveform preamble encoding:")
|
||||
for encoding in ['BINary', 'ASCii']:
|
||||
print(f" Setting WFMOutpre encoding to {encoding}...")
|
||||
scope.set_wfmoutpre_encoding(encoding)
|
||||
actual = scope.get_wfmoutpre_encoding()
|
||||
print(f" Actual encoding: {actual}")
|
||||
|
||||
# Test byte count
|
||||
print("\nTesting byte count settings:")
|
||||
for byte_count in [1, 2]:
|
||||
print(f" Setting byte count to {byte_count}...")
|
||||
scope.set_wfmoutpre_byte_count(byte_count)
|
||||
actual = scope.get_wfmoutpre_byte_count()
|
||||
print(f" Actual byte count: {actual}")
|
||||
|
||||
# Test byte order
|
||||
print("\nTesting byte order settings:")
|
||||
for byte_order in ['MSB', 'LSB']:
|
||||
print(f" Setting byte order to {byte_order}...")
|
||||
scope.set_wfmoutpre_byte_order(byte_order)
|
||||
actual = scope.get_wfmoutpre_byte_order()
|
||||
print(f" Actual byte order: {actual}")
|
||||
|
||||
# Query complete waveform preamble
|
||||
print("\nQuerying complete waveform preamble...")
|
||||
preamble = scope.query_wfmoutpre()
|
||||
print(f" Preamble (first 100 chars): {preamble[:100]}...")
|
||||
|
||||
# Set up for binary waveform acquisition
|
||||
print("\nConfiguring for binary waveform transfer:")
|
||||
print(" Setting data encoding to RIBinary...")
|
||||
scope.set_data_encoding('RIBinary')
|
||||
print(" Setting WFMOutpre encoding to BINary...")
|
||||
scope.set_wfmoutpre_encoding('BINary')
|
||||
print(" Setting byte count to 1...")
|
||||
scope.set_wfmoutpre_byte_count(1)
|
||||
print(" Setting byte order to MSB...")
|
||||
scope.set_wfmoutpre_byte_order('MSB')
|
||||
print(" Setting data source to CH1...")
|
||||
scope.set_data_source('CH1')
|
||||
print(" Configuration complete")
|
||||
|
||||
# Transfer curve data
|
||||
print("\nTransferring curve data from CH1...")
|
||||
curve_data = scope.transfer_curve()
|
||||
print(f" Received {len(curve_data)} bytes of curve data")
|
||||
print(f" First 10 bytes (raw): {list(curve_data[:10])}")
|
||||
|
||||
# Parse the curve data
|
||||
print("\nParsing curve data...")
|
||||
values = scope.parse_curve_data(curve_data, byte_count=1, signed=True, byte_order='MSB')
|
||||
print(f" Parsed {len(values)} samples")
|
||||
print(f" First 10 values: {values[:10]}")
|
||||
print(f" Min value: {min(values)}")
|
||||
print(f" Max value: {max(values)}")
|
||||
print(f" Average value: {sum(values) / len(values):.2f}")
|
||||
|
||||
# Transfer complete waveform (preamble + curve)
|
||||
print("\nTransferring complete waveform (WAVFrm?)...")
|
||||
preamble_str, curve_bytes = scope.transfer_waveform()
|
||||
print(f" Received preamble: {preamble_str[:100]}...")
|
||||
print(f" Received {len(curve_bytes)} bytes of curve data")
|
||||
|
||||
# Parse this curve data too
|
||||
waveform_values = scope.parse_curve_data(curve_bytes, byte_count=1, signed=True, byte_order='MSB')
|
||||
print(f" Parsed {len(waveform_values)} samples from complete waveform")
|
||||
|
||||
# Test high-level acquire_waveform method
|
||||
print("\nTesting high-level acquire_waveform method:")
|
||||
print(" Acquiring waveform from CH1...")
|
||||
waveform = scope.acquire_waveform('CH1')
|
||||
print(f" Acquired {len(waveform)} samples")
|
||||
print(f" First 10 values: {waveform[:10]}")
|
||||
print(f" Min: {min(waveform)}, Max: {max(waveform)}, Avg: {sum(waveform)/len(waveform):.2f}")
|
||||
|
||||
print("\n Acquiring waveform from CH2 (using integer)...")
|
||||
try:
|
||||
waveform2 = scope.acquire_waveform(2)
|
||||
print(f" Acquired {len(waveform2)} samples from CH2")
|
||||
print(f" First 10 values: {waveform2[:10]}")
|
||||
except Exception as e:
|
||||
print(f" Could not acquire from CH2 (channel may not be active): {e}")
|
||||
|
||||
# Test FastFrame support
|
||||
print("\nTesting FastFrame frame selection:")
|
||||
|
||||
# Check if FastFrame is currently enabled
|
||||
try:
|
||||
ff_state = scope.get_fastframe_state()
|
||||
ff_count = scope.get_fastframe_count()
|
||||
print(f" Current FastFrame state: {ff_state} ({'active' if ff_state else 'off'})")
|
||||
print(f" Current frame count: {ff_count}")
|
||||
except Exception as e:
|
||||
print(f" Could not query FastFrame state (skipping FastFrame tests): {e}")
|
||||
ff_state = None
|
||||
|
||||
if ff_state is not None and ff_state:
|
||||
# FastFrame is active, test frame selection
|
||||
print(" FastFrame is active, testing frame selection...")
|
||||
current_frame = scope.get_fastframe_selected()
|
||||
print(f" Current selected frame: {current_frame}")
|
||||
|
||||
# Try selecting different frames
|
||||
for frame in [1, min(5, ff_count), ff_count]:
|
||||
print(f" Selecting frame {frame}...")
|
||||
scope.set_fastframe_selected(frame)
|
||||
actual = scope.get_fastframe_selected()
|
||||
print(f" Selected frame: {actual}")
|
||||
|
||||
# Acquire waveform from this frame
|
||||
print(f" Acquiring waveform from frame {frame}...")
|
||||
frame_waveform = scope.acquire_waveform('CH1', frame_number=frame)
|
||||
print(f" Acquired {len(frame_waveform)} samples")
|
||||
print(f" First 5 values: {frame_waveform[:5]}")
|
||||
|
||||
# Restore original frame
|
||||
scope.set_fastframe_selected(current_frame)
|
||||
elif ff_state is not None:
|
||||
print(" FastFrame is not active, enabling it temporarily...")
|
||||
scope.set_fastframe_state(True)
|
||||
scope.set_fastframe_count(10)
|
||||
print(" FastFrame enabled with 10 frames")
|
||||
|
||||
# Test frame selection
|
||||
for frame in [1, 5, 10]:
|
||||
print(f" Selecting frame {frame}...")
|
||||
scope.set_fastframe_selected(frame)
|
||||
actual = scope.get_fastframe_selected()
|
||||
print(f" Selected frame: {actual}")
|
||||
|
||||
# Restore FastFrame state
|
||||
scope.set_fastframe_state(False)
|
||||
print(" FastFrame disabled (restored)")
|
||||
|
||||
# Restore original settings
|
||||
print("\nRestoring original waveform transfer settings...")
|
||||
try:
|
||||
scope.set_data_encoding(current_data_encoding)
|
||||
scope.set_data_source(current_data_source)
|
||||
scope.set_wfmoutpre_encoding(current_wfmoutpre_encoding)
|
||||
scope.set_wfmoutpre_byte_count(current_byte_count)
|
||||
scope.set_wfmoutpre_byte_order(current_byte_order)
|
||||
print(" Settings restored")
|
||||
except Exception as e:
|
||||
print(f" Could not restore settings (connection may be in bad state): {e}")
|
||||
|
||||
# Test error handling
|
||||
print("\n=== Testing Error Handling ===\n")
|
||||
|
||||
# Skip error handling tests if connection is already bad
|
||||
try:
|
||||
# Quick connectivity check
|
||||
scope.query("*OPC?")
|
||||
except Exception:
|
||||
print("Connection appears to be in bad state, skipping error handling tests\n")
|
||||
print("=== Waveform transfer tests completed (with some skipped due to connection issues) ===")
|
||||
return
|
||||
|
||||
print("Testing invalid data encoding (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_data_encoding('INVALID')
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid data source (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_data_source('CH5')
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid byte count (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_wfmoutpre_byte_count(3)
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid byte order (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_wfmoutpre_byte_order('INVALID')
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid FastFrame frame number (should raise ValueError)...")
|
||||
try:
|
||||
scope.set_fastframe_selected(-1)
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\nTesting invalid channel in acquire_waveform (should raise ValueError)...")
|
||||
try:
|
||||
scope.acquire_waveform(5)
|
||||
print(" ERROR: Should have raised ValueError!")
|
||||
except ValueError as e:
|
||||
print(f" Correctly raised ValueError: {e}")
|
||||
|
||||
print("\n=== All waveform transfer tests completed successfully! ===")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nError: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\nDisconnected from oscilloscope")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple focused test for waveform transfer functionality.
|
||||
"""
|
||||
|
||||
from tektronix_base import TektronixOscilloscopeBase
|
||||
|
||||
|
||||
def main():
|
||||
"""Simple test of core waveform transfer on CH1"""
|
||||
|
||||
scope_ip = "192.168.10.105"
|
||||
|
||||
print(f"Connecting to oscilloscope at {scope_ip}...")
|
||||
|
||||
scope = TektronixOscilloscopeBase(resource_name=scope_ip, timeout=10.0)
|
||||
|
||||
try:
|
||||
# Connect to scope
|
||||
scope.connect()
|
||||
print(f"Connected to {scope.identify()}\n")
|
||||
|
||||
# Test 1: Configure and transfer using low-level methods
|
||||
print("=== Test 1: Low-level waveform transfer ===")
|
||||
print("Configuring data transfer settings...")
|
||||
scope.set_data_encoding('RIBinary')
|
||||
scope.set_wfmoutpre_encoding('BINary')
|
||||
scope.set_wfmoutpre_byte_count(1)
|
||||
scope.set_wfmoutpre_byte_order('MSB')
|
||||
scope.set_data_source('CH1')
|
||||
|
||||
print("Transferring curve data from CH1...")
|
||||
curve_data = scope.transfer_curve()
|
||||
print(f" Received {len(curve_data)} bytes")
|
||||
|
||||
print("Parsing curve data...")
|
||||
values = scope.parse_curve_data(curve_data, byte_count=1, signed=True, byte_order='MSB')
|
||||
print(f" Parsed {len(values)} samples")
|
||||
print(f" First 10 values: {values[:10]}")
|
||||
print(f" Min: {min(values)}, Max: {max(values)}, Avg: {sum(values)/len(values):.2f}")
|
||||
|
||||
# Test 2: Use high-level acquire_waveform method
|
||||
print("\n=== Test 2: High-level waveform acquisition ===")
|
||||
print("Acquiring waveform from CH1...")
|
||||
waveform = scope.acquire_waveform('CH1')
|
||||
print(f" Acquired {len(waveform)} samples")
|
||||
print(f" First 10 values: {waveform[:10]}")
|
||||
print(f" Min: {min(waveform)}, Max: {max(waveform)}, Avg: {sum(waveform)/len(waveform):.2f}")
|
||||
|
||||
# Test 3: Query waveform preamble
|
||||
print("\n=== Test 3: Waveform preamble ===")
|
||||
preamble = scope.query_wfmoutpre()
|
||||
print(f" Preamble: {preamble[:150]}...")
|
||||
|
||||
# Test 4: Transfer complete waveform (preamble + curve)
|
||||
print("\n=== Test 4: Complete waveform transfer ===")
|
||||
print("Transferring complete waveform...")
|
||||
preamble_str, curve_bytes = scope.transfer_waveform()
|
||||
print(f" Preamble length: {len(preamble_str)} chars")
|
||||
print(f" Curve data: {len(curve_bytes)} bytes")
|
||||
wf_values = scope.parse_curve_data(curve_bytes, byte_count=1, signed=True, byte_order='MSB')
|
||||
print(f" Parsed {len(wf_values)} samples")
|
||||
|
||||
print("\n=== All tests completed successfully! ===")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\nError: {type(e).__name__}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if scope.is_connected:
|
||||
scope.disconnect()
|
||||
print("\nDisconnected from oscilloscope")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user