Repository navigation
Scripting
openSciLab works without its window, too: the command line captures, converts, decodes and runs flows, and the Python API does the same from your own scripts. Neither loads the user interface, so both work over SSH and in CI. This page is the practical overview; the reference is docs/cli.md.
The commands come with the Python package (see Installation, running from
source): openscilab starts the application, and openscilab <command> runs a command instead –
the same as openscilab-cli <command>. python -m openscilab <command> works as well.
| Command | Does |
|---|---|
devices |
list the connected devices with their identifiers |
info [DEVICE] |
describe a device (channels, rates, memory, what it simulates) |
capture |
capture and save the samples, optionally decode them right away |
convert IN OUT |
convert a capture file (.lac, .lac.gz, .sr → those, .csv, .vcd) |
decode FILE |
run protocol decoders on a capture file |
decoders |
list the protocol decoders |
plugins |
list the plugins and the kinds of devices they add |
run FLOW |
run a flow |
sim [PROFILE] |
list the simulator profiles, or describe one |
openscilab-cli --help and openscilab-cli <command> --help list every option. --decoders-dir DIR
(before the command) adds a folder of decoders. Every error ends with exit code 1 and one line on
stderr; OPENSCILAB_TRACEBACK=1 shows where it came from.
Every device has an identifier. Without --device the first device found is used.
| Identifier | Device |
|---|---|
pico:/dev/cu.usbmodem1, pico:COM5
|
Pico board with the openSciLab Pico firmware over USB |
pico-net:192.168.1.5:4045 |
Pico W board over WiFi |
pico-multi:/dev/ttyACM0,/dev/ttyACM1 |
multi device set of 2 to 5 boards |
dslogic, dslogic:1:4
|
the first DSLogic, or the one at USB bus 1, address 4 |
arduino:/dev/cu.usbserial-1410 |
Arduino board with the openSciLab Arduino firmware |
rigol:192.168.1.20 |
Rigol DHO900 oscilloscope (through its bridge app when it runs) |
sim:free, sim:uno, sim:pico, ... |
a simulator (openscilab sim lists them) |
arduino-sim:uno, rigol-sim:bridge
|
simulators that speak the real device's protocol |
<kind>:... |
a device of a plugin (openscilab-cli plugins) |
openscilab-cli devices
openscilab-cli info sim:free# 8 channels at 10 MHz for 5 ms, 1000 samples before a rising edge on channel 0
openscilab-cli capture --channels 0-7 --rate 10M --duration 5ms --pre 1000 \
--trigger edge:0:rising -o capture.sr
# Start at once, stream 2 seconds from a DSLogic
openscilab-cli capture -d dslogic -c 0-3 -r 20M -t 2s --mode stream --trigger immediate -o long.lac.gz
# No hardware: the UART of the simulator on D9, decoded right away
openscilab-cli capture -d sim:free -c 9 -r 4M -t 2ms --pre 100 --trigger edge:9:falling \
-o uart.sr --decode uart:rx=9,baudrate=115200 --annotations uart.csv| Option | Meaning |
|---|---|
--device, -d
|
device identifier |
--channels, -c
|
channels counted from 0: 0-7,9 (default 0-7); --names gives them names |
--rate, -r
|
10M, 100k, 1e6, 24MHz (default: the highest) |
--samples, -n / --duration, -t
|
total samples (including --pre) / a time: 5ms, 250us, 1s, 2 min (5m is 5 milliseconds) |
--pre |
samples before the trigger |
--trigger |
edge:<ch>:rising|falling, pattern:0=1,1=0, fast:0=1,1=0, immediate
|
--mode |
buffer (into the device's memory) or stream (over USB while capturing) |
--software-trigger |
with --mode stream: look for the trigger in the stream, on any channel, also on devices whose streams have no trigger |
--threshold |
input threshold in volts (DSLogic) |
--timeout |
seconds to wait for the trigger |
--output, -o
|
.lac, .lac.gz, .sr, .csv (--time adds a time column) or .vcd
|
--decode, --annotations
|
decoders to run right after the capture, and where their output goes |
Settings the device cannot capture are rejected before the capture starts.
openscilab-cli convert capture.lac capture.sr # open it in PulseView
openscilab-cli convert --time capture.sr capture.csv
openscilab-cli decode capture.sr --decoder uart:rx=0,baudrate=115200 -o uart.csv
openscilab-cli decode capture.lac -D i2c:scl=SCL,sda=SDA -D eeprom24xx -o eeprom.jsonAfter <decoder>: come its channels (capture channel number or name) and options. A decoder that
works on the output of another one (eeprom24xx on i2c) is stacked on the one before it. The CSV
has the columns Start time (s), End time (s), Start sample, End sample, Decoder, Row
and Value (times relative to the trigger); the JSON file has the same records and the errors of
the decoders. More in Protocol decoders and Files.
openscilab run flows/test.flow.yaml # real time, the devices of the flow
openscilab run examples/flows/counter.flow.yaml --sim --fast
openscilab run flows/curve.flow.yaml --device dho=sim:dho924s --report out.html
openscilab run flows/logger.flow.yaml --duration 1h
openscilab run flows/counter.py --fast # a flow written in Python| Option | Meaning |
|---|---|
--sim |
every device node of the flow is a simulator (sim: devices are anyway) |
--fast |
virtual time: as fast as possible, the same result every time (simulators) |
--device NAME=ADDRESS |
another address for the device node NAME (repeatable) |
--duration 10s |
end the flow after this (virtual or real) time |
--seed N |
seed of the random numbers (noise of simulators) |
--timeout S |
give up after this many seconds of real time |
--data-dir DIR |
where files are written (default: data/ of the project, or the flow's folder) |
--report FILE.html |
a report of the run: the parts of the report.* nodes, the checks, the run itself |
-v, -q
|
the log of the nodes while running / no summary |
The exit code is 0 when the flow finished and every check passed (report.check,
control.compare), 1 otherwise: a flow is a test on a test bench
(Panels and reports). A flow inside a project folder (one
with project.yaml) uses the project's devices and own nodes, and writes into its data/ folder.
Remote devices run in real time only and have no --sim replacement; give them a remote-sim:
address with --device instead.
from openscilab import api
print(api.devices())
with api.open("sim:free") as device: # or api.open() for the first device found
capture = device.capture(
channels=[0, 1, 2, 3],
rate="10M", # or 10_000_000
duration="1ms", # or samples=10_000
pre_trigger=100,
trigger=api.Edge(0, rising=True), # api.Pattern({0: 1, 1: 0}), api.Immediate(), api.Sequence([...])
mode="buffer",
timeout=10,
)
capture.save("capture.sr") # .lac, .lac.gz, .sr, .csv, .vcd
bit0 = capture.samples(0) # numpy array of 0/1, or samples("CLK")
print(capture.frequency, capture.sample_count, capture.trigger_sample)
capture = api.load("capture.lac")
for item in capture.decode("i2c", channels={"scl": 0, "sda": 1}):
print(f"{item.start_time:.6f} {item.row}: {item.value}")-
capture()waits until the samples are there. It raisesValueErrorfor settings the device cannot capture,api.CaptureFailedwhen the device reports an error andTimeoutErroraftertimeoutseconds without a trigger. -
mode="stream", software_trigger=Truelooks for the trigger in the stream: any trigger on any captured channel, also anapi.Sequenceof patterns, edges, pulse widths and gaps. -
api.instrument("sim:uno")gives an instrument with all its facets:uno.gpio.write("D7", 1),uno.monitor.sample(["D3"]). -
device.inject("disconnect")(also"delay","overflow","restart") injects a fault into a simulator, to test how a script copes. -
api.open(..., process=True)reads the device in a process of its own, as the application does.
Build a flow in code and run it – the same model as the YAML file and the editor:
from openscilab.lab import flow, nodes as n
with flow("Counter") as f:
sim = f.device("sim", "sim:free")
cap = n.device.capture(sim, channels=["D0", "D8"], rate="4 MHz", samples=20000, trigger=n.edge("D8"))
freq = n.measure.frequency(cap.D8)
freq >> n.report.check(name="clock", low=0.9e6, high=1.1e6)
cap.capture >> n.data.file(path="counter.lac")
result = f.run(fast=True)
print(result.state, result.time, result.ok)
print(result.value("frequency", "out"))
print(f.to_yaml()) # the same flow as YAML-
n.<group>.<name>(...)adds a node; a device (oruno.pin("D9")) given to it is wired to itsdeviceinput, a port given to it is wired to its first free input; other arguments set parameters. Nodes are named after their type (capture,frequency) unless you passid=. -
a.out >> b.inwires two ports,a >> bthe first output to the first free input. -
f.run(fast=True, sim=True)runs it;f.save("counter.flow.yaml")writes the YAML file. - An existing flow file runs with
api.run_flow("flows/test.flow.yaml", sim=True, fast=True).
Such a script also opens in the application as a graph, and openscilab run script.py runs it.
For node types of your own, see Nodes.
The console at the bottom of the window (View → Console, Ctrl+J) has a Python tab: a Python
console with shell (the window), openscilab, documents() and active() (the active document),
with completion of attribute names. Handy to look at the data of a document or try a line of the API
without leaving the application.
- docs/cli.md – the reference of the command line and the API
- Flows and Nodes – what a flow is made of
-
Remote devices – the
openscilab_devicepackage for scripts on other computers - Writing drivers – new kinds of devices as plugins
openSciLab · 0.1 beta
Instruments
Logic analyzer
The lab
More