Skip to main content
Drive an oscilloscope from a cargo test: set up its channels, timebase and trigger, control acquisition, and read measurements. It works with Rigol MSO5000 and PicoScope nets, and requires box software 0.55.0 or later.

Handle

A scope is saved on the box as two kinds of net:
  • one scope net for the instrument
  • one scope-channel net for each input
lager.scope(name) takes either kind. Channel settings and measurements need a channel net. Everything else belongs to the instrument, and works through either kind.

Methods

Types

Measurement

Voltages are in volts, times in seconds, frequency in hertz, and duty cycle and overshoot in percent.

EdgeTrigger

TriggerSettings and Measurements

trigger() returns a TriggerSettings with mode, source, slope, level, and holdoff when the scope reports one. Each field is an Option, in the instrument’s own spelling. measure_all() returns a Measurements with one Option<f64> field for each quantity. Measurements::get(Measurement) reads one of them.

ScopeCapture

capture() and ScopeStream::next_capture() return one capture: volts() and counts() return None for a channel that is not in the capture.

Method Reference

measure(m: Measurement) -> Result<Option<f64>>

Read one quantity from the channel.
Returns: None when the capture does not contain the quantity. For example, a DC level has no period. This is an answer, not an error.

measure_all() -> Result<Measurements>

Read every quantity the capture supports. Each measure() call takes its own capture, so values from separate calls can come from different moments of a live signal. measure_all() reads them all from one capture, so they agree with each other.

trigger_edge(trigger: &EdgeTrigger) -> Result<()>

Configure the edge trigger. The box applies only the fields that are set. So level alone moves the level, and leaves the source and slope as they are.
TriggerMode::Single arms the scope for one acquisition, as on a bench scope. The box refuses a call with no field set.

capture() -> Result<ScopeCapture>

Fetch the scope’s latest capture. If it has none, it takes one now, so start the scope first with run() or single(). Needs the scope-trace feature:
capture_timeout(timeout) waits for the time you give it. Without a capture by then, it fails with Error::Timeout.

stream() -> Result<ScopeStream>

Subscribe to every capture from now on. A slow reader gets the newest capture rather than a backlog, so it sees a lower frame rate. Read with next_capture(timeout: Duration), and end with close(). Dropping the stream also closes it.

command(action: &str, params: Value) -> Result<Value>

Run a scope action that has no typed method, and return its value.

Examples

Measure a clock

Supported Hardware

Notes

  • A channel action on the instrument net fails. Send set_scale() or measure() to the scope net, and the box answers Error::Box with HTTP 400. The message names the channel nets to use instead.
  • A box older than 0.55.0 answers HTTP 501 for scope nets, which the crate returns as Error::UnsupportedByBox.
  • Each call allows 45 s. The box limits one scope command to 30 s, so the box’s own timeout error arrives before the crate stops waiting.
  • Trace capture needs a scope that streams. capture() and stream() use the WebSocket behind the box’s /scope page. They work on PicoScope nets, and on Rigol MSO5000 nets with an HDMI capture card paired (box software 0.57.0 or later). On a Rigol with no capture card, the box refuses the request, which gives Error::Box.
  • capture() and stream() are on the blocking client only, and need a plain http:// box URL.
  • Logic-analyzer nets have no Rust handle, because the box has no logic role on /net/command. The work list is in MISSING_ENDPOINTS.md.
  • AsyncScope from AsyncLagerBox::scope provides the same methods, .awaited.