use iv instead of v curves

This commit is contained in:
Matthias@Dell 2023-04-13 17:50:40 +02:00
parent 579d69f92a
commit da49bf68d6
5 changed files with 93 additions and 35 deletions

View File

@ -1,6 +1,10 @@
"""
run this before using this library:
ipython -i keithley_interactive.py
always records iv-t curves
i-data -> smua.nvbuffer1
v-data -> smua.nvbuffer2
"""
import numpy as np
@ -25,7 +29,7 @@ if __name__ == "__main__":
from .keithley import keithley as _keithley
from .utility import data
from .utility import data as _data
from .utility import file_io
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
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()
if not test:
_keithley.reset(k, verbose=True)
k.write("smua.source.output = 1")
k.write("format.data = format.ASCII\nformat.asciiprecision = 12")
# jupyter:
# clear_output(wait=True)
# plt.plot(data)
# plt.show()
index = []
data = []
vdata = []
idata = []
if monitor:
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(ylabel="Voltage [V]")
line1, = ax.plot(index, data)
fig1, (vax, iax) = plt.subplots(2, 1)
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:
i = 0
while max_measurements is None or i < max_measurements:
index.append(i)
if test:
data.append(testing.testcurve(i))
# data.append(tuple(float(v) for v in instr.query("print(smua.measure.v())").strip('\n').split('\t')))
else:
data.append(k.query("print(smua.measure.v())").strip('\n'))
idata.append(testing.testcurve(i, peak_width=1, amplitude=5e-8))
vdata.append(-testing.testcurve(i, peak_width=2, amplitude=15))
# 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:
# update data
line1.set_xdata(index)
line1.set_ydata(data)
iline.set_xdata(index)
iline.set_ydata(idata)
vline.set_xdata(index)
vline.set_ydata(vdata)
# recalculate limits and set them for the view
ax.relim()
iax.relim()
vax.relim()
if max_points_shown and i > max_points_shown:
ax.set_xlim(i - max_points_shown, i)
ax.autoscale_view()
iax.set_xlim(i - max_points_shown, i)
vax.set_xlim(i - max_points_shown, i)
iax.autoscale_view()
vax.autoscale_view()
# update plot
fig.canvas.draw()
fig.canvas.flush_events()
fig1.canvas.draw()
fig1.canvas.flush_events()
sleep(settings["interval"])
i += 1
except KeyboardInterrupt:
if not test:
k.write("smua.source.output = 0")
if monitor:
plt.close(fig)
plt.close(fig1)
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.
@ -131,17 +157,23 @@ def measure(max_measurements=None):
def get_dataframe():
"""
Get a pandas dataframe from the data in smua.nvbuffer1
"""
global k, settings, _runtime_vars
if test:
timestamps = np.arange(0, 50, 0.01)
ydata = np.array([testing.testcurve(t) for t in timestamps])
buffer = np.vstack((timestamps, ydata)).T
ydata = np.array([testing.testcurve(t, amplitude=15, peak_width=2) for t in timestamps])
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:
buffer = _keithley.collect_buffer(k, 1)
df = data.buffer2dataframe(buffer)
ibuffer = _keithley.collect_buffer(k, 1)
vbuffer = _keithley.collect_buffer(k, 2)
df = _data.buffers2dataframe(ibuffer, vbuffer)
df.basename = file_io.get_next_filename(settings["name"], settings["datadir"])
df.name = f"{df.basename} @ {_runtime_vars['last-measurement']}"
df.columns = ["Time [s]", "Voltage [V]"]
return df
def save_csv():
@ -201,6 +233,9 @@ def set(setting, value):
return
settings[setting] = value
def name(s:str):
global settings
settings["name"] = s
def save_settings():
with open(config_path, "w") as file:
@ -218,9 +253,10 @@ def help(topic=None):
Functions:
measure - measure the voltage
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_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
run_script - run a lua script on the Keithely device
Run 'help(function)' to see more information on a function
@ -238,9 +274,10 @@ Run 'help("topic")' to see more information on a topic""")
beep: bool - wether the device should beep or not
Functions:
TODO set("setting", value) - set a setting to a value
TODO save_settings() - store the settings as "k-teng.conf" in the working directory
TODO load_settings() - load settings from a file
name("<name>") - short for set("name", "<name>")
set("setting", value) - set a setting to a value
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 serach path is:
<working-dir>/k-teng.json

View File

@ -5,7 +5,7 @@ import numpy as np
"""
Utility
"""
script_dir = "scripts/"
script_dir = "../scripts/"
scripts = {
"buffer_reset": "buffer_reset.lua",
"smua_reset": "smua_reset.lua",
@ -54,7 +54,7 @@ def reset(instr, verbose=False):
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
@param instr : pyvisa instrument
@ -71,7 +71,8 @@ def collect_buffer(instr, buffer_nr=1):
instr.write("format.data = format.ASCII\nformat.asciiprecision = 7")
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)
print(f"readings: {readings}, \ntimestamps: {timestamps}")
if verbose:
print(f"readings from {buffername}: {readings}, \ntimestamps: {timestamps}")
buffer = np.vstack((timestamps, readings)).T
return buffer

View File

@ -6,3 +6,12 @@ def buffer2dataframe(buffer):
df.colums = ["Time [s]", "Voltage [V]"]
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

View File

@ -2,12 +2,24 @@
"cells": [
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"id": "d1bb781f-f286-44cf-a3e3-181e06281487",
"metadata": {
"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": [
"\"\"\"\n",
"INIT:connect to keithley\n",

View File

@ -1,10 +1,9 @@
-- reset smua
smua.reset()
smua.measure.autorangev = smua.AUTORANGE_ON
smua.measure.autorangei = smua.AUTORANGE_ON
smua.measure.autozero = smua.AUTOZERO_ONCE
-- set output to 0A DC
smua.source.output = smua.OUTPUT_OFF
smua.source.func = smua.OUTPUT_DCAMPS
smua.source.leveli = smua.OUTPUT_OFF
-- smua.measure.rangev = 20