연락처

텍트로닉스 담당자와 실시간 상담 6:00am-4:30pm PST에 이용 가능

전화

전화 문의

9:00am-6:00PM KST에 이용 가능

다운로드

매뉴얼, 데이터 시트, 소프트웨어 등을 다운로드할 수 있습니다.

다운로드 유형
모델 또는 키워드

피드백

Blog

Control Test Measurement Devices with Python the Easy Way


Article Summary

This blog discusses the technical side of the Tektronix tm_devices package. It will cover some of the architecture design and decision-making process. The goal is to explain how tm_devices works and its advantages over other device control options.

Introduction

At Tektronix, we are constantly testing our products. This involves a lot of communication with each device we are testing, and we need a robust infrastructure to enable that. Over six years ago, we started working on an internal test framework that we could use to test our instruments. Fast forward to 2023, we realized that the core of the infrastructure, the device management code, could be useful to a wider audience. We decided to take that core device management framework and release it as an open-source Python package called tm_devices. We still use this infrastructure every day for testing, but now the basic device management framework is available for everyone to use.

          
from tm_devices import DeviceManager
with DeviceManager() as device_manager:
    scope = device_manager.add_scope("192.168.0.100")

    scope.query("*IDN?")

    print(scope)

What is tm_devices

Python is one of the most popular programming languages used today, and here at Tektronix we use it extensively. tm_devices is a Python package that provides a better interface for control and usage of test & measurement devices within Python code. It acts as a higher-level abstraction on top of the existing PyVISA package that is used to manage connections and communication with VISA (Virtual Instrument Software Architecture) devices. This is achieved by providing Python drivers (in the form of a Python class) for each device. This framework is also completely cross-platform and is tested thoroughly on the three major operating systems: Windows, MacOS and Linux. In addition to being cross-platform, the code will also run across multiple versions of Python. At the time of writing this, tm_devices supports Python 3.8+. Plus, when writing Python code using a modern integrated development environment (IDE) such as VSCode or PyCharm, you will get autocomplete and type hinting, helping you to write code that avoids issues before you execute any scripts.

One of the great things about this package is that when you install it, it comes ready to use. It requires no external dependencies to connect and control a device. However, if you want to use a specific VISA backend, it will work with that, too. Using this package will allow you to connect to VISA devices using a TCPIP, USBTMC, SOCKET, Serial or even GPIB connection. See the official documentation for the full list of supported connection types and interfaces. The complete list of supported devices is also available in the official documentation. A few of the notable supported devices are Tektronix 2, 4, 5 and 6 Series Mixed Signal Oscilloscopes as well as a handful of Keithley source measure units (SMUs). The types of devices currently supported are arbitrary function generators (AFGs), arbitrary waveform generators (AWGs), oscilloscopes, power supply units (PSUs), source measure units (SMUs), Tektronix Margin Tester, digital multimeters (DMMs), digital acquisition systems (DAQs) and system switches.
The online documentation provides plenty of example code and helpful troubleshooting information, as well as a complete API (application programming interface) reference guide for the entire package. This Python API includes a one-to-one mapping of VISA instrument commands directly to Python code. No more using strings for commands! The models with this extra API support are noted on the main page of the documentation, and support for additional models is planned.

tm_devices Architecture

The backbone of the entire tm_devices architecture is the DeviceManager class. The DeviceManager is the first thing that you will need to instantiate as it handles connecting to each device that you want to control. The DeviceManager uses a configuration parser to read a configuration file or environment variable to determine with which device to connect. This configuration contains the device type (e.g., SCOPE, AFG, SMU) as well as the address (e.g., hostname, IP address, model and serial number for USBTMC). The config parser also reads in optional configuration settings that apply globally, such as turning on verbose VISA logging. The DeviceManager then connects to all the devices that the config parser has listed and provides access to the Python driver for each device. The Python device driver is the class responsible for actual communication with the physical (or virtual) device.

 

A block diagram showing that the Device Manager class contains 0 to n device driver classes and uses one DMConfigParser class.

 

Figure 1: DeviceManager architecture block diagram.

Python Driver Classes

The drivers are the biggest part of the package; each unique series of instrument gets a uniquely named Python driver class. These classes are implemented using object-oriented programming principles and make extensive use of inheritance. This allows common attributes and methods to be defined in higher-level, abstract classes that are then inherited by the individual driver classes. More updates to the drivers are being added, with a lot of the new features being inherited via mixin classes. This allows multiple device types to all inherit from the same abstract base class without sharing the same inheritance tree (since they might not share much else). The mixin classes define attributes and methods, some of which the driver will overwrite or implement for itself.

All these object-oriented principles cumulate in individual driver classes that are quite simple to read, as they have very few actual lines of code. One other technique to reuse code in the drivers is creating what we call a “family base class”. Each family base class is an abstract class that defines the signature for all child classes that inherit from it. Occasionally a child class will need to overwrite an implementation, but this means that all drivers that inherit from a common family base class will have the same class signature (attributes, methods, etc.). These object-oriented design principles mean that code duplication is extremely low, and drivers are easy to create and update.

Python Package Support, Maintenance, New Drivers and More

This package is in constant use by us here at Tektronix, so we are fully invested in improving it. This will include things like code restructuring and refactoring to make contributing easier. As we have watched the package mature, we have seen mixin classes become more valuable and would like to start using them more. We will also be enhancing support for existing devices by updating drivers and the corresponding one-to-one command APIs. And, of course, as new devices are released, drivers for controlling them will be added to tm_devices.

Conclusion

tm_devices is one of the best instrument control Python packages available today. It supports over 90 different instrument series via unique Python drivers, is cross-platform, supports multiple versions of Python and integrates seamlessly with modern integrated development environments. 

Visit the GitHub page to provide feedback, view any current open issues and/or participate in discussions. If you’re especially interested, feel free to fork the repo and submit a Pull Request with a contribution of your own!