Repository navigation
Nodes
An overview of the node families of a flow: what each family is for and one or two typical uses. The complete list with every node is in docs/lab.md; in the application the palette shows a node's description as a tooltip, and the inspector shows it above the parameters.
The node palette beside the flow groups the nodes by family. A node's type names its family:
measure.frequency is in Measurement.
| Palette group | Types | For |
|---|---|---|
| Devices | device.* |
the instrument itself, capturing, streaming, reading pins periodically |
| Remote devices | remote.* |
devices on another computer (values, outputs, commands, clock) |
| Time | timing.* |
sync signals, aligning instruments, measuring latency |
| GPIO | gpio.* |
setting and reading pins, pulses, PWM, analog outputs |
| Generator | gen.* |
waveforms, patterns, replaying captures, sending UART/SPI/I²C |
| Decoders | decode.* |
the 133 sigrok protocol decoders |
| Measurement | measure.* |
frequency, period, duty cycle, counts, min/max/mean/RMS, setup/hold |
| Signal processing | dsp.* |
thresholds, filters, FFT, derivative, integral, averaging, formulas |
| Control | control.* |
timers, sweeps, sequences, state machines, comparisons, Python code |
| Data | data.* |
files, long-term logging, tables, buffers |
| Views | view.* |
scope, strip chart, XY chart, spectrum, number, LED, table, log |
| Report | report.* |
sections, tables, diagrams and checks of a report |
| Conversions | convert.* |
one type of value into another |
| Structure | structure.* |
bundles of values, comments, groups |
Many nodes that need a device have a device input: wire it to the device output of a device
node. Parameters take quantities with units (1 kHz, 20 ms, 3.3 V).
device.instrument is the instrument (its address: sim:uno, pico:COM5, ...; for a simulator
signals says what it simulates). device.capture captures once with channels, rate, length and
trigger, or again on every value at arm; with a clock channel it samples on the edges of that
clock (state mode). device.stream sends blocks of samples while it runs. device.monitor reads
pins and analog inputs a few times a second.
-
Capture on a trigger:
device.capturewithtrigger: {edge: rising, source: D8}, wired to a scope and a measurement (Templates → Basics → Edge trigger). -
Watch something slow:
device.monitoron an analog input into a strip chart (Templates → Digital I/O → Monitor).
gpio.write, gpio.read, gpio.pulse (pulses timed by the device), gpio.pwm and gpio.dac
(voltage of an analog output).
-
Blink: a
control.timerticks, a counter anddsp.mathturn the ticks into 1, 0, 1, ... forgpio.write(Templates → Digital I/O → Blink). -
Stimulus: the capture reports
armed, acontrol.sequencewaits 1 ms and triggersgpio.pulse, so the capture sees the pulses (Templates → Digital I/O → Pulse train).
gen.waveform (sine, square, triangle, ramp, pulse, DC, noise), gen.arbitrary (a formula, a CSV
file or a signal), gen.pattern (digital patterns in SDL), gen.replay (play a capture),
gen.output (a saved *.wave.yaml), gen.tx_uart, gen.tx_spi, gen.tx_i2c. Their sync output
marks each start, e.g. to arm a capture.
-
Function generator:
gen.waveformon an oscilloscope's generator, captured on CH1 (Templates → Signal generation → Function generator). -
Talk to a device:
gen.tx_i2creads a sensor with the board's own I²C (Templates → Protocols → I²C sensor).
Every sigrok protocol decoder is a node (decode.uart, decode.i2c, decode.spi, decode.can,
...): a capture at in; the annotations as events, a table and text at the outputs. The
inspector assigns the decoder's channels from the channels of the capture wired to it. A decoder
that works on another one's output (eeprom24xx on i2c) is wired behind it.
-
Check a message:
decode.uart→text→control.compare(Templates → Protocols → Check a message).
More in Protocol decoders.
measure.frequency, period, duty, pulse_width, count, setup_hold for digital signals;
measure.min, max, mean, rms, peak_to_peak for analog ones (each block of a stream gives a
value).
-
Is the clock right?
measure.frequencyoncapture.D8→report.checkwith limits (Templates → Measurement → Frequency and duty cycle). - Scope measurements: mean, RMS and peak to peak of four oscilloscope channels (Templates → Analog → Scope measurements).
dsp.threshold (analog to digital, with hysteresis), dsp.debounce, dsp.filter (low-pass,
high-pass, band-pass, band-stop: FIR or IIR), dsp.fft, dsp.derivative, dsp.integral,
dsp.average, dsp.resample and dsp.math (an expression of the inputs a to d with numpy,
e.g. sqrt(a**2 + b**2)).
-
Clean a noisy signal:
dsp.filterbefore a measurement (Templates → Analog → Low pass filter). -
A bouncing button: count edges before and after
dsp.debounce(Templates → Digital I/O → Button).
control.timer ticks, control.sweep steps a value, control.sequence runs steps without code,
control.state_machine runs states with their outputs and ways out, control.compare and
control.limit decide, control.counter counts, control.python runs code of your own.
-
Characteristic curve:
control.sweepsteps the duty cycle ofgpio.pwm,gpio.readreads the voltage after each step,data.tableandview.xycollect and draw the curve (Templates → Control → PWM sweep). -
Traffic light:
control.state_machinedrives three pins (Templates → Control → Traffic light).
data.file writes what arrives (captures as .lac, .sr, .csv, .vcd by the extension;
tables and other values as CSV; numbered for one file per value), data.file_read reads a capture
or table, data.logger records for hours to CSV or a capture on disk, data.table collects values
into rows, data.buffer keeps the latest values.
-
Log readings: values into
data.loggerwith a.csvpath (Templates → Data and reports → CSV logger). -
Work on a recording:
data.file_readinstead of a device (Templates → Basics → Read a capture file).
view.scope (captures in a data view, with decoders and cursors), view.strip_chart, view.xy,
view.spectrum, view.number, view.led, view.table, view.log. Each opens a document while
the flow runs. For a front panel with the same displays use a panel.
-
Frequency over time: a stream, a measurement,
view.strip_chart(Templates → Basics → Stream).
report.section, report.table, report.image (diagrams), report.check (limits or an expected
value) and report.write (HTML or PDF). See Panels and reports.
convert.channel (one channel of a capture), convert.edges, convert.state_bit,
convert.to_analog, convert.to_scalar. You rarely add them by hand: a wire whose types do not fit
offers the right conversion (Flows).
structure.bundle puts several values on one wire, structure.unbundle takes them apart again;
structure.comment and structure.group are notes and frames on the canvas. A subflow is a
part of a flow used like one node (type subflow.<name>).
- Two values together: frequency and duty cycle bundled into one CSV line (Templates → Data and reports → Bundle).
timing.sync drives a sync signal on a pin, timing.align puts an instrument on a reference's
time by that signal, timing.calibrate measures how late an instrument's samples arrive. See
Time and synchronization.
remote.receive (values of a device on another computer, with the time they were measured),
remote.set (an output, applied at a given time), remote.call (a command) and remote.sync
(align its clock with a sync signal). They run in real time only. See Remote devices.
Inside a flow: control.python holds code. async def run(ctx) runs with the flow
(ctx.emit(port, value), await ctx.sleep(seconds), await ctx.receive(port),
ctx.device(name), ctx.log(text)); def on_input(ctx, port, value) is called for every value
on an input. Its parameters inputs and outputs name the ports. The editor highlights the code
and completes ctx., np. and the port names (Templates → Python → Python node).
For a project: every function with @node in a .py file in the project's nodes/ folder is a
node type in the palette:
from openscilab.lab import In, Out, Param, node
@node("example.double", inputs=[In("value", "Scalar", optional=False)], outputs=[Out("out", "Scalar")])
def double(value):
return value.value * 2
@node("example.blink", outputs=[Out("level", "Bool")], params=[Param("period", "quantity", "1 s", "s")])
async def blink(ctx):
for _ in range(3):
ctx.emit("level", True)
await ctx.sleep(ctx.quantity("period") / 2)
ctx.emit("level", False)
await ctx.sleep(ctx.quantity("period") / 2)A plain function is called with the latest values of its inputs whenever one changes; its result
goes to the output (a dict of values for several outputs, None for nothing). An async def
taking ctx runs with the flow. For periodic work use await ctx.sleep_until(start + n * period),
which keeps the period; await ctx.device_call(...) calls a device without holding up the other
nodes. The example is Templates → Python → Own nodes.
For every flow and project: a plugin brings node types with the same @node - a .py file in
the plugins folder of the settings directory, or an installed package (see
Writing drivers). Its nodes appear in the palette in a group of their own
(node_group("calib", "Calibration") names it), in every project, in flow files and on the
command line; Help → Plugins… lists them. A flow that uses a node of a plugin that is not
installed says so. A complete example with a two-point calibration and an NTC thermistor is
examples/plugins/calibration_nodes.py;
the details are in
docs/drivers.md.
openSciLab · 0.1 beta
Instruments
Logic analyzer
The lab
More