Skip logging during auto-range transitions to avoid settling artifacts
When voltage or current range changes, waits 3 measurement cycles before resuming CSV/graph logging. Settling readings are printed to console but not recorded, preventing transient values from corrupting test data. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -62,6 +62,21 @@ def cmd_measure(meter: Hioki3193, args: argparse.Namespace) -> None:
|
|||||||
print(f" {name:>8s} = {value:+.6E}")
|
print(f" {name:>8s} = {value:+.6E}")
|
||||||
|
|
||||||
|
|
||||||
|
SETTLE_CYCLES = 3 # Number of cycles to skip after a range change
|
||||||
|
|
||||||
|
|
||||||
|
def _read_ranges(
|
||||||
|
meter: Hioki3193,
|
||||||
|
voltage_channels: list[int],
|
||||||
|
current_channels: list[int],
|
||||||
|
) -> list[str]:
|
||||||
|
"""Read current voltage and current ranges for the given channels."""
|
||||||
|
return (
|
||||||
|
[meter.get_voltage_range(ch) for ch in voltage_channels]
|
||||||
|
+ [meter.get_current_range(ch) for ch in current_channels]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def cmd_monitor(meter: Hioki3193, args: argparse.Namespace) -> None:
|
def cmd_monitor(meter: Hioki3193, args: argparse.Namespace) -> None:
|
||||||
"""Continuously monitor measurements at an interval."""
|
"""Continuously monitor measurements at an interval."""
|
||||||
items = args.items if args.items else ["U5", "I5", "P5", "U6", "I6", "P6", "EFF1"]
|
items = args.items if args.items else ["U5", "I5", "P5", "U6", "I6", "P6", "EFF1"]
|
||||||
@@ -86,19 +101,37 @@ def cmd_monitor(meter: Hioki3193, args: argparse.Namespace) -> None:
|
|||||||
print(f"{'Time':>10s} {header}")
|
print(f"{'Time':>10s} {header}")
|
||||||
print("-" * (12 + 14 * len(items)))
|
print("-" * (12 + 14 * len(items)))
|
||||||
|
|
||||||
|
# Range settle tracking
|
||||||
|
prev_ranges = _read_ranges(meter, voltage_channels, current_channels)
|
||||||
|
settle_remaining = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
count = 0
|
count = 0
|
||||||
while args.count == 0 or count < args.count:
|
while args.count == 0 or count < args.count:
|
||||||
result = meter.measure(*items)
|
result = meter.measure(*items)
|
||||||
|
ranges = _read_ranges(meter, voltage_channels, current_channels)
|
||||||
|
|
||||||
|
# Detect range change
|
||||||
|
if ranges != prev_ranges:
|
||||||
|
settle_remaining = SETTLE_CYCLES
|
||||||
|
range_desc = ", ".join(
|
||||||
|
f"{a}->{b}" for a, b in zip(prev_ranges, ranges) if a != b
|
||||||
|
)
|
||||||
|
print(f" ** Range changed ({range_desc}), settling {SETTLE_CYCLES} cycles...")
|
||||||
|
prev_ranges = ranges
|
||||||
|
|
||||||
ts = time.strftime("%H:%M:%S")
|
ts = time.strftime("%H:%M:%S")
|
||||||
vals = " ".join(f"{v:>+12.4E}" for v in result.values.values())
|
vals = " ".join(f"{v:>+12.4E}" for v in result.values.values())
|
||||||
|
|
||||||
|
if settle_remaining > 0:
|
||||||
|
print(f"{ts:>10s} {vals} [settling {settle_remaining}]")
|
||||||
|
settle_remaining -= 1
|
||||||
|
time.sleep(interval)
|
||||||
|
continue
|
||||||
|
|
||||||
print(f"{ts:>10s} {vals}")
|
print(f"{ts:>10s} {vals}")
|
||||||
|
|
||||||
if writer:
|
if writer:
|
||||||
ranges = (
|
|
||||||
[meter.get_voltage_range(ch) for ch in voltage_channels]
|
|
||||||
+ [meter.get_current_range(ch) for ch in current_channels]
|
|
||||||
)
|
|
||||||
writer.writerow(
|
writer.writerow(
|
||||||
[time.strftime("%Y-%m-%d %H:%M:%S")]
|
[time.strftime("%Y-%m-%d %H:%M:%S")]
|
||||||
+ [f"{v:.6E}" for v in result.values.values()]
|
+ [f"{v:.6E}" for v in result.values.values()]
|
||||||
@@ -287,6 +320,9 @@ def cmd_live(meter: Hioki3193, args: argparse.Namespace) -> None:
|
|||||||
# Error threshold - values above this are instrument error codes
|
# Error threshold - values above this are instrument error codes
|
||||||
ERROR_THRESHOLD = 1e90
|
ERROR_THRESHOLD = 1e90
|
||||||
|
|
||||||
|
# Range settle tracking (lists for mutability in closure)
|
||||||
|
settle_state = {"prev": _read_ranges(meter, voltage_channels, current_channels), "remaining": 0}
|
||||||
|
|
||||||
def update(_frame):
|
def update(_frame):
|
||||||
try:
|
try:
|
||||||
result = meter.measure(*items)
|
result = meter.measure(*items)
|
||||||
@@ -294,20 +330,31 @@ def cmd_live(meter: Hioki3193, args: argparse.Namespace) -> None:
|
|||||||
print(f"Read error: {e}")
|
print(f"Read error: {e}")
|
||||||
return list(lines.values())
|
return list(lines.values())
|
||||||
|
|
||||||
now = time.time() - t0
|
ranges = _read_ranges(meter, voltage_channels, current_channels)
|
||||||
timestamps.append(now)
|
|
||||||
|
|
||||||
# Print to console
|
# Detect range change
|
||||||
|
if ranges != settle_state["prev"]:
|
||||||
|
settle_state["remaining"] = SETTLE_CYCLES
|
||||||
|
range_desc = ", ".join(
|
||||||
|
f"{a}->{b}" for a, b in zip(settle_state["prev"], ranges) if a != b
|
||||||
|
)
|
||||||
|
print(f" ** Range changed ({range_desc}), settling {SETTLE_CYCLES} cycles...")
|
||||||
|
settle_state["prev"] = ranges
|
||||||
|
|
||||||
|
now = time.time() - t0
|
||||||
ts = time.strftime("%H:%M:%S")
|
ts = time.strftime("%H:%M:%S")
|
||||||
vals = " ".join(f"{v:>+12.4E}" for v in result.values.values())
|
vals = " ".join(f"{v:>+12.4E}" for v in result.values.values())
|
||||||
|
|
||||||
|
if settle_state["remaining"] > 0:
|
||||||
|
print(f"{ts} {vals} [settling {settle_state['remaining']}]")
|
||||||
|
settle_state["remaining"] -= 1
|
||||||
|
return list(lines.values())
|
||||||
|
|
||||||
|
timestamps.append(now)
|
||||||
print(f"{ts} {vals}")
|
print(f"{ts} {vals}")
|
||||||
|
|
||||||
# CSV logging
|
# CSV logging
|
||||||
if writer:
|
if writer:
|
||||||
ranges = (
|
|
||||||
[meter.get_voltage_range(ch) for ch in voltage_channels]
|
|
||||||
+ [meter.get_current_range(ch) for ch in current_channels]
|
|
||||||
)
|
|
||||||
writer.writerow(
|
writer.writerow(
|
||||||
[time.strftime("%Y-%m-%d %H:%M:%S")]
|
[time.strftime("%Y-%m-%d %H:%M:%S")]
|
||||||
+ [f"{v:.6E}" for v in result.values.values()]
|
+ [f"{v:.6E}" for v in result.values.values()]
|
||||||
|
|||||||
Reference in New Issue
Block a user