Skip to content

Commit e5a6be1

Browse files
committed
Update 4200A KXCI Examples
1 parent 6b72462 commit e5a6be1

File tree

54 files changed

+3512
-210
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+3512
-210
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""
2+
This example calls the "cviv_configure" user module to setup the CVIV for
3+
CVU measurements using the EX command.
4+
"""
5+
6+
from instrcomms import Communications
7+
import time
8+
9+
INST_RESOURCE_STR = "TCPIP0::192.0.2.0::1225::SOCKET" # Instrument resource string, obtained from NI MAX
10+
my4200 = Communications(INST_RESOURCE_STR) # Opens the resource manager in PyVISA with the corresponding instrument resource string
11+
my4200.connect() # Opens connections to the 4200A-SCS
12+
my4200._instrument_object.write_termination = "\0" # Set PyVISA write terminator
13+
my4200._instrument_object.read_termination = "\0" # Set PyVISA read terminator
14+
15+
my4200.query("UL") # Enter user lbirary mode
16+
"""
17+
Details on the inputs for the cviv_configure user module:
18+
19+
Inputs | Definition
20+
------ | ----------
21+
InstId | char string instrument identifier, such as "CVIV1"
22+
TwoWireMode | 0: CV Four Wire, 1: CV Two Wire
23+
24+
Connection Mode Settings:
25+
26+
Setting | Mode
27+
------- | ----
28+
0 | OPEN
29+
1 | SMU
30+
2 | CV Hi
31+
3 | CV Low
32+
4 | CV Guard
33+
5 | Ground Unit
34+
6 | AC Coup AC Ground
35+
7 | BiasT SMU CV HI
36+
8 | BiasT SMU CV LO
37+
9 | BiasT SMU LO I CV HI
38+
10 | BiasT SMU LO I CV LO
39+
11 | BiasT SMU AC Ground
40+
41+
Ch1_Mode | Connection Mode
42+
Ch2_Mode | Connection Mode
43+
Ch3_Mode | Connection Mode
44+
Ch4_Mode | Connection Mode
45+
Ch1_TermName | Display Name for Ch1 Terminal (up to 6 characters will be displayed)
46+
Ch2_TermName | Display Name for Ch2 Terminal (up to 6 characters will be displayed)
47+
Ch3_TermName | Display Name for Ch3 Terminal (up to 6 characters will be displayed)
48+
Ch4_TermName | Display Name for Ch4 Terminal (up to 6 characters will be displayed)
49+
TestName | Display Name for Test (up to 16 characters will be displayed)
50+
"""
51+
# Call the cviv_configure user module for CVU measurements
52+
my4200.query("EX cvivulib cviv_configure (CVIV1, 1, 3, 3, 2, 3, Source, Drain, Gate, Bulk, CV, )")
53+
54+
# This is a loop to check the status of the test
55+
# The SP command returns 0 or 1 when the test is done running
56+
while True:
57+
status = my4200.query("SP")
58+
59+
# Continues loop until the test is complete
60+
# Casting the status string to int makes the comparison simpler since it ignores the termination characters
61+
if int(status) in [0, 1]:
62+
print("Setup Complete.")
63+
break
64+
65+
# Continously prints the status of the test every second to the terminal
66+
print(f"Status: {status}")
67+
time.sleep(1)
68+
69+
my4200.disconnect() # Close communications with the 4200A-SCS
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""
2+
This example calls the "cviv_configure" user module to setup the CVIV for
3+
SMU measurements using the EX command.
4+
"""
5+
6+
from instrcomms import Communications
7+
import time
8+
9+
INST_RESOURCE_STR = "TCPIP0::192.0.2.0::1225::SOCKET" # Instrument resource string, obtained from NI MAX
10+
my4200 = Communications(INST_RESOURCE_STR) # Opens the resource manager in PyVISA with the corresponding instrument resource string
11+
my4200.connect() # Opens connections to the 4200A-SCS
12+
my4200._instrument_object.write_termination = "\0" # Set PyVISA write terminator
13+
my4200._instrument_object.read_termination = "\0" # Set PyVISA read terminator
14+
15+
my4200.query("UL") # Enter user library mode
16+
"""
17+
Details on the inputs for the cviv_configure user module:
18+
19+
Inputs | Definition
20+
------ | ----------
21+
InstId | char string instrument identifier, such as "CVIV1"
22+
TwoWireMode | 0: CV Four Wire, 1: CV Two Wire
23+
24+
Connection Mode Settings:
25+
26+
Setting | Mode
27+
------- | ----
28+
0 | OPEN
29+
1 | SMU
30+
2 | CV Hi
31+
3 | CV Low
32+
4 | CV Guard
33+
5 | Ground Unit
34+
6 | AC Coup AC Ground
35+
7 | BiasT SMU CV HI
36+
8 | BiasT SMU CV LO
37+
9 | BiasT SMU LO I CV HI
38+
10 | BiasT SMU LO I CV LO
39+
11 | BiasT SMU AC Ground
40+
41+
Ch1_Mode | Connection Mode
42+
Ch2_Mode | Connection Mode
43+
Ch3_Mode | Connection Mode
44+
Ch4_Mode | Connection Mode
45+
Ch1_TermName | Display Name for Ch1 Terminal (up to 6 characters will be displayed)
46+
Ch2_TermName | Display Name for Ch2 Terminal (up to 6 characters will be displayed)
47+
Ch3_TermName | Display Name for Ch3 Terminal (up to 6 characters will be displayed)
48+
Ch4_TermName | Display Name for Ch4 Terminal (up to 6 characters will be displayed)
49+
TestName | Display Name for Test (up to 16 characters will be displayed)
50+
"""
51+
# Call the cviv_configure user module for SMU measurements
52+
my4200.query("EX cvivulib cviv_configure (CVIV1, 1, 1, 1, 1, 1, Source, Drain, Gate, Bulk, IV, )")
53+
54+
# This is a loop to check the status of the test
55+
# The SP command returns 0 or 1 when the test is done running
56+
while True:
57+
status = my4200.query("SP")
58+
59+
# Continues loop until the test is complete
60+
# Casting the status string to int makes the comparison simpler since it ignores the termination characters
61+
if int(status) in [0, 1]:
62+
print("Setup Complete.")
63+
break
64+
65+
# Continously prints the status of the test every second to the terminal
66+
print(f"Status: {status}")
67+
time.sleep(1)
68+
69+
my4200.disconnect() # Close communications with the 4200A-SCS
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
"""
2+
This example performs both I-V and C-V measurements on an n-MOSFET using the 4200A-SCS.
3+
It uses the SMUs, CVU, and CVIV by calling the EX command.
4+
5+
1. CVIV Configure for SMU Measurements:
6+
Calls the cviv_configure user module by using the EX command. It configures the CVIV
7+
for connection to the SMUs.
8+
9+
2. Vds-Id (Family of Curves):
10+
This example performs a family of curves measurement using the 4200A-SCS.
11+
It sweeps drain voltage (0-5 V) and steps gate voltage (1-4 V) using SMU2 and SMU3,
12+
while SMU1 holds source at 0 V. Data is segmented and saved in a Clarius-like format.
13+
14+
3. CVIV Configure for CVU Measurements:
15+
Calls the cviv_configure user module by using the EX command. It configures the CVIV
16+
for connection to the CVU.
17+
18+
4. cv-nmosfet:
19+
This example performs a C-V sweep on a nMOSFET from 5 V to -5 V using the 4200A-SCS CVU. It will output a
20+
csv file containing the C-V measurements.
21+
Relies on plotly to plot the capacitance and voltage measurements.
22+
23+
Device used: 4-terminal DUT (e.g., nMOSFET) in 8101-PIV fixture
24+
"""
25+
26+
from instrcomms import Communications
27+
import pandas as pd
28+
import time
29+
30+
INST_RESOURCE_STR = "TCPIP0::192.0.2.0::1225::SOCKET" # Instrument resource string, obtained from NI MAX
31+
my4200 = Communications(INST_RESOURCE_STR) # Opens the resource manager in PyVISA with the corresponding instrument resource string
32+
my4200.connect() # Opens connections to the 4200A-SCS
33+
my4200._instrument_object.write_termination = "\0" # Set PyVISA write terminator
34+
my4200._instrument_object.read_termination = "\0" # Set PyVISA read terminator
35+
36+
my4200.query("UL")
37+
# Call the cviv_configure user module for SMU measurements
38+
my4200.query("EX cvivulib cviv_configure (CVIV1, 1, 1, 1, 1, 1, Source, Drain, Gate, Bulk, IV, )")
39+
40+
# This is a loop to check the status of the test
41+
# The SP command returns 0 or 1 when the test is done running
42+
while True:
43+
status = my4200.query("SP")
44+
45+
# Continues loop until the test is complete
46+
# Casting the status string to int makes the comparison simpler since it ignores the termination characters
47+
if int(status) in [0, 1]:
48+
print("Setup Complete.")
49+
break
50+
51+
# Continously prints the status of the test every second to the terminal
52+
print(f"Status: {status}")
53+
time.sleep(1)
54+
55+
# Start SMU family of curves measurement
56+
my4200.query("BC") # Clear all readings from the buffer
57+
my4200.query("DE") # Access the SMU channel definition page
58+
# Channel 1. Voltage Name = VS, Current Name = IS, Voltage Source Mode, Constant source function
59+
my4200.query("CH 1, 'VS', 'IS', 1, 3")
60+
# Channel 2. Voltage Name = VD, Current Name = ID, Voltage Source Mode, VAR1 sweep source function
61+
my4200.query("CH 2, 'VD', 'ID', 1, 1")
62+
# Channel 3. Voltage Name = VG, Current Name = IG, Voltage Source Mode, VAR2 sweep source function
63+
my4200.query("CH 3, 'VG', 'IG', 1, 2")
64+
my4200.query("SS") # Access the source setup page
65+
# Setup VAR1 source function, linear sweep, 0 V to 5 V, 0.1 V steps, 100 mA current compliance (SMU2)
66+
my4200.query("VR 1, 0, 5, 0.1, 100e-3")
67+
# Setup VAR2 step sweep, 1 V to 4 V, 4 total steps (step size 1 V), 100 mA current compliance (SMU3)
68+
my4200.query("VP 2, 1, 4, 100e-3")
69+
# Configure constant voltage, SMU channel 1, 0 V output value, 100 mA current compliance
70+
my4200.query("VC 1, 0, 100e-3")
71+
my4200.query("HT 0") # Set to a 0 second hold time
72+
my4200.query("DT 0.001") # Set to a 1 millisecond delay time
73+
my4200.query("IT2") # Set integration time to 1 PLC
74+
my4200.query("RS 5") # Sets the measurement resolution to 5 digits
75+
my4200.query("RG 1, 100e-9") # Set the lowest current range to be used on SMU 1 to 100 nA
76+
my4200.query("RG 2, 100e-9") # Set the lowest current range to be used on SMU 2 to 100 nA
77+
my4200.query("RG 3, 100e-9") # Set the lowest current range to be used on SMU 3 to 100 nA
78+
my4200.query("SM") # Access the measurement setup page
79+
my4200.query("DM2") # Selects the list display mode
80+
my4200.query("LI 'ID', 'VD','VG'") # Enable current function ID and voltage functions VD & VG in list display mode
81+
my4200.query("MD") # Access the measurement control page
82+
my4200.query("ME 1") # Maps channel 1
83+
84+
while True:
85+
status = my4200.query("SP")
86+
87+
if int(status) in [0, 1]:
88+
print("Measurement Complete.")
89+
break
90+
91+
print(f"Status: {status}")
92+
time.sleep(1)
93+
94+
# Specify what measurements to return
95+
var_returned = ["ID", "VD", "VG"]
96+
97+
# Define the number of segments for each measurements
98+
num_segments = 4 # Total number of lines
99+
readings_per_seg = (51) # Divide total number of readings by segments to get the readings per segment
100+
101+
102+
# Set custom data names
103+
custom_data_names = {"VD": "DrainV", "ID": "DrainI", "VG": "GateV"}
104+
105+
106+
# Function to retrieve measurements for each variable
107+
def retrieve_measurements(variable):
108+
index = 1
109+
measurements = []
110+
while True:
111+
data = my4200.query(f"RD '{variable}', {index}")
112+
if data == "0":
113+
break
114+
measurements.append(float(data))
115+
index += 1
116+
return measurements
117+
118+
119+
# Store all measurements in a dictionary
120+
all_measurements = {}
121+
for variable in var_returned:
122+
all_measurements[variable] = retrieve_measurements(variable)
123+
124+
# Split the measurements into segments
125+
seg_measurements = {} # Initalize segment measurements
126+
for (variables, meas) in all_measurements.items():
127+
seg_var_measurements = {} # Initialize segments for variable measurements
128+
for segment in range(1, num_segments + 1):
129+
start_index = (segment - 1) * readings_per_seg # Set start index
130+
end_index = segment * readings_per_seg # Set end index
131+
seg_name = custom_data_names.get(variables, f"{variables}({segment})") # Set custom data names
132+
seg_var_measurements[f"{seg_name}({segment})"] = meas[start_index:end_index] # Set the measurements to return
133+
seg_measurements.update(seg_var_measurements) # Append array for measurements
134+
135+
# Sort the columns in the order as shown in Clarius
136+
clarius_order = [
137+
"DrainI(1)",
138+
"DrainV(1)",
139+
"GateV(1)",
140+
"DrainI(2)",
141+
"DrainV(2)",
142+
"GateV(2)",
143+
"DrainI(3)",
144+
"DrainV(3)",
145+
"GateV(3)",
146+
"DrainI(4)",
147+
"DrainV(4)",
148+
"GateV(4)",
149+
]
150+
151+
# Create a DataFrame from the segmented measurements
152+
df_smu = pd.DataFrame(seg_measurements)
153+
154+
# Reorder the DataFrame
155+
df_smu = df_smu[clarius_order]
156+
157+
# Save the DataFrame into a CSV file
158+
df_smu.to_csv("vds-id.csv", index=False)
159+
print("Data saved to CSV file")
160+
161+
# Set the CVIV to CVU Measurements
162+
163+
my4200.query("UL")
164+
# Call the cviv_configure user module for CVU measurements
165+
my4200.query("EX cvivulib cviv_configure (CVIV1, 1, 3, 3, 2, 3, Source, Drain, Gate, Bulk, CV, )")
166+
167+
while True:
168+
status = my4200.query("SP")
169+
170+
if int(status) in [0, 1]:
171+
print("Setup Complete.")
172+
break
173+
174+
print(f"Status: {status}")
175+
time.sleep(1)
176+
177+
my4200.query(":CVU:RESET") # Resets the CVU card
178+
my4200.query(":CVU:MODE 1") # Sets the mode to System Mode
179+
my4200.query(":CVU:MODEL 2") # Sets the measurement model to Cp, Gp
180+
my4200.query(":CVU:SPEED 2") # Sets the measurement speed to quiet
181+
my4200.query(":CVU:ACZ:RANGE 0") # Sets the ac measurement range to autorange
182+
my4200.query(":CVU:FREQ 1E6") # Set the frequency to 1 MHz
183+
# Create a DC sweep, from 5 V to -5 V in 0.2 V steps, sample z measurements
184+
my4200.query(":CVU:SWEEP:DCV 5, -5, -0.2")
185+
my4200.query(":CVU:DELAY:SWEEP 0.1") # Set the delay sweep for 100 ms
186+
my4200.query(":CVU:TEST:RUN") # Starts the CVU test
187+
188+
while True:
189+
status = my4200.query("SP")
190+
191+
if int(status) in [0, 1]:
192+
print("Measurement Complete.")
193+
break
194+
195+
print(f"Status: {status}")
196+
time.sleep(1)
197+
198+
CpGp = my4200.query(":CVU:DATA:Z?") # Queries readings of Cp-Gp
199+
Volt = my4200.query(":CVU:DATA:VOLT?") # Queries readings of Voltage
200+
201+
# Assume CpGp and Volt are the raw strings returned from the instrument
202+
CpGpList = CpGp.strip().split("\n") # Split by newline
203+
VoltList = Volt.strip().split("\n") # Split by newline
204+
205+
# Extract only Cp values (before the semicolon)
206+
CapList = [line.split(";")[0] for line in CpGpList]
207+
208+
# Convert to float
209+
VoltList = [float(v) for v in VoltList]
210+
CapList = [float(c) for c in CapList]
211+
212+
df_cvu = pd.DataFrame({"Voltage (V)": VoltList, "Capacitance (F)": CapList})
213+
df_cvu.to_csv("cv-nmosfet.csv", index=False)
214+
print("Data saved to CSV file")
215+
216+
my4200.disconnect() # Close communications with the 4200A-SCS

0 commit comments

Comments
 (0)