diff --git a/mipi_test.py b/mipi_test.py index 2e1c6c2..28980e5 100644 --- a/mipi_test.py +++ b/mipi_test.py @@ -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 """ - try: - r = requests.put(url, json={"state": state}, timeout=2) - return r.status_code == 200 +def setup_scope(): + """Initializes DSO80204B for 210MHz MIPI Signals""" + print("Configuring Scope...") + scope.write("*RST") + time.sleep(1) - except requests.exceptions.RequestException: - return False - -def test_worker(interval): - """ Background loop that toggles the display """ - global test_running - print(f"\n[TEST STARTED] TOGGLING EVERY {interval} SECONDS. USE MENU TO STOP") - - 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 - - # Toggle state for next iteration - state = "off" if state == "on" else "on" + # 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: + scope.clear() + # Use a very short, simple path. No subdirectories if possible. + # Ensure C:\TEMP exists! + filename = f"C:\\TEMP\\cap{iteration}.png" - # 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) + print(f"ATTEMPTING SIMPLEST XP SYNTAX: {filename}") + + # 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 + count = 1 + + while test_running: + # Arm scope + scope.write(":SINGle") + + # Start display + requests.put(URL, json={"state": "on"}, timeout=2) + + # 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()