use iv instead of v curves
This commit is contained in:
parent
579d69f92a
commit
da49bf68d6
@ -1,6 +1,10 @@
|
|||||||
"""
|
"""
|
||||||
run this before using this library:
|
run this before using this library:
|
||||||
ipython -i keithley_interactive.py
|
ipython -i keithley_interactive.py
|
||||||
|
|
||||||
|
always records iv-t curves
|
||||||
|
i-data -> smua.nvbuffer1
|
||||||
|
v-data -> smua.nvbuffer2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -25,7 +29,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
|
|
||||||
from .keithley import keithley as _keithley
|
from .keithley import keithley as _keithley
|
||||||
from .utility import data
|
from .utility import data as _data
|
||||||
from .utility import file_io
|
from .utility import file_io
|
||||||
from .utility import testing
|
from .utility import testing
|
||||||
|
|
||||||
@ -61,49 +65,71 @@ def _measure(max_measurements=None, max_points_shown=None, monitor=False):
|
|||||||
global k, settings, test, _runtime_vars
|
global k, settings, test, _runtime_vars
|
||||||
print(f"Starting measurement with:\n\tinterval = {settings['interval']}s\nUse <C-c> to stop. Save the data using 'save_csv()' afterwards.")
|
print(f"Starting measurement with:\n\tinterval = {settings['interval']}s\nUse <C-c> to stop. Save the data using 'save_csv()' afterwards.")
|
||||||
_runtime_vars["last_measurement"] = dtime.now().isoformat()
|
_runtime_vars["last_measurement"] = dtime.now().isoformat()
|
||||||
|
if not test:
|
||||||
|
_keithley.reset(k, verbose=True)
|
||||||
|
k.write("smua.source.output = 1")
|
||||||
|
k.write("format.data = format.ASCII\nformat.asciiprecision = 12")
|
||||||
# jupyter:
|
# jupyter:
|
||||||
# clear_output(wait=True)
|
# clear_output(wait=True)
|
||||||
# plt.plot(data)
|
# plt.plot(data)
|
||||||
# plt.show()
|
# plt.show()
|
||||||
index = []
|
index = []
|
||||||
data = []
|
vdata = []
|
||||||
|
idata = []
|
||||||
if monitor:
|
if monitor:
|
||||||
plt.ion()
|
plt.ion()
|
||||||
fig = plt.figure()
|
fig1, (vax, iax) = plt.subplots(2, 1)
|
||||||
ax = fig.add_subplot(ylabel="Voltage [V]")
|
|
||||||
line1, = ax.plot(index, data)
|
vline, = vax.plot(index, vdata, color="g")
|
||||||
|
vax.set_ylabel("Voltage [V]")
|
||||||
|
vax.grid(True)
|
||||||
|
|
||||||
|
iline, = iax.plot(index, idata, color="m")
|
||||||
|
iax.set_ylabel("Current [A]")
|
||||||
|
iax.grid(True)
|
||||||
try:
|
try:
|
||||||
i = 0
|
i = 0
|
||||||
while max_measurements is None or i < max_measurements:
|
while max_measurements is None or i < max_measurements:
|
||||||
index.append(i)
|
index.append(i)
|
||||||
if test:
|
if test:
|
||||||
data.append(testing.testcurve(i))
|
idata.append(testing.testcurve(i, peak_width=1, amplitude=5e-8))
|
||||||
# data.append(tuple(float(v) for v in instr.query("print(smua.measure.v())").strip('\n').split('\t')))
|
vdata.append(-testing.testcurve(i, peak_width=2, amplitude=15))
|
||||||
else:
|
|
||||||
data.append(k.query("print(smua.measure.v())").strip('\n'))
|
|
||||||
# data.append(np.random.rand())
|
# data.append(np.random.rand())
|
||||||
print(f"{i:5d} - {data[-1]:.5f} V", end='\r')
|
else:
|
||||||
|
# data.append(float(k.query("print(smua.measure.v(smua.nvbuffer1))").strip('\n')))
|
||||||
|
i_val, v_val = tuple(float(v) for v in k.query("print(smua.measure.iv(smua.nvbuffer1, smua.nvbuffer2))").strip('\n').split('\t'))
|
||||||
|
idata.append(i_val)
|
||||||
|
vdata.append(v_val)
|
||||||
|
print(f"{i:5d} - {idata[-1]:.12f} A - {vdata[-1]:.5f} V", end='\r')
|
||||||
if monitor:
|
if monitor:
|
||||||
# update data
|
# update data
|
||||||
line1.set_xdata(index)
|
iline.set_xdata(index)
|
||||||
line1.set_ydata(data)
|
iline.set_ydata(idata)
|
||||||
|
vline.set_xdata(index)
|
||||||
|
vline.set_ydata(vdata)
|
||||||
# recalculate limits and set them for the view
|
# recalculate limits and set them for the view
|
||||||
ax.relim()
|
iax.relim()
|
||||||
|
vax.relim()
|
||||||
if max_points_shown and i > max_points_shown:
|
if max_points_shown and i > max_points_shown:
|
||||||
ax.set_xlim(i - max_points_shown, i)
|
iax.set_xlim(i - max_points_shown, i)
|
||||||
ax.autoscale_view()
|
vax.set_xlim(i - max_points_shown, i)
|
||||||
|
iax.autoscale_view()
|
||||||
|
vax.autoscale_view()
|
||||||
# update plot
|
# update plot
|
||||||
fig.canvas.draw()
|
fig1.canvas.draw()
|
||||||
fig.canvas.flush_events()
|
fig1.canvas.flush_events()
|
||||||
sleep(settings["interval"])
|
sleep(settings["interval"])
|
||||||
i += 1
|
i += 1
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
if not test:
|
||||||
|
k.write("smua.source.output = 0")
|
||||||
if monitor:
|
if monitor:
|
||||||
plt.close(fig)
|
plt.close(fig1)
|
||||||
print("Measurement stopped" + " "*50)
|
print("Measurement stopped" + " "*50)
|
||||||
|
return vdata, idata
|
||||||
|
|
||||||
|
|
||||||
def monitor(max_measurements=None, max_points_shown=None, ):
|
def monitor(max_measurements=None, max_points_shown=160):
|
||||||
"""
|
"""
|
||||||
Monitor the voltage with matplotlib.
|
Monitor the voltage with matplotlib.
|
||||||
|
|
||||||
@ -131,17 +157,23 @@ def measure(max_measurements=None):
|
|||||||
|
|
||||||
|
|
||||||
def get_dataframe():
|
def get_dataframe():
|
||||||
|
"""
|
||||||
|
Get a pandas dataframe from the data in smua.nvbuffer1
|
||||||
|
"""
|
||||||
global k, settings, _runtime_vars
|
global k, settings, _runtime_vars
|
||||||
if test:
|
if test:
|
||||||
timestamps = np.arange(0, 50, 0.01)
|
timestamps = np.arange(0, 50, 0.01)
|
||||||
ydata = np.array([testing.testcurve(t) for t in timestamps])
|
ydata = np.array([testing.testcurve(t, amplitude=15, peak_width=2) for t in timestamps])
|
||||||
buffer = np.vstack((timestamps, ydata)).T
|
ibuffer = np.vstack((timestamps, ydata)).T
|
||||||
|
|
||||||
|
ydata = np.array([-testing.testcurve(t, amplitude=5e-8, peak_width=1) for t in timestamps])
|
||||||
|
vbuffer = np.vstack((timestamps, ydata)).T
|
||||||
else:
|
else:
|
||||||
buffer = _keithley.collect_buffer(k, 1)
|
ibuffer = _keithley.collect_buffer(k, 1)
|
||||||
df = data.buffer2dataframe(buffer)
|
vbuffer = _keithley.collect_buffer(k, 2)
|
||||||
|
df = _data.buffers2dataframe(ibuffer, vbuffer)
|
||||||
df.basename = file_io.get_next_filename(settings["name"], settings["datadir"])
|
df.basename = file_io.get_next_filename(settings["name"], settings["datadir"])
|
||||||
df.name = f"{df.basename} @ {_runtime_vars['last-measurement']}"
|
df.name = f"{df.basename} @ {_runtime_vars['last-measurement']}"
|
||||||
df.columns = ["Time [s]", "Voltage [V]"]
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def save_csv():
|
def save_csv():
|
||||||
@ -201,6 +233,9 @@ def set(setting, value):
|
|||||||
return
|
return
|
||||||
settings[setting] = value
|
settings[setting] = value
|
||||||
|
|
||||||
|
def name(s:str):
|
||||||
|
global settings
|
||||||
|
settings["name"] = s
|
||||||
|
|
||||||
def save_settings():
|
def save_settings():
|
||||||
with open(config_path, "w") as file:
|
with open(config_path, "w") as file:
|
||||||
@ -218,6 +253,7 @@ def help(topic=None):
|
|||||||
Functions:
|
Functions:
|
||||||
measure - measure the voltage
|
measure - measure the voltage
|
||||||
monitor - measure the voltage with live monitoring in a matplotlib window
|
monitor - measure the voltage with live monitoring in a matplotlib window
|
||||||
|
get_dataframe - return smua.nvbuffer1 as pandas dataframe
|
||||||
save_csv - save the last measurement as csv file
|
save_csv - save the last measurement as csv file
|
||||||
save_pickle - save the last measurement as pickled pandas dataframe
|
save_pickle - save the last measurement as pickled pandas dataframe
|
||||||
load_dataframe - load a pandas dataframe from csv or pickle
|
load_dataframe - load a pandas dataframe from csv or pickle
|
||||||
@ -238,9 +274,10 @@ Run 'help("topic")' to see more information on a topic""")
|
|||||||
beep: bool - wether the device should beep or not
|
beep: bool - wether the device should beep or not
|
||||||
|
|
||||||
Functions:
|
Functions:
|
||||||
TODO set("setting", value) - set a setting to a value
|
name("<name>") - short for set("name", "<name>")
|
||||||
TODO save_settings() - store the settings as "k-teng.conf" in the working directory
|
set("setting", value) - set a setting to a value
|
||||||
TODO load_settings() - load settings from a file
|
save_settings() - store the settings as "k-teng.conf" in the working directory
|
||||||
|
load_settings() - load settings from a file
|
||||||
The global variable 'config_path' determines the path used by save/load_settings. Use -c '<path>' to set another path.
|
The global variable 'config_path' determines the path used by save/load_settings. Use -c '<path>' to set another path.
|
||||||
The serach path is:
|
The serach path is:
|
||||||
<working-dir>/k-teng.json
|
<working-dir>/k-teng.json
|
||||||
|
@ -5,7 +5,7 @@ import numpy as np
|
|||||||
"""
|
"""
|
||||||
Utility
|
Utility
|
||||||
"""
|
"""
|
||||||
script_dir = "scripts/"
|
script_dir = "../scripts/"
|
||||||
scripts = {
|
scripts = {
|
||||||
"buffer_reset": "buffer_reset.lua",
|
"buffer_reset": "buffer_reset.lua",
|
||||||
"smua_reset": "smua_reset.lua",
|
"smua_reset": "smua_reset.lua",
|
||||||
@ -54,7 +54,7 @@ def reset(instr, verbose=False):
|
|||||||
run_lua(instr, scripts["buffer_reset"], verbose=verbose)
|
run_lua(instr, scripts["buffer_reset"], verbose=verbose)
|
||||||
|
|
||||||
|
|
||||||
def collect_buffer(instr, buffer_nr=1):
|
def collect_buffer(instr, buffer_nr=1, verbose=False):
|
||||||
"""
|
"""
|
||||||
Get the buffer as 2D - np.array
|
Get the buffer as 2D - np.array
|
||||||
@param instr : pyvisa instrument
|
@param instr : pyvisa instrument
|
||||||
@ -71,7 +71,8 @@ def collect_buffer(instr, buffer_nr=1):
|
|||||||
instr.write("format.data = format.ASCII\nformat.asciiprecision = 7")
|
instr.write("format.data = format.ASCII\nformat.asciiprecision = 7")
|
||||||
timestamps = instr.query_ascii_values(f"printbuffer(1, {buffername}.n, {buffername}.timestamps)", container=np.array)
|
timestamps = instr.query_ascii_values(f"printbuffer(1, {buffername}.n, {buffername}.timestamps)", container=np.array)
|
||||||
readings = instr.query_ascii_values(f"printbuffer(1, {buffername}.n, {buffername}.readings)", container=np.array)
|
readings = instr.query_ascii_values(f"printbuffer(1, {buffername}.n, {buffername}.readings)", container=np.array)
|
||||||
print(f"readings: {readings}, \ntimestamps: {timestamps}")
|
if verbose:
|
||||||
|
print(f"readings from {buffername}: {readings}, \ntimestamps: {timestamps}")
|
||||||
buffer = np.vstack((timestamps, readings)).T
|
buffer = np.vstack((timestamps, readings)).T
|
||||||
return buffer
|
return buffer
|
||||||
|
|
||||||
|
@ -6,3 +6,12 @@ def buffer2dataframe(buffer):
|
|||||||
df.colums = ["Time [s]", "Voltage [V]"]
|
df.colums = ["Time [s]", "Voltage [V]"]
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
def buffers2dataframe(ibuffer, vbuffer):
|
||||||
|
"""
|
||||||
|
@param ibuffer : 2d - array: timestamps, current
|
||||||
|
@param vbuffer : 2d - array: timestamps, voltage
|
||||||
|
@returns DataFrame: timestamps, current, voltage
|
||||||
|
"""
|
||||||
|
df = pd.DataFrame(np.vstack((ibuffer[:,0], ibuffer[:,1], vbuffer[:,1])).T)
|
||||||
|
df.columns = ["Time [s]", "Current [A]", "Voltage [V]"]
|
||||||
|
return df
|
||||||
|
@ -2,12 +2,24 @@
|
|||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": 1,
|
||||||
"id": "d1bb781f-f286-44cf-a3e3-181e06281487",
|
"id": "d1bb781f-f286-44cf-a3e3-181e06281487",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"tags": []
|
"tags": []
|
||||||
},
|
},
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
|
{
|
||||||
|
"ename": "ModuleNotFoundError",
|
||||||
|
"evalue": "No module named 'keithley'",
|
||||||
|
"output_type": "error",
|
||||||
|
"traceback": [
|
||||||
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||||
|
"\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
|
||||||
|
"Cell \u001b[0;32mIn[1], line 12\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mmatplotlib\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m pyplot \u001b[38;5;28;01mas\u001b[39;00m plt\n\u001b[1;32m 11\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mnumpy\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mnp\u001b[39;00m\n\u001b[0;32m---> 12\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mkeithley\u001b[39;00m\n\u001b[1;32m 13\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mfile_io\u001b[39;00m\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mmeasure\u001b[39;00m\n",
|
||||||
|
"\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'keithley'"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"\"\"\"\n",
|
"\"\"\"\n",
|
||||||
"INIT:connect to keithley\n",
|
"INIT:connect to keithley\n",
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
-- reset smua
|
-- reset smua
|
||||||
smua.reset()
|
smua.reset()
|
||||||
smua.measure.autorangev = smua.AUTORANGE_ON
|
smua.measure.autorangev = smua.AUTORANGE_ON
|
||||||
|
smua.measure.autorangei = smua.AUTORANGE_ON
|
||||||
smua.measure.autozero = smua.AUTOZERO_ONCE
|
smua.measure.autozero = smua.AUTOZERO_ONCE
|
||||||
-- set output to 0A DC
|
-- set output to 0A DC
|
||||||
smua.source.output = smua.OUTPUT_OFF
|
smua.source.output = smua.OUTPUT_OFF
|
||||||
smua.source.func = smua.OUTPUT_DCAMPS
|
smua.source.func = smua.OUTPUT_DCAMPS
|
||||||
smua.source.leveli = smua.OUTPUT_OFF
|
smua.source.leveli = smua.OUTPUT_OFF
|
||||||
|
|
||||||
-- smua.measure.rangev = 20
|
|
||||||
|
Loading…
Reference in New Issue
Block a user