Keithley2400通过RS232做IV扫描时扩展:FETCh?返回长度的求助
问题解决方案
首先明确核心误解:手册中"You can specify from one to all five elements."指的是单次测量返回的数据字段类型(可选电压、电流、电阻、时间、状态共5类),和扫描的测量点数无关,你的问题是由代码逻辑和SCPI命令调用错误导致的。
问题根因
- 资源调用缩进错误:你使用
with rm.open_resource('COM3') as Keithley打开连接后,所有后续通信代码都写在了with块之外,with块结束后串口资源已经自动释放,后续命令交互实际是异常的,返回的是残留缓存的固定5条数据。 - 读取逻辑错误:
:READ?命令会直接触发扫描并返回所有测量结果,你调用后没有接收结果,再调用:FETCh?只能读取到缓存中残留的前5个点。 - 命令拼接错误:SCPI命令和参数之间需要严格保留空格,你直接拼接字符串的写法容易出现格式错误,同时
*IDN?发送后没有读取返回值,会导致后续读取数据时出现错位。 - x值生成逻辑错误:
np.arange用浮点数步进容易出现精度问题,导致最终生成的x值数量和设置的扫描步数不匹配。
修复后的完整代码
import sys import pyvisa import numpy as np import matplotlib.pyplot as plt # 读取命令行参数 startv = float(sys.argv[1]) stopv = float(sys.argv[2]) stepv = float(sys.argv[3]) filename = sys.argv[4] steps = int((stopv - startv) / stepv + 1) # 初始化VISA资源,所有通信逻辑都放在with块内 rm = pyvisa.ResourceManager() with rm.open_resource('COM3') as Keithley: # 配置串口参数 Keithley.baudrate = 9600 Keithley.timeout = 25000 Keithley.read_termination = '\r' Keithley.write_termination = '\r' # 复位设备 Keithley.write("*RST") # 读取IDN,避免缓存残留 idn = Keithley.query("*IDN?") print(f"已连接设备:{idn}") # 配置源表工作模式 Keithley.write(":SENS:FUNC:CONC OFF") Keithley.write(":SOUR:FUNC VOLT") Keithley.write(":SENS:FUNC 'CURR:DC'") # 配置扫描参数 Keithley.write(":SOUR:VOLT:START %f" % startv) Keithley.write(":SOUR:VOLT:STOP %f" % stopv) Keithley.write(":SOUR:VOLT:STEP %f" % stepv) Keithley.write(":SOUR:SWE:RANG AUTO") Keithley.write(":SENS:CURR:PROT 0.1") Keithley.write(":SOUR:SWE:SPAC LIN") Keithley.write(":SOUR:SWE:POIN %d" % steps) Keithley.write(":SOUR:SWE:DIR UP") Keithley.write(":TRIG:COUN %d" % steps) # 配置返回值只包含电流 Keithley.write(":FORM:ELEM CURR") Keithley.write(":SOUR:VOLT:MODE SWE") Keithley.write(":OUTP ON") # 直接读取:READ?返回的所有电流值,不需要额外调用FETCh? yvalues = Keithley.query_ascii_values(":READ?") print(f"实际读取到的测量点数:{len(yvalues)}") Keithley.write(":OUTP OFF") Keithley.write(":SOUR:VOLT 0") # 生成匹配步数的x值,用linspace避免浮点数精度问题 xvalues = np.linspace(startv, stopv, steps) # 单位转换为mA yvalues = np.array(yvalues) * 1000 # 绘图 plt.plot(xvalues, yvalues) plt.xlabel('Drain-Source Voltage (V)') plt.ylabel('Drain-Source Current (mA)') plt.title('IV Curve') plt.grid(True) plt.show() # 保存数据 np.savetxt(filename, np.column_stack((xvalues, yvalues)), header='V, mA')
额外注意事项
- 如果还是出现点数不匹配的情况,可发送命令
:FORM:DATA ASCII明确指定返回格式为ASCII,避免二进制解析错误 - 扫描步数如果超过100,建议适当调高timeout参数,避免扫描未完成就触发超时报错
内容的提问来源于stack exchange,提问作者KWON
相关产品推荐
相关产品推荐

