Skip to content

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 = 5024, timeout: float = 5.0, connection: Optional[BaseConnection] = 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: 5024)

5024
timeout float

Command timeout in seconds (default: 5.0)

5.0
connection Optional[BaseConnection]

Optional custom connection object (uses SocketConnection if None)

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
def __init__(
    self,
    host: str,
    port: int = 5024,
    timeout: float = 5.0,
    connection: Optional[BaseConnection] = None,
):
    """Initialize oscilloscope connection.

    Args:
        host: IP address or hostname of the oscilloscope
        port: TCP port for SCPI communication (default: 5024)
        timeout: Command timeout in seconds (default: 5.0)
        connection: Optional custom connection object (uses SocketConnection if None)

    Note:
        Channels are created dynamically after connection based on model capabilities.
        Call connect() to establish connection and initialize channels.
    """
    self.host = host
    self.port = port
    self.timeout = timeout

    # Create connection
    if connection is not None:
        self._connection = connection
    else:
        self._connection = SocketConnection(host, port, timeout)

    # Model capability and SCPI commands (populated after connection)
    self.model_capability: Optional[ModelCapability] = None
    self._scpi_commands: Optional[SCPICommandSet] = None

    # Device information (populated after connection)
    self._device_info: Optional[Dict[str, str]] = None

    # Channels will be created dynamically based on model capability
    # After connection, channels will be available as self.channel1, self.channel2, etc.

    # Initialize trigger control
    self.trigger = Trigger(self)

    # Initialize waveform acquisition
    self.waveform = Waveform(self)

    # Initialize measurement control
    self.measurement = Measurement(self)

    # Initialize screen capture
    self.screen_capture = ScreenCapture(self)

    # Initialize math channels (available after connection)
    self.math1: Optional[MathChannel] = None
    self.math2: Optional[MathChannel] = None

    # Initialize FFT analyzer
    self.fft_analyzer = FFTAnalyzer()

    # Vector display (lazy-loaded, requires 'fun' extras)
    self._vector_display = None

vector_display property

vector_display

Access vector graphics display functionality.

Requires the 'fun' extras to be installed: pip install "Siglent-Oscilloscope[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

is_connected: bool

Check if connected to oscilloscope.

Returns:

Type Description
bool

True if connected, False otherwise

timebase property writable

timebase: float

Get timebase setting in seconds/division.

device_info property

device_info: Optional[Dict[str, str]]

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

supported_channels: List[int]

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]

connect

connect() -> None

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
def connect(self) -> None:
    """Establish connection to the oscilloscope.

    This method connects to the oscilloscope, detects the model, and initializes
    model-specific capabilities and channels.

    Raises:
        SiglentConnectionError: If connection fails
        SiglentTimeoutError: If connection times out
    """
    logger.info(f"Connecting to oscilloscope at {self.host}:{self.port}")
    self._connection.connect()
    logger.info("Connected successfully")

    # Verify connection by getting device identification
    try:
        idn_string = self.identify()
        self._device_info = self._parse_idn(idn_string)
        logger.info(f"Connected to: {self._device_info.get('model', 'Unknown')}")

        # Detect model capability
        self.model_capability = detect_model_from_idn(idn_string)
        logger.info(f"Model capability: {self.model_capability}")

        # Initialize SCPI command set for this model
        self._scpi_commands = SCPICommandSet(self.model_capability.scpi_variant)
        logger.info(f"Using SCPI variant: {self.model_capability.scpi_variant}")

        # Create channels dynamically based on model capability
        self._create_channels()

        # Create math channels
        self._create_math_channels()

        # Update device info with capability information
        self._device_info["series"] = self.model_capability.series
        self._device_info["num_channels"] = str(self.model_capability.num_channels)
        self._device_info["bandwidth_mhz"] = str(self.model_capability.bandwidth_mhz)

    except Exception as e:
        logger.error(f"Failed to identify device or initialize: {e}")
        self.disconnect()
        raise exceptions.SiglentConnectionError(f"Connected but failed to identify device: {e}")

disconnect

disconnect() -> None

Close connection to the oscilloscope.

Source code in scpi_control/oscilloscope.py
def disconnect(self) -> None:
    """Close connection to the oscilloscope."""
    logger.info("Disconnecting from oscilloscope")
    self._connection.disconnect()
    self._device_info = None
    self.model_capability = None
    self._scpi_commands = None

    # Remove dynamically created channels
    for i in range(1, 5):  # Check all possible channels
        channel_attr = f"channel{i}"
        if hasattr(self, channel_attr):
            delattr(self, channel_attr)

    # Clear math channels
    self.math1 = None
    self.math2 = None

write

write(command: str) -> None

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
def write(self, command: str) -> None:
    """Send a SCPI command to the oscilloscope.

    Args:
        command: SCPI command string

    Raises:
        SiglentConnectionError: If not connected
        CommandError: If command contains invalid characters
    """
    logger.debug(f"Write: {command}")
    self._connection.write(command)

query

query(command: str) -> str

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
def query(self, command: str) -> str:
    """Send a SCPI query and get the response.

    Args:
        command: SCPI query command

    Returns:
        Response string from oscilloscope

    Raises:
        SiglentConnectionError: If not connected
        SiglentTimeoutError: If query times out
        CommandError: If command contains invalid characters
    """
    logger.debug(f"Query: {command}")
    response = self._connection.query(command)
    logger.debug(f"Response: {response}")
    return response

read_raw

read_raw(size: Optional[int] = None) -> bytes

Read raw binary data from oscilloscope.

Parameters:

Name Type Description Default
size Optional[int]

Number of bytes to read (None for all available)

None

Returns:

Type Description
bytes

Raw binary data

Source code in scpi_control/oscilloscope.py
def read_raw(self, size: Optional[int] = None) -> bytes:
    """Read raw binary data from oscilloscope.

    Args:
        size: Number of bytes to read (None for all available)

    Returns:
        Raw binary data
    """
    return self._connection.read_raw(size)

identify

identify() -> str

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
def identify(self) -> str:
    """Get device identification string.

    Returns:
        Device identification string (manufacturer, model, serial, firmware)

    Example:
        'Siglent Technologies,SDS824X HD,SERIAL123,1.0.0.0'
    """
    return self.query("*IDN?")

reset

reset() -> None

Reset oscilloscope to default settings.

Note: This may take several seconds to complete.

Source code in scpi_control/oscilloscope.py
def reset(self) -> None:
    """Reset oscilloscope to default settings.

    Note: This may take several seconds to complete.
    """
    logger.info("Resetting oscilloscope to defaults")
    self.write("*RST")

clear_status

clear_status() -> None

Clear status registers.

Source code in scpi_control/oscilloscope.py
def clear_status(self) -> None:
    """Clear status registers."""
    self.write("*CLS")

get_error

get_error() -> str

Get the last error from the error queue.

Returns:

Type Description
str

Error string (format: "code,description")

Source code in scpi_control/oscilloscope.py
def get_error(self) -> str:
    """Get the last error from the error queue.

    Returns:
        Error string (format: "code,description")
    """
    return self.query("SYST:ERR?")

wait_complete

wait_complete() -> None

Wait for all pending operations to complete.

Source code in scpi_control/oscilloscope.py
def wait_complete(self) -> None:
    """Wait for all pending operations to complete."""
    self.query("*OPC?")

trigger_single

trigger_single() -> None

Set trigger mode to single and force a trigger.

Source code in scpi_control/oscilloscope.py
def trigger_single(self) -> None:
    """Set trigger mode to single and force a trigger."""
    self.write("TRIG_MODE SINGLE")
    self.write("ARM")

trigger_force

trigger_force() -> None

Force a trigger event.

Source code in scpi_control/oscilloscope.py
def trigger_force(self) -> None:
    """Force a trigger event."""
    self.write("FRTR")

run

run() -> None

Start acquisition (set to AUTO trigger mode).

Source code in scpi_control/oscilloscope.py
def run(self) -> None:
    """Start acquisition (set to AUTO trigger mode)."""
    self.write("TRIG_MODE AUTO")

stop

stop() -> None

Stop acquisition.

Source code in scpi_control/oscilloscope.py
def stop(self) -> None:
    """Stop acquisition."""
    self.write("STOP")

set_timebase

set_timebase(seconds_per_div: float) -> None

Set timebase (alias for timebase setter).

Source code in scpi_control/oscilloscope.py
def set_timebase(self, seconds_per_div: float) -> None:
    """Set timebase (alias for timebase setter)."""
    self.timebase = seconds_per_div

auto_setup

auto_setup() -> None

Perform automatic setup.

Source code in scpi_control/oscilloscope.py
def auto_setup(self) -> None:
    """Perform automatic setup."""
    self.write("ASET")

get_waveform

get_waveform(channel: int) -> WaveformData

Acquire waveform data from a channel.

Convenience method that calls waveform.acquire().

Parameters:

Name Type Description Default
channel int

Channel number (1-4)

required

Returns:

Type Description
WaveformData

WaveformData object with time and voltage arrays

Source code in scpi_control/oscilloscope.py
def get_waveform(self, channel: int) -> WaveformData:
    """Acquire waveform data from a channel.

    Convenience method that calls waveform.acquire().

    Args:
        channel: Channel number (1-4)

    Returns:
        WaveformData object with time and voltage arrays
    """
    return self.waveform.acquire(channel)

get_channel

get_channel(channel_num: int) -> Optional[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
def get_channel(self, channel_num: int) -> Optional[Channel]:
    """Get channel object by number.

    Args:
        channel_num: Channel number (1-based)

    Returns:
        Channel object or None if channel doesn't exist

    Example:
        >>> scope.connect()
        >>> ch1 = scope.get_channel(1)
    """
    channel_attr = f"channel{channel_num}"
    return getattr(self, channel_attr, None)

See Also

  • 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