m-teng/m_teng/backends/keithley/measure.py

94 lines
3.6 KiB
Python
Raw Permalink Normal View History

2023-06-18 17:38:10 +02:00
from time import sleep
import numpy as np
from matplotlib import pyplot as plt
import pyvisa
2023-06-27 15:22:48 +02:00
from m_teng.backends.keithley.keithley import reset
2023-06-24 12:28:21 +02:00
from m_teng.utility import testing as _testing
2023-06-18 17:38:10 +02:00
def measure_count(instr, count=100, interval=0.05, update_func=None, update_interval=0.5, beep_done=True, verbose=True):
"""
Take <count> measurements with <interval> inbetween
@details
Uses the devices overlappedY function to make the measurements asynchronosly
The update_func is optional and only used when I == True and V == True
The update_func does not necessarily get all the values that are measured. To obtain the whole measurement, get them from the device buffers (smua.nvbufferX)
@param instr: pyvisa instrument
@param update_func: Callable that processes the measurements: (index, ival, vval) -> None
@param update_interval: interval at which the update_func is called
"""
f_meas = "smua.measure.overlappediv(smua.nvbuffer1, smua.nvbuffer2)"
# if V and I:
# elif V:
# f_meas = "smua.measure.overlappedv(smua.nvbuffer1)"
# elif I:
# f_meas = "smua.measure.overlappedi(smua.nvbuffer1)"
# else:
# print("I and/or V needs to be set to True")
# return
i = 0
reset(instr, verbose=verbose)
instr.write(f"smua.measure.count = {count}")
instr.write(f"smua.measure.interval = {interval}")
# start measurement
instr.write(f"smua.source.output = smua.OUTPUT_ON")
instr.write(f_meas)
sleep(update_interval)
# for live viewing
query = """if smua.nvbufferX.n > 0 then print(smua.nvbufferX.readings[smua.nvbufferX.n]) else print(0) end"""
# will return 2.0 while measruing
while float(instr.query("print(status.operation.measuring.condition)").strip("\n ")) != 0:
if update_func:
try:
ival = float(instr.query(query.replace("X", "1")).strip("\n"))
vval = float(instr.query(query.replace("X", "2")).strip("\n"))
update_func(i, ival, vval)
except ValueError as e:
if i != 0:
pass
else:
print(f"measure_count: ValueError: {e}")
sleep(update_interval)
i += 1
instr.write(f"smua.source.output = smua.OUTPUT_OFF")
if beep_done:
instr.write("beeper.beep(0.3, 1000)")
def measure(instr, interval, update_func=None, max_measurements=None):
"""
@details:
- Resets the buffers
- Until KeyboardInterrupt:
- Take measurement
- Call update_func
- Wait interval
Uses python's time.sleep() for waiting the interval, which is not very precise. Use measure_count for better precision
You can take the data from the buffer afterwards, using save_csv
@param instr: pyvisa instrument
@param update_func: Callable that processes the measurements: (index, ival, vval) -> None
@param max_measurements : maximum number of measurements. None means infinite
"""
reset(instr, verbose=True)
instr.write("smua.source.output = smua.OUTPUT_ON")
instr.write("format.data = format.ASCII\nformat.asciiprecision = 12")
try:
i = 0
while max_measurements is None or i < max_measurements:
ival, vval = tuple(float(v) for v in instr.query("print(smua.measure.iv(smua.nvbuffer1, smua.nvbuffer2))").strip('\n').split('\t'))
if update_func:
update_func(i, ival, vval)
sleep(interval)
i += 1
except KeyboardInterrupt:
pass
instr.write("smua.source.output = smua.OUTPUT_OFF")
print("Measurement stopped" + " "*50)