Overview
Use the scope module to control oscilloscopes for analog signal capture, triggering on specific events, and automated measurements.Instrument support
The same object and the same calls work for a Rigol MSO5000 and for a PicoScope (2000, 2000a, 3000a, 4000a or 5000a). The difference is underneath. The Rigol speaks SCPI over VISA. A PicoScope is a USB device with a vendor SDK, and the oscilloscope daemon on the box drives it. Know these differences before you write a script for a PicoScope:- Measurements are computed, not queried. No PicoTech API has an equivalent
of
:MEAS:VPP?, so the box computes the value from a captured block. One capture yields the whole set, soscope.measurement.all()costs the same as a singlevoltage_peak_to_peak()and reading five values individually costs five captures. - While running, they describe the capture last streamed out. The box computes a measurement or a cursor reading from the block it last sent to subscribers. The numbers therefore agree with the trace on screen. Repeated reads change only as fast as captures arrive: two calls between captures return the same value. Stopped, they describe the last capture, as a stopped bench scope does.
displayandmeasurement_cursordo nothing. They put a reading on the instrument’s own screen, and a PicoScope has none. They are accepted and ignored so a script written for a Rigol still runs.- Some features raise instead of returning. On-screen cursors, protocol
triggers, the logic analyzer, and the measurements listed as Rigol-only below raise
UnsupportedScopeFeaturenaming the gap, rather than returning a plausible-looking zero. Catch it if a script needs to run against both.
Import
Usage
Methods
Channel Control
enable()
Enable the oscilloscope channel.
disable()
Disable the oscilloscope channel.
Capture Control
start_capture()
Start continuous waveform capture.
start_single_capture()
Start single-shot capture (captures one triggered event).
stop_capture()
Stop waveform capture.
force_trigger()
Trigger now rather than waiting for the configured condition. Use it when a
signal does not cross the trigger level and the script needs a capture anyway.
The scope must be running: a stopped PicoScope refuses it.
Measurements
Access comprehensive measurements through themeasurement attribute.
Availability
Everything below works on a Rigol. On a PicoScope the box computes measurements from the captured samples, and these fourteen are the ones it computes:
All other measurements are Rigol only, and raise
UnsupportedScopeFeature
on a PicoScope. These are the flat-top and threshold voltages, preshoot, period
RMS, time-at-extreme, slew rates, edge and pulse counts, area and variance. The
delay and phase measurements are Rigol only too, because they compare two
channels. The box has no command for that on a PicoScope.
period, frequency, the pulse widths, the duty cycles, the rise and fall
times and overshoot need a resolvable waveform. On a PicoScope, a period needs
two full cycles in the capture. With fewer, the call raises rather than return
an imprecise guess. Put at least two cycles on screen before you measure timing.
all()
Every measurement the box computes, from a single capture. On a PicoScope this
is the cheap way to read more than one value.
Voltage Measurements
Timing Measurements
Counting Measurements
Area Measurements
Statistical Measurements
Delay and Phase Measurements
Measurement Options
Most measurements accept optional parameters:Streaming (PicoScope)
For PicoScope devices, streaming capabilities are available:stream_start(channel, volts_per_div, time_per_div, trigger_level, trigger_slope, capture_mode, coupling)
Start streaming acquisition.
Parameters:
channel(str): Channel to enable -"A","B","1","2"volts_per_div(float): Vertical scaletime_per_div(float): Horizontal scale in secondstrigger_level(float): Trigger level in voltstrigger_slope(str):"rising","falling","either"capture_mode(str):"auto","normal","single"coupling(str):"dc","ac"
"gnd" is accepted by the API but refused by 2000-series units, which have no
ground switch: ps2000_set_channel carries a single flag for coupling. Use
"ac" to block the DC component, or unplug the probe to see where zero sits.stream_stop()
Stop streaming acquisition.
stream_capture(output, duration, samples)
Capture for duration seconds, writing a CSV.
Parameters:
output(str): Output file path. Omit it to count samples without writing a fileduration(float): Capture duration in secondssamples(int): Cap on rows per channel (optional). A cap, not a target: the capture still stops atduration
captures,
samples_per_channel, rows and output. The CSV columns are capture,
channel, sample_index, time_ns and voltage, the same layout
lager scope stream capture writes.
Each capture the scope takes in that time is recorded once. The scope must be
running already, from stream_start(), start_capture() or
start_single_capture(). A stopped scope raises at once, rather than after
duration with nothing recorded. A relative output path is relative to the
script’s working directory on the box.
stream_frames(count, timeout)
Yield captures as decoded frames instead of writing a file. This is the
zero-copy path: a frame’s counts() is a view over the received buffer, so
nothing is converted until asked for. Use it when the samples go into numpy
rather than onto disk.
Each frame is a new capture, never one it yielded before. When no capture
arrives within timeout, it raises ScopeDaemonTimeout. Start the scope first,
and in normal mode make sure the signal crosses the trigger level.
Parameters:
count(int): Number of captures to yield (default 1)timeout(float): Seconds to wait for each capture (default 10)
volts() gives the voltage at the probe tip. With a 10x probe it reports the
signal at the tip, not the tenth of it that reaches the BNC. volts_per_div,
the trigger level and the measurement functions are also at the tip. Set the
ratio with set_channel_probe() before you capture. A 2000-series unit starts
at 10x, and the 2000a, 3000a, 4000a and 5000a families start at 1x.Complete Example
Trace Settings
Configure vertical and horizontal scale throughtrace_settings:
Time/div is one tenth of the capture, as on a ten-division screen, so
set_time_per_div(0.001) asks for a 10 ms window.get_time_per_div() returns the scale in use, which is rarely the one asked
for. A scope samples at a fixed ladder of intervals, each twice the last. The
box rounds a request to the closest one: 1 ms/div on a 2204A is really
1.024 ms/div. Read it back if you need the exact window. Better still, use
get_sample_rate() and the frame’s own time axis, not arithmetic on the value
you set.The fastest screen a unit can reach depends on the block depth and the maximum
sample rate, because the two multiply out to the window. A 2204A at
100 MS/s over 8000 samples bottoms out at 8 us/div, and asking for anything
faster gets you that. Enabling a second channel halves the buffer, which makes
the fastest screen faster rather than slower.set_time_offset() moves the capture window in time relative to the trigger.
Use it to look at signal past the left or right edge of one capture. Positive
values look forward, at signal later than the trigger; negative values look
back before it.On a PicoScope the travel is one window each way. The window is a block, and a
block is all the scope holds. So the box clamps the offset where the capture is
entirely before or entirely after the trigger. Setting it re-arms the scope,
because a window somewhere else must be captured to be seen. The offset then
applies to every capture until you change it.Advanced Trigger Settings
Access advanced trigger configuration throughtrigger_settings:
Cursor Control
Access cursor functions through thecursor attribute.
scope.cursor.* is Rigol only. These are markers on the instrument’s own
display, positioned in screen coordinates and read back over SCPI. A PicoScope
has no display, so every method here raises UnsupportedScopeFeature on one.Cursors over the captured samples are a different thing, and a PicoScope has
them. You place them with a time and a voltage, not a pixel, so they have
their own API. Use
lager scope <net> cursor time <t1> <t2>, the same cursor verb in the web
UI’s console, or set_cursors() / measure_cursors() on the driver:Supported Hardware
The box detects an attached PicoScope’s channel count, voltage ranges,
bandwidth, memory depth and ADC resolution at runtime. Models within a series
therefore work without configuration. Read them with
scope.capabilities().
Notes
- Use
NetType.Analogfor oscilloscope channels (1-4) - Use
NetType.Logicfor digital channels (D0-D15) on MSO scopes - Streaming features are only available on PicoScope devices
- Configure trigger before starting capture for reliable measurements
- Measurement methods return
floaton success, orNoneif the measurement is invalid (e.g., no signal, no trigger, wrong channel). On Rigol hardware, the instrument returns 9.9E+37 for invalid measurements, which is automatically converted toNone. - For protocol triggering (UART, I2C, SPI, CAN), see the Logic Analyzer documentation

