Updates
This commit is contained in:
@@ -21,6 +21,14 @@ V18_TIMEBASE = 1e-6 # s/div — 1 µs/div = 10 µs total window
|
||||
V18_TRIG_LEVEL = 1.76 # V — falling-edge trigger on supply droop > 40 mV
|
||||
TRIG_TIMEOUT_S = 15.0 # s — wait this long for Rigol to capture after arming
|
||||
|
||||
# CH2 — SN65DSI83 IRQ pin (CMOS output, active HIGH, high-impedance when IRQ_EN=0)
|
||||
# CSR 0xE0.0 IRQ_EN=0 (default): pin is high-impedance → reads ~0 V (no pull on PCB, normal)
|
||||
# IRQ_EN=1, no error: driven LOW (~0 V)
|
||||
# IRQ_EN=1, error asserted: driven HIGH (~1.25 V min per VOH spec)
|
||||
# No pull-up required — CMOS output drives both high and low.
|
||||
INT_V_SCALE = 0.2 # V/div — shows 0–~1.8 V range clearly
|
||||
INT_V_OFFSET = -0.9 # V — centres display on 0.9 V midpoint
|
||||
|
||||
rigol: vxi11.Instrument | None = None
|
||||
|
||||
|
||||
@@ -62,19 +70,27 @@ def is_connected() -> bool:
|
||||
|
||||
def configure():
|
||||
"""
|
||||
Configure Rigol for 1.8 V supply monitoring.
|
||||
Configure Rigol CH1 for 1.8 V supply monitoring and CH2 for SN65DSI83 INTB pin.
|
||||
AUTO trigger sweep: if no droop occurs, scope still captures on timeout
|
||||
so we always get a supply snapshot even when the rail is healthy.
|
||||
"""
|
||||
rigol.write(":STOP")
|
||||
time.sleep(0.2)
|
||||
|
||||
# CH1 — 1.8 V supply rail
|
||||
rigol.write(":CHANnel1:DISPlay 1")
|
||||
rigol.write(":CHANnel2:DISPlay 0")
|
||||
rigol.write(":CHANnel1:COUPling DC")
|
||||
rigol.write(":CHANnel1:PROBe 10")
|
||||
rigol.write(f":CHANnel1:SCALe {V18_SCALE:.3f}")
|
||||
rigol.write(f":CHANnel1:OFFSet {V18_OFFSET:.3f}")
|
||||
|
||||
# CH2 — SN65DSI83 INTB pin (active-low open-drain, external 10 kΩ pull-up to 1.8 V required)
|
||||
rigol.write(":CHANnel2:DISPlay 1")
|
||||
rigol.write(":CHANnel2:COUPling DC")
|
||||
rigol.write(":CHANnel2:PROBe 1") # direct probe, no attenuation
|
||||
rigol.write(f":CHANnel2:SCALe {INT_V_SCALE:.3f}")
|
||||
rigol.write(f":CHANnel2:OFFSet {INT_V_OFFSET:.3f}")
|
||||
|
||||
rigol.write(f":TIMebase:MAIN:SCALe {V18_TIMEBASE:.2E}")
|
||||
rigol.write(":TRIGger:MODE EDGE")
|
||||
rigol.write(":TRIGger:EDGe:SOURce CHANnel1")
|
||||
@@ -85,7 +101,7 @@ def configure():
|
||||
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, "
|
||||
print(f"[RIGOL] Configured: CH1=1.8 V rail, CH2=INTB pin, {int(V18_TIMEBASE*1e6)} µs/div, "
|
||||
f"trigger <{V18_TRIG_LEVEL} V falling (AUTO sweep, running)")
|
||||
|
||||
|
||||
@@ -117,24 +133,21 @@ def wait_captured(timeout_s: float = TRIG_TIMEOUT_S) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def read_waveform_csv(path: Path) -> int:
|
||||
def _read_channel_csv(channel: str, path: Path, stop_first: bool = True) -> int:
|
||||
"""
|
||||
Read Ch1 waveform from Rigol over SCPI and write to CSV.
|
||||
Sends :STOP first to ensure acquisition is complete before reading —
|
||||
this is reliable regardless of trigger/status state.
|
||||
|
||||
Read one Rigol channel waveform over SCPI and write to CSV.
|
||||
stop_first=False skips :STOP when the scope was already stopped by a prior read.
|
||||
Returns the number of samples written, or 0 on error.
|
||||
"""
|
||||
try:
|
||||
rigol.write(":STOP")
|
||||
time.sleep(0.3)
|
||||
|
||||
rigol.write(":WAVeform:SOURce CHANnel1")
|
||||
if stop_first:
|
||||
rigol.write(":STOP")
|
||||
time.sleep(0.3)
|
||||
rigol.write(f":WAVeform:SOURce {channel}")
|
||||
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}")
|
||||
print(f"[RIGOL] {channel} waveform setup error: {e}")
|
||||
return 0
|
||||
|
||||
try:
|
||||
@@ -145,7 +158,7 @@ def read_waveform_csv(path: Path) -> int:
|
||||
x_orig = float(preamble[5])
|
||||
x_ref = float(preamble[6])
|
||||
except Exception as e:
|
||||
print(f"[RIGOL] Preamble error: {e}")
|
||||
print(f"[RIGOL] {channel} preamble error: {e}")
|
||||
return 0
|
||||
|
||||
try:
|
||||
@@ -158,11 +171,11 @@ def read_waveform_csv(path: Path) -> int:
|
||||
|
||||
vals = [float(v) for v in raw.split(",") if v.strip()]
|
||||
except Exception as e:
|
||||
print(f"[RIGOL] Data read error: {e}")
|
||||
print(f"[RIGOL] {channel} data read error: {e}")
|
||||
return 0
|
||||
|
||||
if not vals:
|
||||
print("[RIGOL] No samples parsed — check scope channel and format settings")
|
||||
print(f"[RIGOL] {channel}: no samples parsed — check channel and format settings")
|
||||
return 0
|
||||
|
||||
try:
|
||||
@@ -175,5 +188,18 @@ def read_waveform_csv(path: Path) -> int:
|
||||
writer.writerow([f"{t:.9f}", f"{v:.6f}"])
|
||||
return len(vals)
|
||||
except Exception as e:
|
||||
print(f"[RIGOL] CSV write error: {e}")
|
||||
print(f"[RIGOL] {channel} CSV write error: {e}")
|
||||
return 0
|
||||
|
||||
|
||||
def read_waveform_csv(path: Path) -> int:
|
||||
"""Read CH1 (1.8 V supply) waveform from Rigol and write to CSV."""
|
||||
return _read_channel_csv("CHANnel1", path, stop_first=True)
|
||||
|
||||
|
||||
def read_int_csv(path: Path) -> int:
|
||||
"""
|
||||
Read CH2 (SN65DSI83 INTB pin) waveform from Rigol and write to CSV.
|
||||
Must be called after read_waveform_csv() — scope is already stopped.
|
||||
"""
|
||||
return _read_channel_csv("CHANnel2", path, stop_first=False)
|
||||
|
||||
Reference in New Issue
Block a user