diff --git a/__pycache__/rigol_scope.cpython-312.pyc b/__pycache__/rigol_scope.cpython-312.pyc index 955fce6..83fd44c 100644 Binary files a/__pycache__/rigol_scope.cpython-312.pyc and b/__pycache__/rigol_scope.cpython-312.pyc differ diff --git a/analyze_captures.py b/analyze_captures.py index d688b5a..5f41931 100644 --- a/analyze_captures.py +++ b/analyze_captures.py @@ -208,7 +208,7 @@ def run_analysis(last: int = 10) -> None: client = anthropic.Anthropic() message = client.messages.create( model = CLAUDE_MODEL, - max_tokens = 1024, + max_tokens = 3072, system = SYSTEM_PROMPT, messages = [{"role": "user", "content": prompt}], ) @@ -282,7 +282,7 @@ def main() -> None: client = anthropic.Anthropic() message = client.messages.create( model = CLAUDE_MODEL, - max_tokens = 1024, + max_tokens = 3072, system = SYSTEM_PROMPT, messages = [{"role": "user", "content": prompt}], ) diff --git a/csv_preprocessor.py b/csv_preprocessor.py index 60954d3..77f4242 100644 --- a/csv_preprocessor.py +++ b/csv_preprocessor.py @@ -127,7 +127,11 @@ def _read_csv(path: Path) -> tuple[np.ndarray, np.ndarray]: volts.append(float(row[1])) except ValueError: pass # skip any header row - return np.array(times, dtype=np.float64), np.array(volts, dtype=np.float64) + t = np.array(times, dtype=np.float64) + v = np.array(volts, dtype=np.float64) + if len(t) < 2: + raise ValueError(f"Insufficient samples in {path.name} ({len(t)} rows parsed)") + return t, v def _zero_crossings(times: np.ndarray, volts: np.ndarray) -> np.ndarray: diff --git a/mipi_test.py b/mipi_test.py index 892f041..e3eea55 100644 --- a/mipi_test.py +++ b/mipi_test.py @@ -322,19 +322,18 @@ def dual_capture(iteration): else: print(" SKIPPING PASS 3 SAVE.") - # Collect Rigol 1.8 V waveform (Agilent save takes ~5 s, Rigol should be done) + # Collect Rigol 1.8 V waveform. + # The Agilent LP acquire + save takes ~35 s, so the Rigol will have + # long since auto-captured by now. read_waveform_csv() sends :STOP + # before reading to guarantee the acquisition is finalised. if rigol_scope.is_connected(): - print(" PASS 3: WAITING FOR RIGOL 1.8 V CAPTURE...") - if rigol_scope.wait_captured(timeout_s=10.0): - DATA_DIR.mkdir(exist_ok=True) - v18_path = DATA_DIR / f"{ts}_pwr_{iteration:04d}_1v8.csv" - n = rigol_scope.read_waveform_csv(v18_path) - if n: - print(f" SAVED: {v18_path.name} ({n} samples)") - else: - print(" RIGOL: Waveform read returned 0 samples.") + DATA_DIR.mkdir(exist_ok=True) + v18_path = DATA_DIR / f"{ts}_pwr_{iteration:04d}_1v8.csv" + n = rigol_scope.read_waveform_csv(v18_path) + if n: + print(f" SAVED: {v18_path.name} ({n} samples)") else: - print(" RIGOL: Timed out waiting for capture.") + print(" RIGOL: Waveform read failed — check connection and probe.") _restore_hs_config() diff --git a/rigol_scope.py b/rigol_scope.py index 3e02649..313fb44 100644 --- a/rigol_scope.py +++ b/rigol_scope.py @@ -72,7 +72,7 @@ def configure(): rigol.write(":CHANnel1:DISPlay 1") rigol.write(":CHANnel2:DISPlay 0") rigol.write(":CHANnel1:COUPling DC") - rigol.write(":CHANnel1:PROBe 1") + rigol.write(":CHANnel1:PROBe 10") rigol.write(f":CHANnel1:SCALe {V18_SCALE:.3f}") rigol.write(f":CHANnel1:OFFSet {V18_OFFSET:.3f}") rigol.write(f":TIMebase:MAIN:SCALe {V18_TIMEBASE:.2E}") @@ -82,9 +82,11 @@ def configure(): rigol.write(f":TRIGger:EDGe:LEVel {V18_TRIG_LEVEL:.3f}") rigol.write(":TRIGger:SWEep AUTO") # auto: captures even without a droop trigger time.sleep(0.3) + rigol.write(":RUN") # start acquiring immediately after configure + time.sleep(0.2) print(f"[RIGOL] Configured: 1.8 V rail, {int(V18_TIMEBASE*1e6)} µs/div, " - f"trigger <{V18_TRIG_LEVEL} V falling (AUTO sweep)") + f"trigger <{V18_TRIG_LEVEL} V falling (AUTO sweep, running)") # --------------------------------------------------------------------------- @@ -92,8 +94,9 @@ def configure(): # --------------------------------------------------------------------------- def arm(): - """Arm for a single acquisition. Non-blocking — returns immediately.""" - rigol.write(":SINGle") + """Ensure scope is running so it is actively acquiring when the LP event occurs. + The waveform is frozen with :STOP inside read_waveform_csv() at collection time.""" + rigol.write(":RUN") def wait_captured(timeout_s: float = TRIG_TIMEOUT_S) -> bool: @@ -117,32 +120,52 @@ def wait_captured(timeout_s: float = TRIG_TIMEOUT_S) -> bool: def read_waveform_csv(path: Path) -> int: """ Read Ch1 waveform from Rigol over SCPI and write to CSV. - The Rigol returns ASCII voltage values; we reconstruct the time axis - from the waveform preamble. + Sends :STOP first to ensure acquisition is complete before reading — + this is reliable regardless of trigger/status state. Returns the number of samples written, or 0 on error. """ try: - rigol.write(":WAVeform:SOURce CHANnel1") - rigol.write(":WAVeform:FORMat ASCII") - rigol.write(":WAVeform:MODE NORMal") + rigol.write(":STOP") + time.sleep(0.3) + rigol.write(":WAVeform:SOURce CHANnel1") + rigol.write(":WAVeform:FORMat ASC") # Rigol DS1000Z uses ASC not ASCII + time.sleep(0.1) + + except Exception as e: + print(f"[RIGOL] Waveform setup error: {e}") + return 0 + + try: preamble = rigol.ask(":WAVeform:PREamble?").strip().split(",") # [0]=fmt [1]=type [2]=points [3]=count [4]=x_incr [5]=x_orig [6]=x_ref # [7]=y_incr [8]=y_orig [9]=y_ref x_incr = float(preamble[4]) x_orig = float(preamble[5]) x_ref = float(preamble[6]) + except Exception as e: + print(f"[RIGOL] Preamble error: {e}") + return 0 + try: raw = rigol.ask(":WAVeform:DATA?").strip() - # Strip any TMC binary header (#) if present + # Strip TMC binary header (#...) if present if raw.startswith("#"): n_digits = int(raw[1]) raw = raw[2 + n_digits:] vals = [float(v) for v in raw.split(",") if v.strip()] + except Exception as e: + print(f"[RIGOL] Data read error: {e}") + return 0 + if not vals: + print("[RIGOL] No samples parsed — check scope channel and format settings") + return 0 + + try: path.parent.mkdir(exist_ok=True) with open(path, "w", newline="") as f: writer = csv.writer(f) @@ -150,9 +173,7 @@ def read_waveform_csv(path: Path) -> int: for i, v in enumerate(vals): t = x_orig + (i - x_ref) * x_incr writer.writerow([f"{t:.9f}", f"{v:.6f}"]) - return len(vals) - except Exception as e: - print(f"[RIGOL] Waveform read error: {e}") + print(f"[RIGOL] CSV write error: {e}") return 0