Tektronix Technical Forums are maintained by community involvement. Feel free to post questions or respond to questions by other members. Should you require a time-sensitive answer, please contact your local Tektronix support center here.

Python: MDO Simple Plot

Programming examples for remote communication with instruments
C/C++, C#, Python, Matlab, LabVIEW
Post Reply
Carl M
Tektronix Applications
Tektronix Applications
Posts: 801
Joined: July 30th, 2008, 4:45 pm
Country: United States

Python: MDO Simple Plot

Post by Carl M » June 28th, 2016, 6:03 pm

This example supersedes the Python Example: Get and Plot Waveform DPO4000.

This code example provides meaningful output (i.e. a scaled waveform plot) as simply as possible without bad practices. It is useful for testing the installation and configuration of a Python environment for development of remote instrument control code. It demonstrates best practice event status checking, command synchronization, waveform acquisition, waveform data transfer, waveform scaling, and waveform plotting using Python 3.5 and PyVISA v1.8 and Matplotlib v1.5.1. Default setup and auto-set are compromises for convenience. Because the exercised features are fairly universal to Tektronix oscilloscopes, this example should work across a wide range of models without any modification.

For TDS2k, TPS2k, and TBS1k series oscilloscopes, see Python: TBS Simple Plot

Code: Select all

# mdo simple plot
# python v3.8.3, pyvisa v1.10.1
# should work with MSO70k, DPO7k, MSO5k, MDO4k, MDO3k, and MSO2k series
# 5/6 Series MSO 

# incompatible with TDS2k and TBS1k series (see tbs simple plot)

import time # std module
import visa # http://github.com/hgrecco/pyvisa
import matplotlib.pyplot as plt # http://matplotlib.org/
import numpy as np # http://www.numpy.org/

visa_address = 'tcpip::10.2.1.130::instr'

rm = visa.ResourceManager()
scope = rm.open_resource(visa_address)
scope.timeout = 10000 # ms
scope.encoding = 'latin_1'
scope.read_termination = '\n'
scope.write_termination = None
scope.write('*cls') # clear ESR
scope.write('header OFF') # disable attribute echo in replies

print(scope.query('*idn?'))

# prompt
input("""
ACTION:
Connect probe to oscilloscope Channel 1 and the probe compensation signal.

Press Enter to continue...
""")

# default setup
scope.write('*rst')
t1 = time.perf_counter()
r = scope.query('*opc?') # sync
t2 = time.perf_counter()
print('reset time: {}'.format(t2 - t1))

# autoset
scope.write('autoset EXECUTE')
t3 = time.perf_counter()
r = scope.query('*opc?')
t4 = time.perf_counter()
print('autoset time: {} s'.format(t4 - t3))

# acquisition
scope.write('acquire:state OFF') # stop
scope.write('acquire:stopafter SEQUENCE;state ON') # single
t5 = time.perf_counter()
r = scope.query('*opc?')
t6 = time.perf_counter()
print('acquire time: {} s'.format(t6 - t5))

# curve configuration
scope.write('data:encdg SRIBINARY') # signed integer
scope.write('data:source CH1')
scope.write('data:start 1')
acq_record = int(scope.query('horizontal:recordlength?'))
scope.write('data:stop {}'.format(acq_record))
scope.write('wfmoutpre:byt_n 1') # 1 byte per sample

# data query
t7 = time.perf_counter()
bin_wave = scope.query_binary_values('curve?', datatype='b', container=np.array)
t8 = time.perf_counter()
print('transfer time: {} s'.format(t8 - t7))

# retrieve scaling factors
wfm_record = int(scope.query('wfmoutpre:nr_pt?'))
pre_trig_record = int(scope.query('wfmoutpre:pt_off?'))
t_scale = float(scope.query('wfmoutpre:xincr?'))
t_sub = float(scope.query('wfmoutpre:xzero?')) # sub-sample trigger correction
v_scale = float(scope.query('wfmoutpre:ymult?')) # volts / level
v_off = float(scope.query('wfmoutpre:yzero?')) # reference voltage
v_pos = float(scope.query('wfmoutpre:yoff?')) # reference position (level)

# error checking
r = int(scope.query('*esr?'))
print('event status register: 0b{:08b}'.format(r))
r = scope.query('allev?').strip()
print('all event messages: {}'.format(r))

# disconnect
scope.close()
rm.close()

# create scaled vectors
# horizontal (time)
total_time = t_scale * wfm_record
t_start = (-pre_trig_record * t_scale) + t_sub
t_stop = t_start + total_time
scaled_time = np.linspace(t_start, t_stop, num=wfm_record, endpoint=False)
# vertical (voltage)
unscaled_wave = np.array(bin_wave, dtype='double') # data type conversion
scaled_wave = (unscaled_wave - v_pos) * v_scale + v_off

# plotting
plt.plot(scaled_time, scaled_wave)
plt.title('channel 1') # plot label
plt.xlabel('time (seconds)') # x label
plt.ylabel('voltage (volts)') # y label
print("look for plot window...")
plt.show()

print("\nend of demonstration")
Please discuss.
Tektronix Application Engineer

Carl M
Tektronix Applications
Tektronix Applications
Posts: 801
Joined: July 30th, 2008, 4:45 pm
Country: United States

Re: Python: MDO Simple Plot

Post by Carl M » May 31st, 2017, 11:17 am

i've made a small update. immediately after creating the instrument object (which implicitly connects) the default parameters work but aren't technically correct.

Code: Select all

scope.encoding = 'latin_1' # default 'ascii'
scope.read_termination = '\n' # default None
scope.write_termination = None # default '\r\n'
i also moved '*CLS' up to be the first command. writing *CLS to the instrument immediately after connecting prevents any cached events or messages causing inconsistent behavior.
Tektronix Application Engineer

Carl M
Tektronix Applications
Tektronix Applications
Posts: 801
Joined: July 30th, 2008, 4:45 pm
Country: United States

Re: Python: MDO Simple Plot

Post by Carl M » August 28th, 2018, 11:25 am

updates to record length detection and data encoding. tested with 5 and 6 series MSOs.

Code: Select all

'data:encoding SRIBINARY' for signed little endian dac values
FASTEST is depreciated, encoding has trivial impact on performance

record length now queried from 'horizontal:recordlength', not 'wfmoutpre:nr_pt'
wfmoutpre:nr_pt is (data:stop - data:start +1) and not a good indicator of record length setting
Tektronix Application Engineer

Carl M
Tektronix Applications
Tektronix Applications
Posts: 801
Joined: July 30th, 2008, 4:45 pm
Country: United States

Re: Python: MDO Simple Plot

Post by Carl M » July 28th, 2020, 11:14 am

corrected a time scale offset on certain models. :oops:
changed some variable names and adjusted order to improve flow and readability.
Tektronix Application Engineer

Post Reply

Return to “Remote Instrument Communication (Programming) Examples”

Who is online

Users browsing this forum: No registered users and 1 guest