Skip to main content
Control oscilloscope nets through the Lager CLI for waveform capture, triggering, measurements, and streaming.
Known limitations on the Rigol MSO5000. The edge and SPI triggers work. The pulse, UART and I2C triggers fail on the Rigol MSO5000. The CAN trigger and every bus decoder in the Python API also fail. A failed command prints the error and exits 1. Issue #418 tracks this work.

Syntax

With no command, lager scope lists the scope and scope-channel nets on the box. A command without NET_NAME uses the default scope net. Set the default with lager defaults add --scope-net NET_NAME.

The scope and its channels

An oscilloscope is two kinds of net. A scope net is the instrument itself. A scope-channel net is one of its inputs, one net for each channel. For a two-channel PicoScope, lager nets tui offers three nets: the two channels and the scope that they belong to. The split follows the hardware. Six settings belong to a channel, and the rest belong to the instrument: You address both kinds of net in the same way:
An instrument command also works on one of its channel nets. A channel names exactly one scope, so the command is not ambiguous. Scripts from before scope nets keep working unchanged.The reverse does not work. lager scope picoscope1 coupling ac names no channel, and the box does not guess one. The error names the channel nets to use instead.
Boxes from before scope nets had only channel nets, saved with the role scope. The box converts them the first time that it reads its nets. Each one becomes a scope-channel net with the same name and pin. A scope net named after the model, such as picoscope1, appears next to them. An old scope net with no pin stays a scope net and stands for the instrument. You do not need to add anything again, and you can rename the new net.

Global Options

Every command also accepts --box. The channel, capture-control, autoscale, measure and cursor commands also accept --mcu MCU, and so do the trigger types other than holdoff. No lager scope command uses its value.

Commands

The edge trigger works on PicoScope and Rigol. The pulse trigger and the protocol triggers (I2C, SPI, UART) are Rigol only. trigger holdoff is PicoScope only.
Measurements work on both instruments, but each one computes them in a different way. A Rigol answers a SCPI query about the trace that it shows. For a PicoScope, the daemon computes the value from a captured block, because no PicoTech API has an equivalent of :MEAS:VPP?. So --display and --cursor are Rigol only. They put the reading on the screen of the instrument, and a PicoScope has no screen.While a PicoScope acquires, measurements and cursor readings use the capture that the daemon streamed out last. So they describe the trace in the web UI, not a different capture a moment later. After a stop, they describe the last capture, as the readouts on a stopped bench scope do.

Validation Ranges

The CLI checks these values before it sends a command to the oscilloscope:

Supported Hardware

The daemon reads the channel count, voltage ranges, bandwidth, memory depth and ADC resolution from the attached PicoScope. It does not assume them from the series. Type capabilities in the console of the web UI to see what the daemon found. When you add nets, lager nets tui reads the channel count from the model number. It offers two channel nets for a 2-channel model and four for a 4-channel model. The 8-channel 4824A also gets four, channels A to D, because Lager names no channel after D. A model number that it cannot read gets two.

Feature Comparison


Basic Control Commands

enable

Enable the channel of a scope-channel net.

disable

Disable the channel of a scope-channel net.

start

Start waveform capture. Without --single, the scope captures continuously in the trigger mode that is set.
Options:
  • --single - Arm one capture, then stop (one-shot mode)
A PicoScope in single mode changes to auto when start runs without --single. A single-shot stops after one capture, so it cannot run continuously.

stop

Stop waveform capture.

force

Trigger now, without the trigger condition. Use it when the signal does not meet the trigger condition.

status

Show every scope setting in one reply: the channels, the timebase, the trigger and the acquisition. PicoScope only.
The reply comes from the settings that the daemon published last. The web UI draws its controls from the same state.

autoscale

Automatically adjust the vertical scale and the horizontal timebase (Rigol only). The command can take 10 to 15 seconds.
A PicoScope refuses autoscale, because its SDKs have no autoset. Set scale and timebase yourself.

Channel Configuration

coupling

Set the input coupling mode of the channel.
Arguments:
  • MODE - Coupling mode: dc, ac, or gnd
A PicoScope refuses gnd, because no PicoScope series has a ground switch. Use ac to block the DC component, or disable the channel.

probe

Set the probe attenuation ratio for accurate voltage measurements.
Arguments:
  • RATIO - Probe attenuation: 1, 10, 100, or 1000
A 2000-series PicoScope (2204A, 2205A) starts at 10x. The 2000a, 3000a, 4000a and 5000a series start at 1x. Set the ratio to match your probe.

scale

Set the vertical scale (volts per division) of the channel.
Arguments:
  • VOLTS_PER_DIV - Vertical scale in volts per division (0.001 to 100.0)

timebase

Set the horizontal timebase (seconds per division) of the oscilloscope.
Arguments:
  • SECONDS_PER_DIV - Horizontal timebase in seconds per division (1e-9 to 50.0)
The range above is what the command accepts, not what a given unit can do. A scope samples at a fixed set of intervals, so it rounds the request to the nearest one. The fastest timebase also depends on the block depth, not only on the sample rate. For example, a 2204A at 100 MS/s over 8000 samples stops at 8 us/div. On a PicoScope, status reports the timebase in use, not the one that you asked for.

Measure Subcommands

Measure waveform characteristics on either instrument. A Rigol returns a reading that it computes itself. For a PicoScope, the box captures a block and the daemon computes the value from the samples. You do not need streaming or a CSV export. Each PicoScope measurement asks for its own capture, so several values cost several captures. To read the whole set from one capture, use measurement.all() in the Python API. Common Options for all measure commands:

Time Measurements

measure period

Measure waveform period.

measure freq

Measure waveform frequency.

measure pulse-width-pos

Measure positive pulse width.

measure pulse-width-neg

Measure negative pulse width.

measure duty-cycle-pos

Measure positive duty cycle (percentage of time signal is high).

measure duty-cycle-neg

Measure negative duty cycle (percentage of time signal is low).

Voltage Measurements

measure vpp

Measure peak-to-peak voltage.

measure vmax

Measure maximum voltage.

measure vmin

Measure minimum voltage.

measure vavg

Measure average voltage.

measure vrms

Measure RMS (root mean square) voltage.

Trigger Subcommands

Show or set the trigger. The edge trigger works on PicoScope and Rigol. The protocol triggers (I2C, SPI, UART) and the pulse trigger are Rigol only.

trigger

With no subcommand, trigger shows the mode, source, slope and level of the trigger. On a PicoScope, it also shows the holdoff if one is set.
Options for pulse, i2c, spi and uart: These four commands apply --mode and --coupling every time. So a call without them sets normal and dc. trigger edge has no defaults, and it changes only the settings that you give.
--coupling is the filter in front of the trigger comparator, not the input coupling of the channel. The two settings share a word, but they do different things. The trigger filter lets the scope trigger on a noisy or drifting edge, and the trace does not change. lager scope <net> coupling changes what the channel passes, and the trace moves. Only a Rigol has the trigger filter. A PicoScope refuses the flag, and it does not apply it to the input instead.
--mode sets how a running scope triggers. In auto, the scope triggers itself if no edge crosses the level, so the trace always moves. In normal, the screen updates only on a real trigger, which holds a repetitive waveform still.On a PicoScope, --mode single also arms one capture, the same as lager scope <net> start --single. A single-shot cannot run continuously. So start without --single changes single to auto. In the other modes, start keeps the mode that you set.

trigger edge

Set the edge trigger. It works on PicoScope and Rigol.
Options: Every option is optional, and an option that you do not give keeps its value. On a PicoScope, give at least one option. With none, the command prints an error and exits 1. On a PicoScope, --source takes a channel letter (A to D), a channel number (1 to 4), or the name of a scope-channel net. On a Rigol, --source takes the name of a scope-channel net. Examples:

trigger holdoff

Ignore triggers for SECONDS after each trigger, from 0 to 10. With no value, the command shows the holdoff. PicoScope only.
A holdoff steadies the trace of a signal with several edges that cross the level, such as a burst or a serial byte. The scope waits for the rest of one burst before it triggers on the next.

trigger pulse

Set pulse width trigger (Rigol only). The scope triggers when a pulse width meets the conditions. On the Rigol MSO5000, this trigger does not work yet. See the limitations at the top of this page.
Options (in addition to the options above): Trigger-on Conditions: The condition does not select a polarity yet: each positive value and its negative counterpart set the same width condition. Without the width it needs, the command changes no width condition and prints a note.

trigger i2c

Set I2C protocol trigger (Rigol only). The scope triggers on I2C bus events. On the Rigol MSO5000, this command does not work yet. See the limitations at the top of this page.
Options (in addition to --mode and --coupling): Trigger-on Conditions:

trigger spi

Set SPI protocol trigger (Rigol only). The scope triggers on SPI bus events.
Options (in addition to --mode and --coupling): Examples:

trigger uart

Set UART protocol trigger (Rigol only). The scope triggers on UART serial events. On the Rigol MSO5000, this command does not work yet. See the limitations at the top of this page.
Options (in addition to the options above):

Acquisition and Display

These commands are PicoScope only. A Rigol does the same work on its front panel, and the box refuses them for a Rigol net.

acquire

Set how consecutive captures combine. With no mode, the command shows the current mode.
--count needs a mode. With --count and no mode, the command prints an error.

roll

Set roll mode, which streams slow timebases continuously. With no mode, the command shows the current mode.

fft

Report the strongest frequency components of a channel. The box computes the spectrum from the capture on screen. Amplitudes are RMS volts at the probe tip, in dBV.
On a scope net, give --channel, because the instrument has no channel of its own. Use hann for general work and flattop when the amplitude of a tone is important. Use rectangular for a signal that fits the capture exactly.

display

Set how the web UI draws the trace. With no subcommand, display shows the current settings. The box holds them, so an open page follows a change from the CLI.

Cursor Subcommands

Two different sets of commands share this name. cursor time, cursor volts and cursor off place cursors over the captured samples of a PicoScope. You type them, because there is no knob for them and no handle on the plot. The box holds the pair, so the web UI draws a cursor that you place from the terminal. The console of the web UI accepts the same cursor commands. cursor set-a, set-b, move-a, move-b and hide move markers on the front display of a Rigol in screen coordinates, over SCPI. A PicoScope has no display for them.

cursor

With no subcommand, cursor reads the cursors that are set. PicoScope only.

cursor time

Place the two time cursors, in seconds from the trigger. A negative time is before the trigger, and half of a capture is there.
The reply gives the interval between the cursors, its reciprocal as a frequency, and the voltage of the trace under each cursor. So a pair one cycle apart shows the frequency directly. The box interpolates the voltages between samples, because a cursor stays where you put it, not on the sample grid.

cursor volts

Place the two voltage cursors, in volts at the probe tip.
The reply gives the difference. This pair needs no capture, so the reply comes without a wait for a trigger.

cursor off

Clear both pairs, and stop the web UI from drawing them.
Examples:
The pairs are independent. When you place time cursors, the voltage cursors stay where they are. You place each pair as a pair, because one cursor alone reads nothing. The quantity that you want is the difference between two cursors.A cursor outside the captured window reports no voltage. The nearest sample comes from a different moment, so the box does not use it. The reply names the window, so the cause is clear.

cursor set-a / cursor set-b

Rigol only. Set the absolute position of cursor A or B.
Options:

cursor move-a / cursor move-b

Rigol only. Move a display cursor by a relative offset from its current position.
Options:

cursor hide

Rigol only. Hide the display cursors of the instrument.
Examples:

Stream Subcommands (PicoScope)

Stream oscilloscope data in real time from a PicoScope. A daemon on the Lager Box owns the PicoScope, and a web page on the box shows the trace.

Daemon Architecture

Everything reaches the scope through the box HTTP server on port 9000, the same port that every other net uses. The daemon that owns the PicoScope listens on loopback only. You cannot reach it from outside the box: Capture frames cross the relay in LSCP/1, a packed binary format. A frame has a 64-byte header, a 16-byte descriptor for each channel, and then contiguous int16 ADC counts. The relay forwards frames without a decode, so its cost does not grow with the capture size.
Earlier versions published the daemon directly on ports 8081-8085. They streamed to the browser over WebTransport, which needed a QUIC listener and a certificate in the container. That design is gone. There is one listener, on loopback, and one way in.

stream start

Start a streaming acquisition on a PicoScope, and print the link to the web UI.
Options: The command applies the settings in order, then starts the acquisition. If the daemon refuses a setting, the command prints the error and exits 1. The acquisition does not start. The trigger source is the streamed channel. After the start, the command prints the link to http://<box>:9000/scope. With --json, the link is the visualization_url field. On a box behind an access gateway, the link carries your sign-in token, as for webcam streams. For a scope that is not a PicoScope, the command prints an error and suggests lager scope NET_NAME start --single. Examples:

stream stop

Stop the streaming acquisition. If the daemon refuses, the command prints the error and exits 1.

stream status

Check that the oscilloscope daemon runs. The command shows the command port, the channel count and whether a capture is ready. It does not need a net name.
The command exits 1 if the daemon does not answer or cannot reach the scope. So a script can use it to check that a scope is ready to stream.

stream web

Open the oscilloscope web UI in a browser.
Options:
  • --port - Box HTTP server port (default: 9000)
The command opens http://<box>:<port>/scope. On a box behind an access gateway, the link carries your sign-in token, as for webcam streams. Run stream web again for a fresh link when the token expires. The web interface is a dependency-free HTML5 oscilloscope display that the box serves at http://<box>:9000/scope. Waveforms arrive over a WebSocket as LSCP binary frames, and the browser decodes them. The page builds its controls from the capabilities of the attached unit, so a 2-channel scope shows no channel C. The page also has a command console. It accepts most commands of this CLI, and also offset, hpos, vpos, sidebar and capabilities. In the console, a command for one channel can name the channel: scale B 0.5, coupling B ac, probe B 10, offset B 0.1, vpos B -0.5 and measure B vpp. Put the channel first. Use a letter for it, because scale 2 sets 2 V/div. With no channel, the command uses the first channel that is on, as the measurements panel does. The reply in the console names the channel. Hide the controls sidebar to give the trace and the console the full width. Use the Hide sidebar button in the header, or type sidebar off. sidebar on and Show sidebar bring it back. sidebar with no argument says which it is. The page keeps the choice for the next visit. Turning a channel off removes its trace, including the one already on screen. disable B does it, and so does the channel’s switch. Unplugging a scope during a stream stops the live session. The page then shows no live trace. Plugging the scope back in opens the unit again. Start then runs on the new session. The page has two position controls, and they work differently:
  • Units. In the console, give a number in seconds or volts, or add a unit: hpos 100ms, hpos 0.1 and hpos 1e-3 are all correct. In the sidebar, the selector beside each field changes the unit of the number that the field shows. It does not change the position.
  • Limits. The limits are in divisions, so they change when you change the scale. If a position is outside the limit, the page moves it to the limit and writes a note in the console. A vertical position stays at the same voltage when you change volts/div, until it is outside the limit.
  • Applying a value. A value that you type in the horizontal field applies when you push Enter or leave the field, because each change starts a new capture. Escape restores the last value. A value that you type in the vertical field applies immediately.
  • Arrow keys and buttons. Each field has an up button and a down button at its right edge. In both fields, the buttons and the Up and Down keys apply a step immediately. They change the last digit that the field shows: 1.14 becomes 1.13, and 1.1 becomes 1.2. The field keeps the same number of decimal places, so 1.19 becomes 1.20. If the field shows only 0, the step is one tenth of a division. Hold a button down to repeat the step.
  • offset is not vpos. offset moves the signal in the scope hardware, before the ADC. The measurements change, and at a smaller volts/div you get more resolution on a signal that is not centred on 0 V. vpos only moves the trace on the screen. Legacy PicoScope 2000 models (for example the 2204A) have no analog offset. On these models, the console refuses a nonzero offset and tells you to use vpos.
  • status also shows the vertical position of each channel. position is an old name for hpos, and it will be removed in a later release.

stream capture

Record the captures that a streaming PicoScope takes during --duration to a CSV file. Run stream start first.
Options: The command writes the CSV file on the box, not on your computer. A relative path is relative to /tmp on the box. After the capture, the command prints an scp command that copies the file to your computer. The command either captures data or fails. If the scope is stopped, or no capture arrives during --duration, it prints the cause and exits 1. In normal and single mode, the scope waits for a trigger, so check the trigger level and source. The CSV columns are capture, channel, sample_index, time_ns and voltage. Examples:

stream config

Change streaming settings without a start or a stop of the acquisition.
Options: Give at least one setting. --volts-per-div, --coupling, --enable and --disable apply to the channel that --channel names. Without --channel, they apply to the channel of the net, else to channel A. The command prints each setting that it applies. It stops at the first setting that the daemon refuses, and exits 1. Examples:

Examples

Basic Rigol Workflow

Channel Configuration

Measurements

Triggering

Cursor Measurements

PicoScope Streaming


Command Structure


Notes

  • Net names are the names that you assign with lager nets when you set up your testbed
  • Instrument commands work on a scope net or on one of its scope-channel nets. Channel commands need a scope-channel net
  • Streaming commands work only on PicoScope devices
  • Measurements work on both instruments. --display and --cursor are Rigol only, because they draw on the screen of the instrument
  • cursor time, cursor volts and cursor off are PicoScope only. The display cursor commands are Rigol only
  • status, acquire, roll, fft, display and trigger holdoff are PicoScope only
  • The edge trigger is the only trigger type that works on both PicoScope and Rigol
  • On the Rigol MSO5000, only the edge and SPI triggers work (see issue #418)
  • The web UI needs access to port 9000 on the Lager Box
  • The CLI rejects values outside the allowed ranges before it sends them to the hardware
  • Run lager scope --box BOX to list the scope and scope-channel nets

See Also