Topics

OT: I/V curve tracing made easy with Python and PyVISA

Albert Otten
 

Hi Tony,

It looks like you didn't find the necessary documentation?
Always have a look at the Tekwiki website. All you need is there, both for 2465 (+ options) and WR P6407.
As said by Harvey White a.o. in another thread there is no special software needed for the P6407.
If you like, the settings for WR can also be done via GPIB. Appendix A of the WR operators manual lists the additional GPIB commands for the WR.
Chuck Harris gave his opinion about using GPIB for this scope -- it's rather useless. It's nice to see that GPIB works and that you can download single measurement values, but the real advantage would be that you can transfer waveforms or screen images to a PC which isn't possible with this analog scope.

Albert

On Fri, May 17, 2019 at 10:23 PM, Tony Fleming wrote:


I purchased couple weeks ago the P6407 stuff, but it has no manual or any
instructions - I must find that information and print it....

Harvey White
 

On 5/17/2019 11:48 AM, magnustoelle via Groups.Io wrote:
Good Day,

thank you for your kind comments, Gentlemen. And thank you for that weblink and the German figure of speech, Albert! :-)

The trouble is that I am looking at my Keithley 230 programmable voltage source and the Keithley type 195 DMM (with its 100pA resolution)  at the shelves right behind my back right now. Both are equipped with GPIB, but I have never done much with either device yet - and they keep staring at me.
Looking at this from a programming standpoint, you have (generally) measuring equipment and stimulus equipment.  Changing the any of the above that you don't have support for is a matter of looking at what you've told device A (which you have) what to do.  You don't want to know how you told it to do that, that's possibly specific to the instrument (depending on age).  Then you need to look at what you want device B to do.  You compare ranges and functions, and assuming you can live with what device "B" does....

You replace the specific instructions of device A with the specific instructions of device B.

For maximum utility, you devise a switch of some sort (programming switch, very much depends on the language how you do it), so that given choice 1, you produce instructions for device A, and for choice 2, you produce instructions for device B.

In C, C++, this can be done with #define, and #ifdef statements. In basic (haven't used it for years.... likely an "on...... value" statement.  For pascal, you use the case statement unless your version of pascal has the equivalent of #define.

The difference between #define related stuff and case/switch/on stuff is that the former contains only the code you want, and cannot do anything else unless you recompile it.  It is, however, smaller in size.

The latter has all the options, and makes the choice on the fly. You have unused code (for the nonce) , but you're ultimately more versatile at the cost of a bigger program.

Harvey



In combination with the FLUKE 8840A DMM, they might turn into a much better curve tracer setup than the mentioned Grundig Digimess PN300 alone. More to come!

Tot ziens,

Magnus

[..]
A basic introduction corresponding to what Magnus does in his script is
here for example:

https://www.edn.com/design/test-and-measurement/4441692/How-to-automate-measurements-with-Python
I tried Python successfully for command communication (both serial and
GPIB) with my CSA803 but only to verify that it is possible.
(Magnus, I guess "a lot of water has flown through the river Rhein" while
you composed that Python script ;-)

Albert





Tony Fleming
 

Thank you Albert for your nice reply!
Yes, I have options 1,9,10+GPIB on my 2465 DMS scope. I also have DMM
option on top of the scope!
I purchased couple weeks ago the P6407 stuff, but it has no manual or any
instructions - I must find that information and print it....
I'm not planing to use it for anything serious, just to demo the Tektronix
scope and the "old technology", when I do shows or visit clubs/libraries....
Many people find older stuff interesting and the kids in the schools do not
learn almost any history in electronics!
I also have couple older scopes, like Simpson Model 466 - Handiscope, not
oscilloscope.... but it is interesting to see peoples reaction when they
see it in person.
One of my dream was to have Tektronix and some kind of "old scope" that is
as old as I'm now! ha ha ha
About Arduino - it is lots of fun and now we are using Python also and or
ESP8266 or ESP32 - for few bucks you have input-output + sensors or Wi-Fi
.... You should have your son demo stuff for you!
I wish I had a dad like you, who is in electronics and "plugged in".... but
I had Mr. Helebrand who was like the perfect dad but teach me electronics!
(Back in early 70's)
Anyway, if you, or anyone else, find the software and instructions+manuals
.... I appreciate your input and help guys/gals!
Thank you all!

On Fri, May 17, 2019 at 3:02 PM Albert Otten <aodiversen@...> wrote:

Hi Tony,

Your 2465 doesn't have RS232, so you need a GPIB connection. Do you have
such already (NI GPIB-USB-HS, Prologix,...)? I have the NI adapter. Or are
you considering to use an Arduino (mentioned in your 2465 topic) for this?
I know nothing of Arduinos (except that my son is married with these tiny
things).
Tektronix had it's own version of NI-VISA, TekVISA, and a program
Wavestar. These could be downloaded for free I think for Windows. I tried
this once without much success and deleted it right away: together with NI
drivers a HUGE amount of software! I used Linux ever since with the
linux-gpib driver package. I don't know if the GPIB programs by Hakan (
http://www.hakanh.com/dl/index.htm) together with drivers can serve you.
In my opinion PiVISA is not of much interest for you. VISA is intended for
equipment that understands VISA commands. So you have to lookup in the
Opt.10 manual which commands are recognized by the 2465 and send these
commands exactly as shown in the manual. I have the same situation with my
7854 and CSAs.
At this moment I don't remember for sure whether drivers are still needed
if the Pivisa-py package is used, but I think the are. If not then PiVISA
is attractive. (Magnus knows?)
An alternative to PiVISA is to use the python package gpib_ctypes in
combination with the Linux linux-gpib package or the (Linux, Windows) NI
drivers.
The python script could look like this (note, I didn't test this since
some time, I hope I removed errors):

#!/usr/bin/python3

# test gpib connection with the CSA803
from gpib_ctypes import gpib
# in my case, the CSA was set address to 1
csa=gpib.dev(0,1) # get device handle
print("device handle",csa) # was 17
print("status serial poll",gpib.serial_poll(csa))
# serial poll seems needed as first command as response to SRQ request
issued by CSA at startup

gpib.write(csa,b'ID?') # no \r\n needed, EOI takes care of this
# in interactive mode the command also receives and prints the
status byte, 8448.
result=gpib.read(csa,1000) # read ID and store in result
print(result)

# another example
gpib.write(csa,b'uptime?')
print(gpib.read(csa,1000)) # result immediately shown now
gpib.close(csa)

The DMM Opt.1 recognizes some additional GPIB commands.

Pffff,
Albert

On Fri, May 17, 2019 at 06:24 PM, Tony Fleming wrote:


Magnus, and most or all of you are in a "stratosphere" compared to me,
who
is trying to learn my Tektronix 2465 DMS! But I also have P6407 and I
would
like to learn how to use it.
Can anyone out there help me with something simple I can try to connect
it?
I never have anything like this before, so use very simple terms what
all I
need please.
You all were very helpful with my scope, when it was sick and now it
works,
thanks to you all. I found this group to be the most helpful group out
there!
Thank you very much.
Tony


Albert Otten
 

Hi Tony,

Your 2465 doesn't have RS232, so you need a GPIB connection. Do you have such already (NI GPIB-USB-HS, Prologix,...)? I have the NI adapter. Or are you considering to use an Arduino (mentioned in your 2465 topic) for this? I know nothing of Arduinos (except that my son is married with these tiny things).
Tektronix had it's own version of NI-VISA, TekVISA, and a program Wavestar. These could be downloaded for free I think for Windows. I tried this once without much success and deleted it right away: together with NI drivers a HUGE amount of software! I used Linux ever since with the linux-gpib driver package. I don't know if the GPIB programs by Hakan (http://www.hakanh.com/dl/index.htm) together with drivers can serve you.
In my opinion PiVISA is not of much interest for you. VISA is intended for equipment that understands VISA commands. So you have to lookup in the Opt.10 manual which commands are recognized by the 2465 and send these commands exactly as shown in the manual. I have the same situation with my 7854 and CSAs.
At this moment I don't remember for sure whether drivers are still needed if the Pivisa-py package is used, but I think the are. If not then PiVISA is attractive. (Magnus knows?)
An alternative to PiVISA is to use the python package gpib_ctypes in combination with the Linux linux-gpib package or the (Linux, Windows) NI drivers.
The python script could look like this (note, I didn't test this since some time, I hope I removed errors):

#!/usr/bin/python3

# test gpib connection with the CSA803
from gpib_ctypes import gpib
# in my case, the CSA was set address to 1
csa=gpib.dev(0,1) # get device handle
print("device handle",csa) # was 17
print("status serial poll",gpib.serial_poll(csa))
# serial poll seems needed as first command as response to SRQ request issued by CSA at startup

gpib.write(csa,b'ID?') # no \r\n needed, EOI takes care of this
# in interactive mode the command also receives and prints the status byte, 8448.
result=gpib.read(csa,1000) # read ID and store in result
print(result)

# another example
gpib.write(csa,b'uptime?')
print(gpib.read(csa,1000)) # result immediately shown now
gpib.close(csa)

The DMM Opt.1 recognizes some additional GPIB commands.

Pffff,
Albert

On Fri, May 17, 2019 at 06:24 PM, Tony Fleming wrote:


Magnus, and most or all of you are in a "stratosphere" compared to me, who
is trying to learn my Tektronix 2465 DMS! But I also have P6407 and I would
like to learn how to use it.
Can anyone out there help me with something simple I can try to connect it?
I never have anything like this before, so use very simple terms what all I
need please.
You all were very helpful with my scope, when it was sick and now it works,
thanks to you all. I found this group to be the most helpful group out
there!
Thank you very much.
Tony

Tony Fleming
 

Magnus, and most or all of you are in a "stratosphere" compared to me, who
is trying to learn my Tektronix 2465 DMS! But I also have P6407 and I would
like to learn how to use it.
Can anyone out there help me with something simple I can try to connect it?
I never have anything like this before, so use very simple terms what all I
need please.
You all were very helpful with my scope, when it was sick and now it works,
thanks to you all. I found this group to be the most helpful group out
there!
Thank you very much.
Tony

On Fri, May 17, 2019 at 10:49 AM magnustoelle via Groups.Io <magnustoelle=
yahoo.com@groups.io> wrote:

Good Day,

thank you for your kind comments, Gentlemen. And thank you for that
weblink and the German figure of speech, Albert! :-)

The trouble is that I am looking at my Keithley 230 programmable voltage
source and the Keithley type 195 DMM (with its 100pA resolution) at the
shelves right behind my back right now. Both are equipped with GPIB, but
I have never done much with either device yet - and they keep staring at
me.
In combination with the FLUKE 8840A DMM, they might turn into a much
better curve tracer setup than the mentioned Grundig Digimess PN300
alone. More to come!

Tot ziens,

Magnus

[..]
A basic introduction corresponding to what Magnus does in his script is
here for example:

https://www.edn.com/design/test-and-measurement/4441692/How-to-automate-measurements-with-Python
I tried Python successfully for command communication (both serial and
GPIB) with my CSA803 but only to verify that it is possible.
(Magnus, I guess "a lot of water has flown through the river Rhein"
while
you composed that Python script ;-)

Albert





magnustoelle
 

Good Day,

thank you for your kind comments, Gentlemen. And thank you for that weblink and the German figure of speech, Albert! :-)

The trouble is that I am looking at my Keithley 230 programmable voltage source and the Keithley type 195 DMM (with its 100pA resolution)  at the shelves right behind my back right now. Both are equipped with GPIB, but I have never done much with either device yet - and they keep staring at me.
In combination with the FLUKE 8840A DMM, they might turn into a much better curve tracer setup than the mentioned Grundig Digimess PN300 alone. More to come!

Tot ziens,

Magnus

[..]

A basic introduction corresponding to what Magnus does in his script is
here for example:

https://www.edn.com/design/test-and-measurement/4441692/How-to-automate-measurements-with-Python
I tried Python successfully for command communication (both serial and
GPIB) with my CSA803 but only to verify that it is possible.
(Magnus, I guess "a lot of water has flown through the river Rhein" while
you composed that Python script ;-)

Albert



Tony Fleming
 

Thank you Albert!

On Thu, May 16, 2019 at 1:18 PM Albert Otten <aodiversen@...> wrote:

A basic introduction corresponding to what Magnus does in his script is
here for example:

https://www.edn.com/design/test-and-measurement/4441692/How-to-automate-measurements-with-Python
I tried Python successfully for command communication (both serial and
GPIB) with my CSA803 but only to verify that it is possible.
(Magnus, I guess "a lot of water has flown through the river Rhein" while
you composed that Python script ;-)

Albert



Albert Otten
 

A basic introduction corresponding to what Magnus does in his script is here for example:
https://www.edn.com/design/test-and-measurement/4441692/How-to-automate-measurements-with-Python
I tried Python successfully for command communication (both serial and GPIB) with my CSA803 but only to verify that it is possible.
(Magnus, I guess "a lot of water has flown through the river Rhein" while you composed that Python script ;-)

Albert

Tony Fleming
 

Jim (or anyone out there) can answer my question. I have Tektronix 2465 DMS
and I just purchased PC6407 RQus1, but I never used anything like this
before.
Is there some instructional video that would show how to use it and Python
combination?
I'm learning Micro-Python on my Arduino and ESP8266/ESP32 boards - I love
Python!!!
Here is the video I'm learning from:
https://www.youtube.com/watch?v=rfscVS0vtbw&t=3773s

On Thu, May 16, 2019 at 11:06 AM Jim Ford <james.ford@...> wrote:

Thanks, Magnus, for posting. I, too, am interested in automating my test
bench using Python. This after seeing the nightmare at work of piles of
Labview code tweaked by many engineers over several decades. You know
there's a problem when tests have to pass 2 out of 3 times because of race
conditions and other nasties in the code! We asked one of the software
jocks for an Abort Test button that actually gets out of a test, but he
said "Well, it's not that simple. Which module should it jump out of, and
where should it land?" Uh, never mind...!With the VISA wrappers it
*should* be easy to write test code for both my old (mostly HP) instruments
with their GPIB interfaces and newer gear with USB. Hoping to get a GPIB
card for my garage lab computer and get programming in Python over the
summer (of which year remains to be seen!)Jim Ford Sent from my Verizon,
Samsung Galaxy smartphone
-------- Original message --------From: "magnustoelle via Groups.Io"
<magnustoelle=yahoo.com@groups.io> Date: 5/16/19 8:26 AM (GMT-08:00)
To: TekScopes@groups.io Subject: [TekScopes] OT: I/V curve tracing made
easy with Python and PyVISA Good Day to the group,this is completely
off-topic, but as several of you seemed always interested in curve-tracing
applications, let me share my excitement with you...I know that I am very
late into this, but allow me to say that I have found the use of the Python
scripting language in combination with libraries & packages such as PyVISA
very powerful.To cut a long story short: I was curious to see, if I can
replace my NI LabView projects with something simpler, less costly and more
portable between Operating Systems such as Windows, Linux etc. And after
playing with Python for a few days, it seems that Python offers such an
alternative.I still like how easy it is to generate appealing GUIs with
LabView, but even when using hierarchical designs, LabView "code" can be
hard to read and comprehend - just try to decipher your own VIs after a few
months!I have used PyVISA https://pyvisa.readthedocs.io/en/master/ for
easy communication with T&M equipment and libraries such as mathlibplot
https://matplotlib.org/ for plotting and numpy https://www.numpy.org/ for
a few math operations. The documentation and tools come for free, and there
are tons and tons of on-line training courses on Python as well as code
examples etc. which are available at 0 costs.Curve-tracing application:I
have used a GRUNDIG/digimess PN300 programmable power supply & a common NI
USB-GPIB adapter; then created some simple Python-scripts which allow the
I/V-curve tracing of two-terminal devices such as diodes and of
three-terminal devices such as transistors. For the latter, output A from
the power supply provided the Collector-Emitter sweep voltage, and output B
and a 22kOhm resistor provided the base current sweep.I have never really
had any formal education in programming/coding, but I have found it fairly
easy to create the attached PNG diagram, to save the current and voltage
data to a local file for post-processing with MS Excel etc.While this is
nothing to "write home about" - my heartful recommendation is: If you have
the interest and leisure, give Python and a stab into PyVISA a try!I am
including my simple Python code below . I am sure there are many things
which could be improved - however, please let's do not discuss
here...Cheers,MagnusP.S. I am aware that the GRUNDIG PN300 power supply is
not a precision instrument, but I have chosen it for simplicity - upgrading
to precision DMMs and more precise current/voltage sources and the like
would be easy.# Setup Digimess/GRUNDIG PN300 power supply# Testing
three-terminal electronic devices such as transistors# Set-up for
independent operation, Voltage and Currents for output A and readback
Current measurements# Set-up Voltage and Currents for output B and readback
Current measurements and turn off outputs# Hardware setup: Connect emitter
to common GND, collector to pos. terminal output A, connect base to output
B using a 22k series resistor for base currents.# Magnus Tölle, last edit:
13th May 2019# Setup: Easyinstall from
https://pypi.org/project/setuptools/0.6c11/#files first, and "easyinstall
pip" second# Install Python, pip, matplotlib, numpy, pandas, seaborn and NI
VISA from ni.com# References:
https://github.com/demisjohn/Keithley-I-V-Sweep/blob/master/Keithley%20I-V%20Sweep%20v2.py
# Import libraries for plottingimport matplotlib.pyplot as pltimport numpy
as np# import pandas as pd# import seaborn as sns# Import libraries for
VISA controlimport visa# Optional logging of PyVISA# visa.log_to_screen()#
Import other librariesimport time # as to allow pause between
measurementsimport csv # as to allow saving data file# For UTF Coding to
avoid encoding issues:# -*- coding: utf-8 -*-# Program runs on Windows
only:import sysimport os # Filesystem manipulation# Disable printdef
blockPrint(): sys.stdout = open(os.devnull, 'w')# Restore printdef
enablePrint(): sys.stdout = sys.__stdout__def windows_interaction():
assert ('win' in sys.platform), "This program only runs on Windows
systems." try: windows_interaction() except AssertionError as
error: print(error) print('This script was not executed')#
open resource Digimess/GRUNDIG PN300 power supplyrm =
visa.ResourceManager()# rm.list_resources()res = rm.list_resources()print
("Please connect and power-up GPIB adapter and PN300 power supply")print
("Please configure PN300 for GPIB and note address - default is address
7")PN300_GPIB_address = input("Please enter GPIB address:")print ("Please
connect DUT as follows:")print ("Emitter to common GND, collector to pos.
terminal output A, connect base to output B using a 22k series
resistor")print("Found the following equipment / resources:")print(res)
# print("Opening " + res[-1])PN300 = rm.get_instrument ('GPIB::' +
str(PN300_GPIB_address)) # Query to confirm that Digimess/GRUNDIG PN300 is
presentprint (PN300.query('*IDN?')) # Initialize and setup
Digimess/GRUNDIG PN300 power supply for constant voltage, independent
operationPN300.write('*RST')PN300.write('OPER_IND')PN300.write('CONT_CV')#
Ask user for voltage setup, current limits for output AVstartA =
input("Enter min. voltage sweep setting for output A in Volt: ")VstopA =
input("Enter max. voltage sweep setting for output A in Volt: ")VstepA =
input("Enter number of sweep steps for output A: ")VoltsA =
np.linspace(int(VstartA),int(VstopA),(int(VstepA)+1))Current_setA =
input("Enter current limit for output A in Ampere: ")Current_setA = 'ISET '
+ Current_setA# Ask user for voltage setup, current limits for output
BVstartB = input("Enter min. current sweep setting for output B in µA:
")VstopB = input("Enter max. current sweep setting for output B in µA (max.
1300µA): ")VstepB = input("Enter number of sweep steps for output B:
")Current_setB = input("Enter current limit for output B in Ampere:
")Current_setB = 'ISET ' + Current_setB# Ask user for base current resistor
valueResistor = input("Enter measured series resistor value in kOhm:
")Resistor = float(Resistor)*1E3VoltsB =
np.linspace(float(float(VstartB)*1E-6*Resistor),float(float(VstopB)*1E-6*Resistor),int(VstepB)+1)
# Ask user for DUT nameDUTname = input("Enter name of the device under test
or DUT: ")# Set timeout to 10 secondsPN300.timeout = 10000# Enable outputs,
and set output A and B to 0V, inform user that measurements start
nowPN300.write('SEL_A')PN300.write('VSET
0.00')PN300.write(Current_setA)PN300.write('SEL_B')PN300.write('VSET
0.00')PN300.write(Current_setB)PN300.write('OUT_ON')print("Starting with
measurements now")VoltageDataA = []CurrentDataA = []CurrentDataB = []for
Voltage2 in VoltsB: PN300.write('SEL_B') PN300.write('VSET
'+(str(Voltage2))) Voltage2A = PN300.query('VOUT?')
Voltage_formatted2A = float(Voltage2A[2:7])
CurrentDataB.append(Voltage_formatted2A/Resistor) for Voltage1 in
VoltsA: PN300.write('SEL_A') PN300.write('VSET
'+(str(Voltage1))) Voltage1A = PN300.query('VOUT?')
Voltage_formatted1A = float(Voltage1A[2:7])
VoltageDataA.append(Voltage_formatted1A) # time.sleep(0.1) optional
delay time of 0.1 seconds Current1A = PN300.query('IOUT?')
Current_formatted1A = float(Current1A[2:7])
CurrentDataA.append(Current_formatted1A) print ("Emitter voltage
and current: ", Voltage1A, Current1A) print ("Base current in µA:
", (Voltage_formatted2A/Resistor*1E6))DataArrayA =
np.asarray((VoltageDataA, CurrentDataA, CurrentDataB)) # Set output A to
0V and turn outputs offPN300.write('OUT_OFF')Voltage_setA = 'VSET
0.00'PN300.write(Voltage_setA)# Notify userprint("Finished measurement and
outputs turned off")plt.style.use('seaborn-whitegrid')for IndexA in
range(0, int(VstepA)+1): IndexB = IndexA+1 IndexC =
IndexA+2plt.plot(VoltageDataA[(IndexA*int(VstepA)+IndexA):(IndexC*int(VstepA)+IndexC-1)],
CurrentDataA[(IndexA*int(VstepA)+IndexA):(IndexC*int(VstepA)+IndexC-1)],
linestyle='--', marker='x', markersize=8, color='g')plt.xlabel('Voltage in
Volt')plt.ylabel('Current in Ampere')plt.legend([DUTname + ' I/V curve'],
loc='best', shadow=True)plt.show()# Save the Data to a csv-file with the
DUT name# with appended rows for VoltageA, CurrentA, CurrentB dataNewFile =
open(DUTname+'.csv', 'w')with open(DUTname+'.csv', 'w', newline='') as fp:
wr = csv.writer(fp, dialect='excel') wr.writerow(VoltageDataA)with
open(DUTname+'.csv', 'a', newline='') as fp: wr = csv.writer(fp,
dialect='excel') wr.writerow(CurrentDataA)with open(DUTname+'.csv',
'a', newline='') as fp: wr = csv.writer(fp, dialect='excel')
wr.writerow(CurrentDataB)# Close the file - end of python
scriptNewFile.close()


Gary Robert Bosworth
 

Magnus:
Thanx for the info. I learn something new every day.
Gary

On Thu, May 16, 2019 at 8:28 AM magnustoelle via Groups.Io <magnustoelle=
yahoo.com@groups.io> wrote:

Good Day to the group,

this is completely off-topic, but as several of you seemed always
interested in curve-tracing applications, let me share my excitement
with you...

I know that I am very late into this, but allow me to say that I have
found the use of the Python scripting language in combination with
libraries & packages such as PyVISA very powerful.
To cut a long story short: I was curious to see, if I can replace my NI
LabView projects with something simpler, less costly and more portable
between Operating Systems such as Windows, Linux etc. And after playing
with Python for a few days, it seems that Python offers such an
alternative.
I still like how easy it is to generate appealing GUIs with LabView, but
even when using hierarchical designs, LabView "code" can be hard to read
and comprehend - just try to decipher your own VIs after a few months!

I have used PyVISA https://pyvisa.readthedocs.io/en/master/ for easy
communication with T&M equipment and libraries such as mathlibplot
https://matplotlib.org/ for plotting and numpy https://www.numpy.org/
for a few math operations. The documentation and tools come for free,
and there are tons and tons of on-line training courses on Python as
well as code examples etc. which are available at 0 costs.

Curve-tracing application:
I have used a GRUNDIG/digimess PN300 programmable power supply & a
common NI USB-GPIB adapter; then created some simple Python-scripts
which allow the I/V-curve tracing of two-terminal devices such as diodes
and of three-terminal devices such as transistors. For the latter,
output A from the power supply provided the Collector-Emitter sweep
voltage, and output B and a 22kOhm resistor provided the base current
sweep.

I have never really had any formal education in programming/coding, but
I have found it fairly easy to create the attached PNG diagram, to save
the current and voltage data to a local file for post-processing with MS
Excel etc.

While this is nothing to "write home about" - my heartful recommendation
is: If you have the interest and leisure, give Python and a stab into
PyVISA a try!

I am including my simple Python code below . I am sure there are many
things which could be improved - however, please let's do not discuss
here...

Cheers,

Magnus

P.S. I am aware that the GRUNDIG PN300 power supply is not a precision
instrument, but I have chosen it for simplicity - upgrading to precision
DMMs and more precise current/voltage sources and the like would be easy.

# Setup Digimess/GRUNDIG PN300 power supply
# Testing three-terminal electronic devices such as transistors
# Set-up for independent operation, Voltage and Currents for output A
and readback Current measurements
# Set-up Voltage and Currents for output B and readback Current
measurements and turn off outputs
# Hardware setup: Connect emitter to common GND, collector to pos.
terminal output A, connect base to output B using a 22k series resistor
for base currents.
# Magnus Tölle, last edit: 13th May 2019
# Setup: Easyinstall from
https://pypi.org/project/setuptools/0.6c11/#files first, and
"easyinstall pip" second
# Install Python, pip, matplotlib, numpy, pandas, seaborn and NI VISA
from ni.com
# References:

https://github.com/demisjohn/Keithley-I-V-Sweep/blob/master/Keithley%20I-V%20Sweep%20v2.py


# Import libraries for plotting
import matplotlib.pyplot as plt
import numpy as np
# import pandas as pd
# import seaborn as sns

# Import libraries for VISA control
import visa

# Optional logging of PyVISA
# visa.log_to_screen()

# Import other libraries
import time # as to allow pause between measurements
import csv # as to allow saving data file

# For UTF Coding to avoid encoding issues:
# -*- coding: utf-8 -*-

# Program runs on Windows only:
import sys
import os # Filesystem manipulation

# Disable print
def blockPrint():
sys.stdout = open(os.devnull, 'w')

# Restore print
def enablePrint():
sys.stdout = sys.__stdout__

def windows_interaction():
assert ('win' in sys.platform), "This program only runs on Windows
systems."
try: windows_interaction()
except AssertionError as error:
print(error)
print('This script was not executed')

# open resource Digimess/GRUNDIG PN300 power supply
rm = visa.ResourceManager()
# rm.list_resources()
res = rm.list_resources()
print ("Please connect and power-up GPIB adapter and PN300 power supply")
print ("Please configure PN300 for GPIB and note address - default is
address 7")
PN300_GPIB_address = input("Please enter GPIB address:")
print ("Please connect DUT as follows:")
print ("Emitter to common GND, collector to pos. terminal output A,
connect base to output B using a 22k series resistor")

print("Found the following equipment / resources:")
print(res)
# print("Opening " + res[-1])

PN300 = rm.get_instrument ('GPIB::' + str(PN300_GPIB_address))

# Query to confirm that Digimess/GRUNDIG PN300 is present
print (PN300.query('*IDN?'))

# Initialize and setup Digimess/GRUNDIG PN300 power supply for
constant voltage, independent operation
PN300.write('*RST')
PN300.write('OPER_IND')
PN300.write('CONT_CV')

# Ask user for voltage setup, current limits for output A
VstartA = input("Enter min. voltage sweep setting for output A in Volt: ")
VstopA = input("Enter max. voltage sweep setting for output A in Volt: ")
VstepA = input("Enter number of sweep steps for output A: ")

VoltsA = np.linspace(int(VstartA),int(VstopA),(int(VstepA)+1))

Current_setA = input("Enter current limit for output A in Ampere: ")
Current_setA = 'ISET ' + Current_setA

# Ask user for voltage setup, current limits for output B
VstartB = input("Enter min. current sweep setting for output B in µA: ")
VstopB = input("Enter max. current sweep setting for output B in µA
(max. 1300µA): ")
VstepB = input("Enter number of sweep steps for output B: ")

Current_setB = input("Enter current limit for output B in Ampere: ")
Current_setB = 'ISET ' + Current_setB

# Ask user for base current resistor value
Resistor = input("Enter measured series resistor value in kOhm: ")
Resistor = float(Resistor)*1E3

VoltsB =
np.linspace(float(float(VstartB)*1E-6*Resistor),float(float(VstopB)*1E-6*Resistor),int(VstepB)+1)



# Ask user for DUT name
DUTname = input("Enter name of the device under test or DUT: ")

# Set timeout to 10 seconds
PN300.timeout = 10000
# Enable outputs, and set output A and B to 0V, inform user that
measurements start now
PN300.write('SEL_A')
PN300.write('VSET 0.00')
PN300.write(Current_setA)

PN300.write('SEL_B')
PN300.write('VSET 0.00')
PN300.write(Current_setB)
PN300.write('OUT_ON')
print("Starting with measurements now")

VoltageDataA = []
CurrentDataA = []
CurrentDataB = []

for Voltage2 in VoltsB:
PN300.write('SEL_B')
PN300.write('VSET '+(str(Voltage2)))
Voltage2A = PN300.query('VOUT?')
Voltage_formatted2A = float(Voltage2A[2:7])
CurrentDataB.append(Voltage_formatted2A/Resistor)

for Voltage1 in VoltsA:
PN300.write('SEL_A')
PN300.write('VSET '+(str(Voltage1)))
Voltage1A = PN300.query('VOUT?')
Voltage_formatted1A = float(Voltage1A[2:7])
VoltageDataA.append(Voltage_formatted1A)
# time.sleep(0.1) optional delay time of 0.1 seconds
Current1A = PN300.query('IOUT?')
Current_formatted1A = float(Current1A[2:7])
CurrentDataA.append(Current_formatted1A)
print ("Emitter voltage and current: ", Voltage1A, Current1A)
print ("Base current in µA: ", (Voltage_formatted2A/Resistor*1E6))

DataArrayA = np.asarray((VoltageDataA, CurrentDataA, CurrentDataB))


# Set output A to 0V and turn outputs off
PN300.write('OUT_OFF')
Voltage_setA = 'VSET 0.00'
PN300.write(Voltage_setA)

# Notify user
print("Finished measurement and outputs turned off")

plt.style.use('seaborn-whitegrid')

for IndexA in range(0, int(VstepA)+1):
IndexB = IndexA+1
IndexC = IndexA+2
plt.plot(VoltageDataA[(IndexA*int(VstepA)+IndexA):(IndexC*int(VstepA)+IndexC-1)],

CurrentDataA[(IndexA*int(VstepA)+IndexA):(IndexC*int(VstepA)+IndexC-1)],
linestyle='--', marker='x', markersize=8, color='g')
plt.xlabel('Voltage in Volt')
plt.ylabel('Current in Ampere')
plt.legend([DUTname + ' I/V curve'], loc='best', shadow=True)
plt.show()

# Save the Data to a csv-file with the DUT name
# with appended rows for VoltageA, CurrentA, CurrentB data
NewFile = open(DUTname+'.csv', 'w')

with open(DUTname+'.csv', 'w', newline='') as fp:
wr = csv.writer(fp, dialect='excel')
wr.writerow(VoltageDataA)

with open(DUTname+'.csv', 'a', newline='') as fp:
wr = csv.writer(fp, dialect='excel')
wr.writerow(CurrentDataA)

with open(DUTname+'.csv', 'a', newline='') as fp:
wr = csv.writer(fp, dialect='excel')
wr.writerow(CurrentDataB)
# Close the file - end of python script
NewFile.close()




--
Gary Robert Bosworth
@grbosworth
Tel: 310-317-2247

Jim Ford
 

Thanks, Magnus, for posting.  I, too, am interested in automating my test bench using Python.  This after seeing the nightmare at work of piles of Labview code tweaked by many engineers over several decades.  You know there's a problem when tests have to pass 2 out of 3 times because of race conditions and other nasties in the code!  We asked one of the software jocks for an Abort Test button that actually gets out of a test, but he said "Well, it's not that simple.  Which module should it jump out of, and where should it land?"  Uh, never mind...!With the VISA wrappers it *should* be easy to write test code for both my old (mostly HP) instruments with their GPIB interfaces and newer gear with USB.  Hoping to get a GPIB card for my garage lab computer and get programming in Python over the summer (of which year remains to be seen!)Jim Ford Sent from my Verizon, Samsung Galaxy smartphone

-------- Original message --------From: "magnustoelle via Groups.Io" <magnustoelle=yahoo.com@groups.io> Date: 5/16/19 8:26 AM (GMT-08:00) To: TekScopes@groups.io Subject: [TekScopes] OT: I/V curve tracing made easy with Python and PyVISA Good Day to the group,this is completely off-topic, but as several of you seemed always interested in curve-tracing applications, let me share my excitement with you...I know that I am very late into this, but allow me to say that I have found the use of the Python scripting language in combination with libraries & packages such as PyVISA very powerful.To cut a long story short: I was curious to see, if I can replace my NI LabView projects with something simpler, less costly and more portable between Operating Systems such as Windows, Linux etc. And after playing with Python for a few days, it seems that Python offers such an alternative.I still like how easy it is to generate appealing GUIs with LabView, but even when using hierarchical designs, LabView "code" can be hard to read and comprehend - just try to decipher your own VIs after a few months!I have used PyVISA https://pyvisa.readthedocs.io/en/master/ for easy communication with T&M equipment and libraries such as mathlibplot https://matplotlib.org/ for plotting and numpy https://www.numpy.org/ for a few math operations. The documentation and tools come for free, and there are tons and tons of on-line training courses on Python as well as code examples etc. which are available at 0 costs.Curve-tracing application:I have used a GRUNDIG/digimess PN300 programmable power supply & a common NI USB-GPIB adapter; then created some simple Python-scripts which allow the I/V-curve tracing of two-terminal devices such as diodes and of three-terminal devices such as transistors. For the latter, output A from the power supply provided the Collector-Emitter sweep voltage, and output B and a 22kOhm resistor provided the base current sweep.I have never really had any formal education in programming/coding, but I have found it fairly easy to create the attached PNG diagram, to save the current and voltage data to a local file for post-processing with MS Excel etc.While this is nothing to "write home about" - my heartful recommendation is: If you have the interest and leisure, give Python and a stab into PyVISA a try!I am including my simple Python code below . I am sure there are many things which could be improved - however,  please let's do not discuss here...Cheers,MagnusP.S. I am aware that the GRUNDIG PN300 power supply is not a precision instrument, but I have chosen it for simplicity - upgrading to precision DMMs and more precise current/voltage sources and the like would be easy.# Setup Digimess/GRUNDIG PN300 power supply# Testing three-terminal electronic devices such as transistors# Set-up for independent operation, Voltage and Currents for output A and readback Current measurements# Set-up Voltage and Currents for output B and readback Current measurements and turn off outputs# Hardware setup: Connect emitter to common GND, collector to pos. terminal output A, connect base to output B using a 22k series resistor for base currents.# Magnus Tölle, last edit: 13th May 2019# Setup: Easyinstall from https://pypi.org/project/setuptools/0.6c11/#files first, and "easyinstall pip" second# Install Python, pip, matplotlib, numpy, pandas, seaborn and NI VISA from ni.com# References: https://github.com/demisjohn/Keithley-I-V-Sweep/blob/master/Keithley%20I-V%20Sweep%20v2.py # Import libraries for plottingimport matplotlib.pyplot as pltimport numpy as np# import pandas as pd# import seaborn as sns# Import libraries for VISA controlimport visa# Optional logging of PyVISA# visa.log_to_screen()# Import other librariesimport time # as to allow pause between measurementsimport csv # as to allow saving data file# For UTF Coding to avoid encoding issues:# -*- coding: utf-8 -*-# Program runs on Windows only:import sysimport os # Filesystem manipulation# Disable printdef blockPrint():     sys.stdout = open(os.devnull, 'w')# Restore printdef enablePrint():     sys.stdout = sys.__stdout__def windows_interaction():     assert ('win' in sys.platform), "This program only runs on Windows systems."     try: windows_interaction()     except AssertionError as error:         print(error)         print('This script was not executed')# open resource Digimess/GRUNDIG PN300 power supplyrm = visa.ResourceManager()# rm.list_resources()res = rm.list_resources()print ("Please connect and power-up GPIB adapter and PN300 power supply")print ("Please configure PN300 for GPIB and note address - default is address 7")PN300_GPIB_address = input("Please enter GPIB address:")print ("Please connect DUT as follows:")print ("Emitter to common GND, collector to pos. terminal output A, connect base to output B using a 22k series resistor")print("Found the following equipment / resources:")print(res)     # print("Opening " + res[-1])PN300 = rm.get_instrument ('GPIB::' + str(PN300_GPIB_address))  # Query to confirm that Digimess/GRUNDIG PN300 is presentprint (PN300.query('*IDN?'))  # Initialize and setup Digimess/GRUNDIG PN300 power supply for constant voltage, independent operationPN300.write('*RST')PN300.write('OPER_IND')PN300.write('CONT_CV')# Ask user for voltage setup, current limits for output AVstartA = input("Enter min. voltage sweep setting for output A in Volt: ")VstopA = input("Enter max. voltage sweep setting for output A in Volt: ")VstepA = input("Enter number of sweep steps for output A: ")VoltsA = np.linspace(int(VstartA),int(VstopA),(int(VstepA)+1))Current_setA = input("Enter current limit for output A in Ampere: ")Current_setA = 'ISET ' + Current_setA# Ask user for voltage setup, current limits for output BVstartB = input("Enter min. current sweep setting for output B in µA: ")VstopB = input("Enter max. current sweep setting for output B in µA (max. 1300µA): ")VstepB = input("Enter number of sweep steps for output B: ")Current_setB = input("Enter current limit for output B in Ampere: ")Current_setB = 'ISET ' + Current_setB# Ask user for base current resistor valueResistor = input("Enter measured series resistor value in kOhm: ")Resistor = float(Resistor)*1E3VoltsB = np.linspace(float(float(VstartB)*1E-6*Resistor),float(float(VstopB)*1E-6*Resistor),int(VstepB)+1) # Ask user for DUT nameDUTname = input("Enter name of the device under test or DUT: ")# Set timeout to 10 secondsPN300.timeout = 10000# Enable outputs, and set output A and B to 0V, inform user that measurements start nowPN300.write('SEL_A')PN300.write('VSET 0.00')PN300.write(Current_setA)PN300.write('SEL_B')PN300.write('VSET 0.00')PN300.write(Current_setB)PN300.write('OUT_ON')print("Starting with measurements now")VoltageDataA = []CurrentDataA = []CurrentDataB = []for Voltage2 in VoltsB:     PN300.write('SEL_B')     PN300.write('VSET '+(str(Voltage2)))     Voltage2A = PN300.query('VOUT?')     Voltage_formatted2A = float(Voltage2A[2:7])     CurrentDataB.append(Voltage_formatted2A/Resistor)     for Voltage1 in VoltsA:         PN300.write('SEL_A')         PN300.write('VSET '+(str(Voltage1)))         Voltage1A = PN300.query('VOUT?')         Voltage_formatted1A = float(Voltage1A[2:7])         VoltageDataA.append(Voltage_formatted1A)         # time.sleep(0.1) optional delay time of 0.1 seconds         Current1A = PN300.query('IOUT?')         Current_formatted1A = float(Current1A[2:7])         CurrentDataA.append(Current_formatted1A)         print ("Emitter voltage and current: ", Voltage1A, Current1A)         print ("Base current in µA: ", (Voltage_formatted2A/Resistor*1E6))DataArrayA = np.asarray((VoltageDataA, CurrentDataA, CurrentDataB))  # Set output A to 0V and turn outputs offPN300.write('OUT_OFF')Voltage_setA = 'VSET 0.00'PN300.write(Voltage_setA)# Notify userprint("Finished measurement and outputs turned off")plt.style.use('seaborn-whitegrid')for IndexA in range(0, int(VstepA)+1):     IndexB = IndexA+1     IndexC = IndexA+2plt.plot(VoltageDataA[(IndexA*int(VstepA)+IndexA):(IndexC*int(VstepA)+IndexC-1)], CurrentDataA[(IndexA*int(VstepA)+IndexA):(IndexC*int(VstepA)+IndexC-1)], linestyle='--', marker='x', markersize=8, color='g')plt.xlabel('Voltage in Volt')plt.ylabel('Current in Ampere')plt.legend([DUTname + ' I/V curve'], loc='best', shadow=True)plt.show()# Save the Data to a csv-file with the DUT name# with appended rows for VoltageA, CurrentA, CurrentB dataNewFile = open(DUTname+'.csv', 'w')with open(DUTname+'.csv', 'w', newline='') as fp:     wr = csv.writer(fp, dialect='excel')     wr.writerow(VoltageDataA)with open(DUTname+'.csv', 'a', newline='') as fp:     wr = csv.writer(fp, dialect='excel')     wr.writerow(CurrentDataA)with open(DUTname+'.csv', 'a', newline='') as fp:     wr = csv.writer(fp, dialect='excel')     wr.writerow(CurrentDataB)# Close the file - end of python scriptNewFile.close()

magnustoelle
 

Good Day to the group,

this is completely off-topic, but as several of you seemed always interested in curve-tracing applications, let me share my excitement with you...

I know that I am very late into this, but allow me to say that I have found the use of the Python scripting language in combination with libraries & packages such as PyVISA very powerful.
To cut a long story short: I was curious to see, if I can replace my NI LabView projects with something simpler, less costly and more portable between Operating Systems such as Windows, Linux etc. And after playing with Python for a few days, it seems that Python offers such an alternative.
I still like how easy it is to generate appealing GUIs with LabView, but even when using hierarchical designs, LabView "code" can be hard to read and comprehend - just try to decipher your own VIs after a few months!

I have used PyVISA https://pyvisa.readthedocs.io/en/master/ for easy communication with T&M equipment and libraries such as mathlibplot https://matplotlib.org/ for plotting and numpy https://www.numpy.org/ for a few math operations. The documentation and tools come for free, and there are tons and tons of on-line training courses on Python as well as code examples etc. which are available at 0 costs.

Curve-tracing application:
I have used a GRUNDIG/digimess PN300 programmable power supply & a common NI USB-GPIB adapter; then created some simple Python-scripts which allow the I/V-curve tracing of two-terminal devices such as diodes and of three-terminal devices such as transistors. For the latter, output A from the power supply provided the Collector-Emitter sweep voltage, and output B and a 22kOhm resistor provided the base current sweep.

I have never really had any formal education in programming/coding, but I have found it fairly easy to create the attached PNG diagram, to save the current and voltage data to a local file for post-processing with MS Excel etc.

While this is nothing to "write home about" - my heartful recommendation is: If you have the interest and leisure, give Python and a stab into PyVISA a try!

I am including my simple Python code below . I am sure there are many things which could be improved - however,  please let's do not discuss here...

Cheers,

Magnus

P.S. I am aware that the GRUNDIG PN300 power supply is not a precision instrument, but I have chosen it for simplicity - upgrading to precision DMMs and more precise current/voltage sources and the like would be easy.

# Setup Digimess/GRUNDIG PN300 power supply
# Testing three-terminal electronic devices such as transistors
# Set-up for independent operation, Voltage and Currents for output A and readback Current measurements
# Set-up Voltage and Currents for output B and readback Current measurements and turn off outputs
# Hardware setup: Connect emitter to common GND, collector to pos. terminal output A, connect base to output B using a 22k series resistor for base currents.
# Magnus Tölle, last edit: 13th May 2019
# Setup: Easyinstall from https://pypi.org/project/setuptools/0.6c11/#files first, and "easyinstall pip" second
# Install Python, pip, matplotlib, numpy, pandas, seaborn and NI VISA from ni.com
# References: https://github.com/demisjohn/Keithley-I-V-Sweep/blob/master/Keithley%20I-V%20Sweep%20v2.py


# Import libraries for plotting
import matplotlib.pyplot as plt
import numpy as np
# import pandas as pd
# import seaborn as sns

# Import libraries for VISA control
import visa

# Optional logging of PyVISA
# visa.log_to_screen()

# Import other libraries
import time # as to allow pause between measurements
import csv # as to allow saving data file

# For UTF Coding to avoid encoding issues:
# -*- coding: utf-8 -*-

# Program runs on Windows only:
import sys
import os # Filesystem manipulation

# Disable print
def blockPrint():
    sys.stdout = open(os.devnull, 'w')

# Restore print
def enablePrint():
    sys.stdout = sys.__stdout__

def windows_interaction():
    assert ('win' in sys.platform), "This program only runs on Windows systems."
    try: windows_interaction()
    except AssertionError as error:
        print(error)
        print('This script was not executed')

# open resource Digimess/GRUNDIG PN300 power supply
rm = visa.ResourceManager()
# rm.list_resources()
res = rm.list_resources()
print ("Please connect and power-up GPIB adapter and PN300 power supply")
print ("Please configure PN300 for GPIB and note address - default is address 7")
PN300_GPIB_address = input("Please enter GPIB address:")
print ("Please connect DUT as follows:")
print ("Emitter to common GND, collector to pos. terminal output A, connect base to output B using a 22k series resistor")

print("Found the following equipment / resources:")
print(res)
    # print("Opening " + res[-1])

PN300 = rm.get_instrument ('GPIB::' + str(PN300_GPIB_address))

 # Query to confirm that Digimess/GRUNDIG PN300 is present
print (PN300.query('*IDN?'))

 # Initialize and setup Digimess/GRUNDIG PN300 power supply for constant voltage, independent operation
PN300.write('*RST')
PN300.write('OPER_IND')
PN300.write('CONT_CV')

# Ask user for voltage setup, current limits for output A
VstartA = input("Enter min. voltage sweep setting for output A in Volt: ")
VstopA = input("Enter max. voltage sweep setting for output A in Volt: ")
VstepA = input("Enter number of sweep steps for output A: ")

VoltsA = np.linspace(int(VstartA),int(VstopA),(int(VstepA)+1))

Current_setA = input("Enter current limit for output A in Ampere: ")
Current_setA = 'ISET ' + Current_setA

# Ask user for voltage setup, current limits for output B
VstartB = input("Enter min. current sweep setting for output B in µA: ")
VstopB = input("Enter max. current sweep setting for output B in µA (max. 1300µA): ")
VstepB = input("Enter number of sweep steps for output B: ")

Current_setB = input("Enter current limit for output B in Ampere: ")
Current_setB = 'ISET ' + Current_setB

# Ask user for base current resistor value
Resistor = input("Enter measured series resistor value in kOhm: ")
Resistor = float(Resistor)*1E3

VoltsB = np.linspace(float(float(VstartB)*1E-6*Resistor),float(float(VstopB)*1E-6*Resistor),int(VstepB)+1)


# Ask user for DUT name
DUTname = input("Enter name of the device under test or DUT: ")

# Set timeout to 10 seconds
PN300.timeout = 10000
# Enable outputs, and set output A and B to 0V, inform user that measurements start now
PN300.write('SEL_A')
PN300.write('VSET 0.00')
PN300.write(Current_setA)

PN300.write('SEL_B')
PN300.write('VSET 0.00')
PN300.write(Current_setB)
PN300.write('OUT_ON')
print("Starting with measurements now")

VoltageDataA = []
CurrentDataA = []
CurrentDataB = []

for Voltage2 in VoltsB:
    PN300.write('SEL_B')
    PN300.write('VSET '+(str(Voltage2)))
    Voltage2A = PN300.query('VOUT?')
    Voltage_formatted2A = float(Voltage2A[2:7])
    CurrentDataB.append(Voltage_formatted2A/Resistor)

    for Voltage1 in VoltsA:
        PN300.write('SEL_A')
        PN300.write('VSET '+(str(Voltage1)))
        Voltage1A = PN300.query('VOUT?')
        Voltage_formatted1A = float(Voltage1A[2:7])
        VoltageDataA.append(Voltage_formatted1A)
        # time.sleep(0.1) optional delay time of 0.1 seconds
        Current1A = PN300.query('IOUT?')
        Current_formatted1A = float(Current1A[2:7])
        CurrentDataA.append(Current_formatted1A)
        print ("Emitter voltage and current: ", Voltage1A, Current1A)
        print ("Base current in µA: ", (Voltage_formatted2A/Resistor*1E6))

DataArrayA = np.asarray((VoltageDataA, CurrentDataA, CurrentDataB))


 # Set output A to 0V and turn outputs off
PN300.write('OUT_OFF')
Voltage_setA = 'VSET 0.00'
PN300.write(Voltage_setA)

# Notify user
print("Finished measurement and outputs turned off")

plt.style.use('seaborn-whitegrid')

for IndexA in range(0, int(VstepA)+1):
    IndexB = IndexA+1
    IndexC = IndexA+2
plt.plot(VoltageDataA[(IndexA*int(VstepA)+IndexA):(IndexC*int(VstepA)+IndexC-1)], CurrentDataA[(IndexA*int(VstepA)+IndexA):(IndexC*int(VstepA)+IndexC-1)], linestyle='--', marker='x', markersize=8, color='g')
plt.xlabel('Voltage in Volt')
plt.ylabel('Current in Ampere')
plt.legend([DUTname + ' I/V curve'], loc='best', shadow=True)
plt.show()

# Save the Data to a csv-file with the DUT name
# with appended rows for VoltageA, CurrentA, CurrentB data
NewFile = open(DUTname+'.csv', 'w')

with open(DUTname+'.csv', 'w', newline='') as fp:
    wr = csv.writer(fp, dialect='excel')
    wr.writerow(VoltageDataA)

with open(DUTname+'.csv', 'a', newline='') as fp:
    wr = csv.writer(fp, dialect='excel')
    wr.writerow(CurrentDataA)

with open(DUTname+'.csv', 'a', newline='') as fp:
    wr = csv.writer(fp, dialect='excel')
    wr.writerow(CurrentDataB)
# Close the file - end of python script
NewFile.close()