This commit is contained in:
david rice
2026-03-26 15:18:58 +00:00
parent 46a2bf1571
commit 8be10c8b20

View File

@@ -12,78 +12,131 @@ import time
import sys
import requests
import threading
import os
# --- Configuration ---
URL = "http://192.168.45.8:5000/display"
SCOPE_IP = "192.168.45.4"
PSU_IP = "192.168.45.3"
url = f"http://192.168.45.8:5000/display"
test_running = False # Global flag to control the background thread
# --- Hardware Initialisation ---
# --- Instrument Connection ---
try:
psu = vxi11.Instrument("192.168.45.3")
scope = vxi11.Instrument("192.168.45.4")
setup_del = 0.2
# Increase timeout for large image data transfers
scope.timeout = 5
except Exception as e:
print(f"ERROR: CANNOT CONNECT TO INSTRUMENTS: {e}")
sys.exit(1)
def set_display(state):
""" Helper to handle HTTP PUT with error catching """
def setup_scope():
"""Initializes DSO80204B for 210MHz MIPI Signals"""
print("Configuring Scope...")
scope.write("*RST")
time.sleep(1)
# Setup Channels (1&2=Clock, 3&4=Data)
for ch in range(1, 5):
scope.write(f":CHANnel{ch}:DISPlay ON")
scope.write(f":CHANnel{ch}:PROBe 19.2") # 910R/50R Divider
scope.write(f":CHANnel{ch}:INPut DC50")
scope.write(f":CHANnel{ch}:SCALe 0.1") # 100mV/div (200mV HS swing)
scope.write(f":CHANnel{ch}:OFFSet 0.0")
# Timebase & Trigger
scope.write(":TIMebase:SCALe 10e-6") # 10us/div
scope.write(":TRIGger:EDGE:SOURce CHANnel3")
scope.write(":TRIGger:EDGE:SLOPe FALLing") # Catch LP-11 to HS transition
scope.write(":TRIGger:LEVel CHANnel3, 0.15") # 150mV
scope.write(":TRIGger:SWEep SINGle")
print("Scope Configured.")
def save_screenshot(iteration):
try:
r = requests.put(url, json={"state": state}, timeout=2)
return r.status_code == 200
scope.clear()
# Use a very short, simple path. No subdirectories if possible.
# Ensure C:\TEMP exists!
filename = f"C:\\TEMP\\cap{iteration}.png"
except requests.exceptions.RequestException:
return False
print(f"ATTEMPTING SIMPLEST XP SYNTAX: {filename}")
def test_worker(interval):
""" Background loop that toggles the display """
# Try ONLY the filename and the format.
# Many XP versions hate the SCR,COL extra parameters via SCPI.
cmd = f':DISK:SAVE:IMAGe "{filename}",PNG'
scope.write(cmd)
# DO NOT use scope.ask() or any queries yet.
# Just sleep and check the folder manually.
time.sleep(5.0)
print("COMMAND SENT. CHECK C:\\TEMP")
except Exception as e:
print(f"XP COMM ERROR: {e}")
def test_worker(on_time):
""" Background loop:
- Sets display ON for user-defined duration.
- Sets display OFF for exactly 1 second.
"""
global test_running
print(f"\n[TEST STARTED] TOGGLING EVERY {interval} SECONDS. USE MENU TO STOP")
count = 1
state = "on"
while test_running:
success = set_display(state)
if not success:
print(f"\n[TEST ERROR] FAILED TO REACH FLASK SERVER... STOPPING TEST...")
test_running = False
break
# Arm scope
scope.write(":SINGle")
# Toggle state for next iteration
state = "off" if state == "on" else "on"
# Start display
requests.put(URL, json={"state": "on"}, timeout=2)
# Sleep in small increments so we can exit the thread quickly
for _ in range(int(interval * 10)):
if not test_running: break
time.sleep(0.1)
# Wait for the scope to trigger and fill memory
# We wait slightly longer than the 'on_time' to ensure capture is done
time.sleep(on_time + 0.5)
# Pull the image
save_screenshot(count)
count += 1
# Set Display OFF
requests.put(URL, json={"state": "off"}, timeout=2)
# Fixed 1s OFF period
time.sleep(1.0)
def main_menu():
global test_running
"""Main Application Loop."""
while True:
print("\n=== MIPI TEST CONTROL ===")
print("\n===== MIPI TEST CONTROL =====")
print("1. RUN IDN CHECK (PSU & SCOPE)")
print("2. CONFIGURE PSU (DEFAULT 24V/1.5A)")
print("3. PSU OUTPUT ON/OFF (CH1)")
print("4. START FLICKER TEST")
print("5. STOP FLICKER TEST")
print("6. EXIT")
print("2. SETUP SCOPE (RUN FIRST)")
print("3. CONFIGURE PSU (DEFAULT 24V/1.5A)")
print("4. PSU OUTPUT ON/OFF (CH1)")
print("5. START TEST & CAPTURE")
print("6. STOP TEST")
print("7. EXIT")
choice = input("\nSELECT OPTION (1-6): ")
choice = input("\nSELECT OPTION (1-7): ")
if choice == '1':
print(f"PSU: {psu.ask('*IDN?')}")
print(f"SCOPE: {scope.ask('*IDN?')}")
elif choice == '2':
setup_scope()
elif choice == '3':
psu.write('CH1:VOLT 24.0')
psu.write('CH1:CURR 1.5')
print("PSU CONFIGURED...")
elif choice == '3':
elif choice == '4':
state = input("TYPE 'ON' OR 'OFF': ").upper()
psu.write(f'OUTP CH1,{state}')
elif choice == '4':
elif choice == '5':
if not test_running:
try:
sec = float(input("ENTER TOGGLE INTERVAL IN SECONDS: "))
sec = float(input("ON DURATION (sec): "))
test_running = True
t = threading.Thread(target=test_worker, args=(sec,), daemon=True)
t.start()
@@ -91,10 +144,10 @@ def main_menu():
print("INVALID TIME ENTERED.")
else:
print("TEST IS ALREADY RUNNING!")
elif choice == '5':
elif choice == '6':
print("STOPPING TEST...")
test_running = False
elif choice == '6':
elif choice == '7':
test_running = False # Ensure thread stops
psu.close()
scope.close()