MSO#
The MSO
class is the main interface for interacting with a Saleae Logic MSO device. It provides methods for capturing data and managing device settings.
Overview#
The MSO
class handles:
Device connection and initialization
Analog capture operations
Device configuration and settings
Classes#
MSO
#
class MSO:
def __init__(self, serial_number: Optional[str] = None)
Parameters:
serial_number
: Optional serial number to connect to a specific device. If not provided, connects to the first available device.
Properties:
part_number
: The Saleae Part Number for the attached MSO. Supplies information like maximum sample rates and buffer sizes.
Methods#
MSO.capture()
#
def capture(self,
capture_config: mso_api.CaptureConfig,
save_dir: pathlib.Path,
timeout_secs: Optional[float] = None) -> mso_api.Capture
Captures data from the device according to the specified configuration.
Parameters:
capture_config
: Configuration for the capture (channels, sample rate, etc.)save_dir
: Directory to save capture datatimeout_secs
: Optional timeout for the capture operation
Returns:
A
Capture
object containing the captured data
Note: This method will:
Create the save directory if it doesn’t exist
Save the record options to
record_options.json
Execute the capture command
Save the record result to
record_result.json
Load the captured data into a
Capture
object
Example Usage:
from pathlib import Path
from saleae.mso_api import MSO, CaptureConfig, AnalogChannel, AnalogSettings, TimedCapture
# Initialize the MSO
mso = MSO()
# Configure the capture
config = CaptureConfig(
enabled_channels=[AnalogChannel(channel=0, name="clock")],
analog_settings=AnalogSettings(sample_rate=100e6),
capture_settings=TimedCapture(capture_length_seconds=0.1),
)
# Perform the capture
save_dir = Path("my-capture")
capture = mso.capture(config, save_dir=save_dir)
# Access the captured data and inspect the actual (effective) capture settings
print(f"Captured {capture.analog_data['clock'].num_samples} samples at a "
f"{capture.config.analog_settings.sample_rate/1e6:.1f} MHz sample rate")
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[1], line 16
14 # Perform the capture
15 save_dir = Path("my-capture")
---> 16 capture = mso.capture(config, save_dir=save_dir)
18 # Access the captured data and inspect the actual (effective) capture settings
19 print(f"Captured {capture.analog_data['clock'].num_samples} samples at a "
20 f"{capture.config.analog_settings.sample_rate/1e6:.1f} MHz sample rate")
File ~\src\mso-api\src\saleae\mso_api\mso_device.py:103, in MSO.capture(self, capture_config, save_dir, timeout_secs, debug)
100 record_traceback(save_dir, self.wrapper.last_stdout or "", exception_tb, exception)
102 # read the data into numpy arrays
--> 103 return Capture.from_config(capture_config, save_dir)
File ~\src\mso-api\src\saleae\mso_api\capture.py:506, in Capture.from_config(cls, config, dir_path)
502 """
503 Create a Capture from a CaptureConfig by reading the files in it's save directory
504 """
505 dir_path = Path(dir_path)
--> 506 capture_obj = Capture.from_dir(dir_path)
508 # TODO: do some sanity checking comparing the recovered config with the provided config
510 capture_obj.config = copy.deepcopy(config)
File ~\src\mso-api\src\saleae\mso_api\capture.py:497, in Capture.from_dir(cls, dir_path)
490 capture_obj = cls(
491 analog_data={},
492 digital_data={},
493 config=config,
494 _stored_path=dir_path,
495 )
496 # load the data from the files
--> 497 capture_obj._load_data_from_located_files(located_files)
498 return capture_obj
File ~\src\mso-api\src\saleae\mso_api\capture.py:460, in Capture._load_data_from_located_files(self, located_files)
458 for located_file in located_files:
459 if isinstance(located_file.channel_config, AnalogChannel):
--> 460 self._load_analog_data_file(located_file)
461 elif isinstance(located_file.channel_config, DigitalChannel):
462 self._load_digital_data_file(located_file)
File ~\src\mso-api\src\saleae\mso_api\capture.py:309, in Capture._load_analog_data_file(self, located_file)
307 self._load_analog_data_file_v0(located_file, parsed_file.contents)
308 elif isinstance(parsed_file.contents, binary_files.AnalogExport_V1):
--> 309 self._load_analog_data_file_v1(located_file, parsed_file.contents)
310 else:
311 raise NotImplementedError("Only AnalogExport_V0 and AnalogExport_V1 are supported at this time")
File ~\src\mso-api\src\saleae\mso_api\capture.py:348, in Capture._load_analog_data_file_v1(self, located_file, contents)
346 # TODO: update the epsilon on this check if/when export sample rate starts being defined as a double
347 elif abs(self.config.analog_settings.sample_rate - float(contents.waveforms[0].sample_rate)) > 1.0:
--> 348 raise ValueError(f"Inconsistent sample rates: {self.config.analog_settings.sample_rate} vs {contents.waveforms[0].sample_rate}")
350 # track start time
351 if self._analog_start_time is None:
ValueError: Inconsistent sample rates: 100000000.0 vs 125000000.0
Error Handling#
The MSO
class can raise the following exceptions, which are all subclasses of MsoApiError
:
CaptureTimeoutError
when capture operations timeoutMsoCommandError
when device commands otherwise failSmartCableNotReadyError
when a digital capture is initiated on a Smart Cable that’s not plugged inSaleaeCommsProcessError
when something has broken in the low-level communications layer, or the device has been unplugged from USB during a capture.
If either of these conditions arise, the directory you requested your capture to be saved in
will contain a file called traceback.txt
with debug information from your own program
as well as the underlying capture executable.
CaptureTimeoutError
#
class CaptureTimeoutError(MsoApiError):
def __init__(self, timeout_seconds: Optional[float] = None):
self.timeout_seconds = timeout_seconds
Exception raised when a capture operation times out. This can occur in two scenarios:
No trigger condition was found during a triggered capture
The actual capturing and uploading did not complete within the specified timeout period
If you’re running into a lot of these, try the following:
check that your trigger condition is actually occurring on the channel you’ve configured within the trigger timeout
consider increasing (or dropping) the overall command timeout (
timeout_secs
), as that includes upload time from the device.
Attributes:
timeout_seconds
: The timeout duration that was exceeded
MsoCommandError
#
class MsoCommandError(MsoApiError):
def __init__(self, command: str, stdout: str):
self.command = command
self.stdout = stdout
super().__init__(f"Command {command} failed, stdout was: {stdout}")
Exception raised when device commands otherwise fail.
Attributes:
command
: The command that failedstdout
: The stdout output from the command
SmartCableNotReadyError
#
class SmartCableNotReadyError(MsoApiError):
def __init__(self, command: str, stdout: str):
self.command = command
self.stdout = stdout
super().__init__(f"Smart cable was not connected or initialized in time. {command} failed, stdout was: {stdout}")
Exception raised when a smart cable is not ready or not connected. This typically occurs when:
The smart cable is not properly connected to the MSO device
The smart cable has not been initialized in time for the capture operation
There are communication issues with the smart cable hardware
Attributes:
command
: The command that failedstdout
: The stdout output from the command
Common Solutions:
Ensure the smart cable is properly connected to the MSO device
Try unplugging and replugging the smart cable
Verify that the smart cable is being detected by the system by opening Logic2 and attempting to capture data from it
SaleaeCommsProcessError
#
class SaleaeCommsProcessError(MsoApiError):
def __init__(self, args: list[str], stdout: str, stderr: str, returncode: int, env: Optional[dict[str, str]] = None):
self.msoexe_args = args
self.stdout = stdout
self.stderr = stderr
self.returncode = returncode
self.env = env
Exception raised when there are low-level communication issues with the MSO device. This typically occurs when:
The device is disconnected from USB during a capture operation
There are fundamental communication problems with the device
Attributes:
msoexe_args
: The command arguments that were passed to the MSO executablestdout
: The stdout output from the commandstderr
: The stderr output from the commandreturncode
: The return code from the MSO executableenv
: The environment variables used during execution
Note: If you encounter this error outside of obvious scenarios like disconnecting the USB cable during capture, please contact Saleae support with the error details and your system information. We’d like to get the problem fixed as soon as possible.