SCPI Python examples
Preconditions
Before running the examples start the SCPI server, verify and adapt the IP-address and the port number in the python code. The connection to the SCPI server can be verified using NI MAX.
The PyVISA package for the VISA communication must be added to the used Python projects. The currently used version ist the 1.11.3.
Connection test
This examples shows how to:
- build a connection with a SCPI server (i.e. the one provided by Bode 100)
- test the connection with the SCPI server
# use pyvisa or similar package
import pyvisa
# *** TO DO: adapt IP address and SCPI port according to your needs ***
SCPI_server_IP = '172.22.44.29'
SCPI_Port = '5025'
VISA_resource_name = 'TCPIP::' + SCPI_server_IP + '::' + SCPI_Port + '::SOCKET'
print('Trying to connect to VISA resource: ' + VISA_resource_name)
visaSession = pyvisa.ResourceManager().open_resource(VISA_resource_name)
visaSession.read_termination = '\n'
print('SCPI client connected to SCPI server: ' + visaSession.query("*IDN?"))
Define and execute a sweep measurement and display the results
This examples shows how to:
- build a connection with a SCPI server (i.e. the one provided by Bode 100)
- parametrize a measurement sweep defining start and stop frequencies, number of measurement points a.s.o.
- execute the measurement also in a loop in order to implement a continuous sweep
- retrieve and handle measurement data
This example also shows a case of trigger handling for measurement on demand:
- Step 1. Use the :INIT:CONT command to turn on continuous initiation mode for the a channel.
- Step 2. Issue the :TRIG:SOUR command to set the trigger source to “Bus Trigger”.
- Step 3. Trigger the instrument at any time you want to perform measurement. :TRIG:SING this should be followed by a *OPC? command
- Step 4. To start the next measurement cycle, repeat step 3.
For more information about the trigger handling please have a look at the trigger system page.
# use pyvisa or similar package
import pyvisa
import time
# *** TO DO: adapt IP address and SCPI port according to your needs ***
SCPI_server_IP = '10.0.0.42'
SCPI_Port = '5025'
SCPI_timeout = 20000 # milliseconds
VISA_resource_name = 'TCPIP::' + SCPI_server_IP + '::' + SCPI_Port + '::SOCKET'
# Start and Stop frequencies can be set either as strings or as double. In the latter case a conversion to string will be required before assemblying the SCPI command using them
# if the values are entered as numbers then the "." (dot) shall be used as decimal separator.
# Alternative: entering the values as string e.g. '10MAHz' no coversion to string shall be used building the SCPI command later on
Start_frequency = '10kHz'
Stop_frequency = 10000000.0
Number_of_measurement_points = 201 # the minimum amount of measurement points is 2!
Sweep_type = 'LOG'
Receiver_bandwidth = '300Hz'
def Init():
start_time = time.time()
print(
'Trying to connect to VISA resource: ' + VISA_resource_name +
'. Be sure that IP address and port number are correct!')
visaSession = pyvisa.ResourceManager().open_resource(VISA_resource_name)
visaSession.timeout = SCPI_timeout
visaSession.read_termination = '\n'
print('SCPI client connected to SCPI server: ' + visaSession.query("*IDN?"))
lockOk = visaSession.query(":SYST:LOCK:REQ?")
if lockOk != "1":
print("Locking was not successful, exiting!")
return
else:
print("Locking was successful!")
try:
### Here comes the measurement configuration data for measurement sweep
# Start_frequency is already string and doesn´t require any conversion
visaSession.write(':SENS:FREQ:STAR ' + Start_frequency)
# Stop_frequency is a number and must be converted to string
visaSession.write(':SENS:FREQ:STOP ' + str(Stop_frequency))
visaSession.write(':SENS:SWE:POIN ' + str(Number_of_measurement_points))
visaSession.write(':SENS:SWE:TYPE ' + Sweep_type)
visaSession.write(':SENS:BAND ' + Receiver_bandwidth)
# configuring 'one-port' impedance measurement
visaSession.write(':CALC:PAR:DEF Z')
# linear magnitude in Ohms + phase(deg)
visaSession.write(":CALC:FORM SLIN")
# Intializes trigger system to use BUS as source
visaSession.write(':TRIG:SOUR BUS')
# Sets the trigger in continous mode.
# This way after a measurement the trigges gets back in state "ready"
# and waits for a further measurement without being primed (command :INIT).
visaSession.write(':INIT:CONT ON')
visaSession.write(':TRIG:SING')
# This command waits for all pending operations to finish and afterwards returns an 1
visaSession.query('*OPC?')
# Query the measurement results
allResults = visaSession.query(":CALC:DATA:SDAT?")
frequencyValues = visaSession.query(":SENS:FREQ:DATA?")
# Magnitude and phase from the results are first coverted to a list of strings,
# then the list is converter to a FLOAT array)
allResults_list_raw = list(map(float, allResults.split(",")))
magnitude_raw = allResults_list_raw[0:Number_of_measurement_points]
phase_raw = allResults_list_raw[Number_of_measurement_points:len(allResults_list_raw)]
# Same procedure with frequency raw data to list and eventually to array
freq_list_raw = list(map(float, frequencyValues.split(",")))
# Printing just the first results of the measurement cycle as example
print("Frequency: " + str(freq_list_raw[0]) + " Hz;" + "\tMagnitude: "
+ str(magnitude_raw[0])
+ " Ω;" + "\tPhase: " + str(phase_raw[0]) + "°")
except:
print("Something went wrong - an error has occurred")
finally:
### At the end the device shall be released to be available for other programs/users
# It´s important that the releasing takes place even if an error occurred
# causing the program to exit unexpectedly
relOK = visaSession.query(':SYSTem:LOCK:RELease?')
visaSession.query('*OPC?')
if relOK != "1":
print("Releasing was not successful, check the availability of the device!")
return
else:
print("Releasing was successful!")
visaSession.close()
print()
print("---Measurement time: %s seconds ---" % (time.time() - start_time))
if __name__ == "__main__":
Init()
Define and execute a single frequency measurement and display the results
This examples shows how to:
- build a connection with a SCPI server (i.e. the one provided by Bode 100)
- parametrize a single frequency measurement defining the used frequency
- execute the measurement also in a loop in order to implement a continuous sweep
- retrieve and handle measurement data
This example also shows a case of trigger handling for single measurement. For a further measurement the trigger shall be primed again with :INIT:
- Step 1. Use the :INIT command to turn on single initiation mode for a channel.
- Step 2. Issue the :TRIG:SOUR command to set the trigger source to “Bus Trigger”.
- Step 3. Trigger the instrument once to perform measurement. :TRIG:SING this should be followed by a *OPC? command
- Step 4. To start the next measurement, repeat step 3.
For more information about the trigger handling please have a look at the trigger system page.
# use pyvisa or similar package
import pyvisa
import time
# *** TO DO: adapt IP address and SCPI port according to your needs ***
SCPI_server_IP = '10.0.0.42'
SCPI_Port = '5025'
SCPI_timeout = 20000 # milliseconds
VISA_resource_name = 'TCPIP::' + SCPI_server_IP + '::' + SCPI_Port + '::SOCKET'
# Start and Stop frequencies can be set either as strings or as double. In the latter case a conversion to string will be required before assemblying the SCPI command using them
# if the values are entered as numbers then the "." (dot) shall be used as decimal separator.
# Alternative: entering the values as string e.g. '10MAHz' no coversion to string shall be used building the SCPI command later on
Start_frequency = '10kHz'
Receiver_bandwidth = '300Hz'
def Init():
start_time = time.time()
print('Trying to connect to VISA resource: ' + VISA_resource_name + '. Be sure that IP address and port number are correct!')
visaSession = pyvisa.ResourceManager().open_resource(VISA_resource_name)
visaSession.timeout = SCPI_timeout
visaSession.read_termination = '\n'
print('SCPI client connected to SCPI server: ' + visaSession.query("*IDN?"))
lockOk = visaSession.query(":SYST:LOCK:REQ?")
if lockOk != "1":
print("Locking was not successful, exiting!")
return
else:
print("Locking was successful!")
try:
# A try/except/finally block is used in order to execute the release
# at the end in any case
# Here comes the measurement configuration data for measurement sweep
# Start_frequency is already string and doesn´t require any conversion
visaSession.write(':SENS:FREQ:STAR ' + Start_frequency)
visaSession.write(':SENS:SWE:POIN ' + str(1))
visaSession.write(':SENS:BAND ' + Receiver_bandwidth)
# configuring 'one-port' impedance measurement
visaSession.write(':CALC:PAR:DEF Z')
# linear magnitude in Ohms + phase(deg)
visaSession.write(":CALC:FORM SLIN")
# Intializes trigger system to use BUS as source
visaSession.write(':TRIG:SOUR BUS')
# Primes the trigger setting it into "Wait" and after a :TRIG command
# the measurement starts
# To perform a further measurement the trigger must be primed again with :INIT
visaSession.write(':INIT')
visaSession.write(':TRIG:SING')
# *OPC? waits for all pending operations to finish and afterwards returns an 1
visaSession.query('*OPC?')
# Read the results
allResults = visaSession.query(":CALC:DATA:SDAT?")
frequencyValues = visaSession.query(":SENS:FREQ:DATA?")
# Magnitude and phase from the results (first to a list, then to a FLOAT array)
# A single frequency result is complex and contains both magnitude and phase
allResults_list_raw = list(map(float, allResults.split(",")))
magnitude_raw = allResults_list_raw[0]
phase_raw = allResults_list_raw[1]
# Frequency raw data to list
freq_list_raw = list(map(float, frequencyValues.split(",")))
# Printing just the results of the measurement
print("Frequency: " + str(frequencyValues) + " Hz;" + "\tMagnitude: "
+ str(magnitude_raw) + " Ω;" + "\tPhase: " + str(phase_raw) + "°")
except:
print ("Something went wrong with the measurement")
finally:
### At the end the device shall be released to be available for other programs/users
# It´s important that the releasing takes place even if an error occurred
# causing the program to exit unexpectedly
relOK= visaSession.query(':SYSTem:LOCK:RELease?')
visaSession.query('*OPC?')
if relOK != "1":
print("Releasing was not successful, check the availability of the device!")
return
else:
print("Releasing was successful!")
visaSession.close()
print()
print("---Measurement time: %s seconds ---" % (time.time() - start_time))
if __name__ == "__main__":
Init()