This repository contains the code to configure oscilloscopes, signal generators, DC Power-supplies and other measurement devices.
It provides following functionality:
- Establishing a network connection and identifying the different types of devices
- Execution of VISA commands on the devices. E.g. setting the voltage on a DC power-supply, Setting voltage limits on SMUs or to gather the current data of an oscilloscope
- CSV export function to directly store the output of measure devices in an *.csv file.
- Environment to set up test cases, configured by an XML file.
- Platform independent implementation (tested on Windows, MAC OS and Ubuntu)
Supported Devices
- SPD1305X DC Power Supply
- Keysight 33500B Waveform Generator
- Keysight InfiniiVision 3000A X-Series Oscilloscopes
- Tektronix 2600B Series SMU
Continuous integration
OS | Status |
Windows Latest | |
Mac OS Latest | |
Ubuntu Latest | |
Documentation
See https://florianfrank.github.io/instrument_control_lib/index.html for an overview of all available operations and further documentation. This documentation is built automatically, so it is always up to date.
Build
1. Build from master branch
1.1 Checkout repository
git clone git@github.com:FlorianFrank/instrument_control_lib.git
1.2 Configure build
Adjust the configuration files according to your needs.
option(INSTRUMENT_LIB_BUILD_STATIC "Build instrument lib as static library" ON)
# Definitions for the platform independent abstraction layer.
option(PIL_COMMUNICATION "Enable PIL Sockets" ON)
option(PIL_THREADING "Enable PIL Threads" ON)
option(PIL_LOGGING "Enable Logging support" ON)
option(PIL_SHARED "BUILD PIL as shared library" OFF)
option(PIL_STATIC "BUILD PIL as static library" ON)
option(PIL_CXX "Enable PIL C++ support" ON)
# PugiXML options
option(BUILD_SHARED_LIBS "Build pugiXML as shared lib" OFF)
set(PUGI_XML_VERSION 1.12)
1.3 Build the library
On Linux and MAC OS run:
On Windows run:
1.4 Exporting the library
You can find the library in the build folder.
out
├── include Here you can find the device and include fines for the project
├── ĺib Here you can find the libraries to link to your project.
├── bin In this folder you can find sample test programs, like a command line interface.
├── doc This folder contains the doxygen documentation.
2. Download pre-installed packages
2.1 Download a released version from github.
Go to:
Instrument Control Packages and download the preferred version.
2.2 Install the package
2.2.1 On Debian based systems
Execute:
dpkg -i instrument_control_lib.deb
The files are copied into the **/usr/bin, /usr/lib/,** and **/usr/include** folders and can be linked and included in any program.
2.2.2 On Windows systems
Run the graphical installer.
2.2.3 On MAC OS systems
Run the graphical installer.
Examples
See the examples directory for samples on how to use this lib with C++ and with Python.
Connect to devices
{c++}
#include "kst33500.h" // include right device header file
int main() {
// provide a IP address, some devices may need an extra port parameter
KST33500 k("xx.xx.xx.xx", <timeout>);
k.Connect();
}
Development
In this lab, we use sockets to send SCPI commands to devices in order control them remotely.
Check the documents in Docs for SCPI commands.
Basically, you can run any commands using Exec commands. For saving time, we wrapped some frequently used commands. But we cannot wrap all the commands.
Here is an instruction for wrapping a command. Let's say you want to wrap a command of Keysight waveform generator:
{c++}
FUNCtion <function>
which sets a <function> waveform.
Go to kst33500.h file and add a function signature called "function".
{c++}
int function(string fun);
Go to kst33500.cpp file and add the implementation of this function. What you need to do is making an SCPI command and invoke the Exec function.
{c++}
int KST33500::function(string fun) {
string msg = "FUNCtion " + fun;
Exec(msg);
return 0;
}
That's it. After that, you can use it like this:
Tutorial Python interface
Easy installation with pip.
Execute pip install .
in the root directory to install the instrument control lib for the current python installation. You can now just import py_instrument_control_lib and use it just like the C++ lib. With the pip installer the lib now supports autocompletion and type hints.
- Open the python console
- Make sure you installed the lib using pip
- Open the library as module
- Create a SMU object with an IP and an timeout for the socket
- Connect to the SMU
- You can check the error code which should be ERROR_CODE.NO_ERROR
- All defined error codes are listed below
$ python3
>>> from py_instrument_control_lib import *
>>> smu = KEI2600("192.168.1.10", 2000, SEND_METHOD.DIRECT_SEND)
>>> error_code = smu.connect()
>>> print(error_code)
ERROR_CODE.NO_ERROR
>>> device_identifier = smu.getDeviceIdentifier()
>>> print(device_identifier)
Keithley Instruments Inc*, Model 2636B, 4031
>>> error_code = smu.setLevel(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, 3.3, False)
>>> if error_code != ERROR_CODE.NO_ERROR:
pass # stop execution or do some error handling
>>> error_code = smu.setLimit(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, 5.0, False)
>>> # error handling
>>> error_code = smu.turnOn(SMU_CHANNEL.CHANNEL_A, False)
>>> # error handling
>>> measure_value = smu.measure(SMU_UNIT.CURRENT, SMU_CHANNEL.CHANNEL_B, False)
>>> print(measure_value)
3.04
>>> smu.disconnect()
Functions
This list gives an overview of the smu functions and how to call them.
# Establish the connection to the device
error_code = smu.connect()
error_code = smu.disconnect()
error_code = smu.turnOn(SMU_CHANNEL.CHANNEL_A, False)
error_code = smu.turnOff(SMU_CHANNEL.CHANNEL_A, False)
value = smu.measure(SMU_UNIT.CURRENT, SMU_CHANNEL.CHANNEL_A, False)
value = smu.measure(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, False)
value = smu.measure(SMU_UNIT.RESISTANCE, SMU_CHANNEL.CHANNEL_A, False)
value = smu.measure(SMU_UNIT.POWER, SMU_CHANNEL.CHANNEL_A, False)
error_code = smu.setLevel(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, 3.3, False)
error_code = smu.setLevel(SMU_UNIT.CURRENT, SMU_CHANNEL.CHANNEL_A, 0.1, False)
error_code = smu.setLimit(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, 3.3, False)
error_code = smu.setLimit(SMU_UNIT.CURRENT, SMU_CHANNEL.CHANNEL_A, 0.1, False)
error_code = smu.enableMeasureAutoRange(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, False)
error_code = smu.enableMeasureAutoRange(SMU_UNIT.CURRENT, SMU_CHANNEL.CHANNEL_A, False)
error_code = smu.disableMeasureAutoRange(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, False)
error_code = smu.disableMeasureAutoRange(SMU_UNIT.CURRENT, SMU_CHANNEL.CHANNEL_A, False)
error_code = smu.enableSourceAutoRange(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, False)
error_code = smu.enableSourceeAutoRange(SMU_UNIT.CURRENT, SMU_CHANNEL.CHANNEL_A, False)
error_code = smu.disableSourceAutoRange(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, False)
error_code = smu.disableSourceAutoRange(SMU_UNIT.CURRENT, SMU_CHANNEL.CHANNEL_A, False)
smu.setSenseMode(SMU_CHANNEL.CHANNEL_A, SMU_SENSE.LOCAL, False)
error_code = smu.setSourceRange(SMU_UNIT.VOLTAGE, SMU_CHANNEL.CHANNEL_A, 3.0, False)
device_description = smu.getDeviceIdentifier()
Error codes
There is a function which transforms the error codes into Strings. Some error codes are not used in the library because these are derived from the abstraction library. This function will be implemented in python soon!
# No error occurred
NO_ERROR
# Invalid arguments passed to a function, e.g. passing a nullptr.
PIL_INVALID_ARGUMENT
# An error occured and an errno error code was set.
# Internal error message can be requested by the error handle
ERRNO
# Error when performing an operation on a closed interface.
INTERFACE_CLOSED
# Error when baudrate cannot be set. E.g. when the approximation function has a higher deviation then 2 %.
INVALID_BAUDRATE
# Error insufficient resources.
INSUFFICIENT_RESOURCES
# Error, insufficient permissions to perform a certain operation.
INSUFFICIENT_PERMISSIONS
# Error, when deadlock is detected in a multithreaded application.
DEADLOCK_DETECTED
# Error while joining a thread.
THREAD_NOT_JOINABLE
# Error performing an operation on on a not initialized thread.
THREAD_NOT_FOUND
# Error entire file could not be written.
ONLY_PARTIALLY_READ_WRITTEN
# Error no such file or directory.
NO_SUCH_FILE
# Invalid error code.
UNKNOWN_ERROR
# Error while parsing an XML file.
XML_PARSING_ERROR