Oscilloscope¶
Main oscilloscope control class for SCPI communication
Main Oscilloscope class for controlling Siglent oscilloscopes.
Supports multiple Siglent oscilloscope series including SDS800X HD, SDS1000X-E, SDS2000X Plus, and SDS5000X.
Oscilloscope
¶
Oscilloscope(host: str, port: int = 5025, timeout: float = 5.0, connection: Optional[BaseConnection] = None, dialect: Optional[str] = None)
Main class for controlling Siglent oscilloscopes.
This class provides a high-level interface for controlling oscilloscope functions including channels, triggers, waveform acquisition, and measurements.
Supports multiple Siglent oscilloscope series with automatic model detection and capability-based feature availability.
Example
scope = Oscilloscope('192.168.1.100') scope.connect() print(scope.identify()) print(f"Model: {scope.model_capability.model_name}") print(f"Channels: {scope.model_capability.num_channels}") scope.disconnect()
Or using context manager:
with Oscilloscope('192.168.1.100') as scope: ... print(scope.identify())
Initialize oscilloscope connection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
host
|
str
|
IP address or hostname of the oscilloscope |
required |
port
|
int
|
TCP port for SCPI communication (default: 5025, the Siglent raw SCPI socket; 5024 is the telnet-style port with prompts and is not recommended) |
5025
|
timeout
|
float
|
Command timeout in seconds (default: 5.0) |
5.0
|
connection
|
Optional[BaseConnection]
|
Optional custom connection object (uses SocketConnection if None) |
None
|
dialect
|
Optional[str]
|
Optional SCPI dialect override - "legacy" or "modern". None (default) auto-detects from the model registry. Use "legacy" if a modern-generation scope misbehaves on the colon-form commands. |
None
|
Note
Channels are created dynamically after connection based on model capabilities. Call connect() to establish connection and initialize channels.
Source code in scpi_control/oscilloscope.py
vector_display
property
¶
Access vector graphics display functionality.
Requires the 'fun' extras to be installed: pip install "SCPI-Instrument-Control[fun]"
Returns:
| Type | Description |
|---|---|
|
VectorDisplay instance for XY mode graphics |
Raises:
| Type | Description |
|---|---|
ImportError
|
If 'fun' extras are not installed |
Example
scope.vector_display.enable_xy_mode() circle = Shape.circle(radius=0.8) scope.vector_display.draw(circle)
is_connected
property
¶
Check if connected to oscilloscope.
Returns:
| Type | Description |
|---|---|
bool
|
True if connected, False otherwise |
device_info
property
¶
Get parsed device information.
Returns:
| Type | Description |
|---|---|
Optional[Dict[str, str]]
|
Dictionary with keys: manufacturer, model, serial, firmware |
Optional[Dict[str, str]]
|
None if not connected |
supported_channels
property
¶
Get list of supported channel numbers for this model.
Returns:
| Type | Description |
|---|---|
List[int]
|
List of channel numbers (e.g., [1, 2, 3, 4] for 4-channel model) |
List[int]
|
Empty list if not connected |
Example
scope.connect() print(scope.supported_channels) [1, 2, 3, 4]
capabilities
property
¶
Derived capabilities of the CONNECTED scope (dialect-resolved).
Raises:
| Type | Description |
|---|---|
SiglentConnectionError
|
before connect()/after disconnect() -- capabilities depend on the resolved dialect; guessing would fabricate support claims. |
connect
¶
Establish connection to the oscilloscope.
This method connects to the oscilloscope, detects the model, and initializes model-specific capabilities and channels.
Raises:
| Type | Description |
|---|---|
SiglentConnectionError
|
If connection fails |
SiglentTimeoutError
|
If connection times out |
Source code in scpi_control/oscilloscope.py
disconnect
¶
Close connection to the oscilloscope.
Source code in scpi_control/oscilloscope.py
write
¶
Send a SCPI command to the oscilloscope.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
command
|
str
|
SCPI command string |
required |
Raises:
| Type | Description |
|---|---|
SiglentConnectionError
|
If not connected |
CommandError
|
If command contains invalid characters |
Source code in scpi_control/oscilloscope.py
query
¶
Send a SCPI query and get the response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
command
|
str
|
SCPI query command |
required |
Returns:
| Type | Description |
|---|---|
str
|
Response string from oscilloscope |
Raises:
| Type | Description |
|---|---|
SiglentConnectionError
|
If not connected |
SiglentTimeoutError
|
If query times out |
CommandError
|
If command contains invalid characters |
Source code in scpi_control/oscilloscope.py
read_raw
¶
Read raw binary data from oscilloscope.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
Optional[int]
|
Number of bytes to read (None for all available) |
None
|
framing
|
Framing
|
What the caller knows the response to be (see connection.framing.Framing). What happens when BOTH size and framing are given is transport-specific, not a uniform "ignored": SocketConnection's exact-size path never reaches the framing code, so framing is genuinely ignored there. MockConnection's BLOCK check instead runs unconditionally, BEFORE size truncation -- a declaration the canned response cannot honour still raises CommandError even with size set, deliberately, so a wrong wire-shape declaration cannot hide behind a truncated read. |
AUTO
|
Returns:
| Type | Description |
|---|---|
bytes
|
Raw binary data |
Source code in scpi_control/oscilloscope.py
identify
¶
Get device identification string.
Returns:
| Type | Description |
|---|---|
str
|
Device identification string (manufacturer, model, serial, firmware) |
Example
'Siglent Technologies,SDS824X HD,SERIAL123,1.0.0.0'
Source code in scpi_control/oscilloscope.py
reset
¶
Reset oscilloscope to default settings.
Note: This may take several seconds to complete.
clear_status
¶
get_error
¶
Unsupported: neither Siglent scope dialect documents an error-queue query.
Legacy scopes use CMR?/EXR? registers; the modern programming guide documents no error queue at all. The old SYST:ERR? implementation always timed out on real hardware.
Source code in scpi_control/oscilloscope.py
wait_complete
¶
trigger_single
¶
Arm a one-shot (single) acquisition.
Source code in scpi_control/oscilloscope.py
trigger_force
¶
run
¶
Start acquisition.
Source code in scpi_control/oscilloscope.py
stop
¶
acquisition_status
¶
Query the acquisition state, normalized across dialects.
Returns:
| Type | Description |
|---|---|
str
|
One of 'ARM', 'READY', 'AUTO', 'TRIGD', 'STOP', 'ROLL'. |
Source code in scpi_control/oscilloscope.py
new_acquisition_ready
¶
True if a new acquisition has completed since the last check.
Returns None when the active dialect has no way to tell us, which callers must treat as "no gate available" rather than as False -- a False would stall the live view forever on those dialects.
The underlying INR? register is READ-AND-CLEAR: reading it consumes the event. This method is therefore the single permitted consumer. Do not read get_new_data anywhere else, and do not call this method twice per tick expecting the same answer.
Source code in scpi_control/oscilloscope.py
record_length
¶
The full acquisition length in points, or None if the dialect can't say.
This is :ACQuire:POINts?, NOT :WAVeform:MAXPoint? -- the latter is the maximum points a single transfer can carry, not how many the record actually holds. A caller sizing a stride from the wrong one would under-decimate a deep record.
A dialect that MAPS the command is not a promise the instrument will answer it: firmware that doesn't implement the query (or errors on it while stopped) makes it fail, and so does the mock, which has no modern handler for it. A raise here reached the gateway's export path as a 504 on an otherwise healthy session, so this degrades to None -- "the dialect can't say" -- exactly like waveform_max_points() below, and callers already handle None.
Source code in scpi_control/oscilloscope.py
waveform_max_points
¶
The instrument's per-:WAVeform:DATA?-transfer cap, or None if the dialect can't say.
This is :WAVeform:MAXPoint? -- the same cap ModernTransfer.acquire (waveform_transfer.py) reads before deciding whether a strided record fits in a single window, raising FeatureNotSupportedError when it doesn't. A caller sizing a stride against a frame budget alone, ignoring this number, can turn that guard into a total live-view outage on a model that reports a cap below the frame budget -- size against min(frame_budget, this value) instead.
Source code in scpi_control/oscilloscope.py
set_timebase
¶
auto_setup
¶
get_waveform
¶
Acquire waveform data from a channel.
Convenience method that calls waveform.acquire().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channel
|
int
|
Channel number (1-4) |
required |
provenance
|
bool
|
Snapshot instrument settings alongside the data (default True; pass False on high-rate paths) |
True
|
stride
|
Optional[int]
|
Ask the instrument to return every Nth point via :WAVeform:INTerval, bounding the transfer instead of pulling the full record and striding it down afterward. This is instrument state, not a per-request argument: every read sets it explicitly, so None means "set it to 1", never "leave it alone" -- otherwise a stride left over from the live view would silently decimate the next export on this session. Ignored on dialects that don't document the command. |
None
|
Returns:
| Type | Description |
|---|---|
WaveformData
|
WaveformData object with time and voltage arrays |
Source code in scpi_control/oscilloscope.py
get_channel
¶
Get channel object by number.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channel_num
|
int
|
Channel number (1-based) |
required |
Returns:
| Type | Description |
|---|---|
Optional[Channel]
|
Channel object or None if channel doesn't exist |
Example
scope.connect() ch1 = scope.get_channel(1)
Source code in scpi_control/oscilloscope.py
See Also¶
- Vocabulary - String-compatible enums for token-valued parameters (coupling, trigger mode/slope/source/coupling/type, bandwidth limit, tracking mode) -- enums in, strings out
- Scope Capabilities - Derived, dialect-resolved capabilities of a connected oscilloscope (scope.capabilities)
- Channel - Channel configuration and control
- Trigger - Trigger configuration and modes
- Waveform - Waveform acquisition and data handling
- Measurement - Automated measurements (frequency, voltage, timing)
- Exceptions - Custom exception classes