Keithley SourceMeter测量电流值无法传输至电脑问题咨询及代码排查求助
问题原因分析
你碰到的这个问题其实很常见——ser.write()方法的返回值并不是设备的响应数据,而是你发送出去的字节数。这就是为什么你得到的总是:READ?\r\n这条命令的字符数,完全和电流值没关系。
要获取Keithley返回的电流数据,你需要在发送查询命令后,主动去读取串口缓冲区里设备发回来的响应内容,而不是直接拿write的返回值。
代码修正方案
我给你调整了关键部分的代码,同时补充了一些必要的设置,确保能稳定读取到正确的电流值:
1. 先完善串口初始化(增加超时设置)
在打开串口之前,加上超时配置,避免读取操作一直卡住:
ser = serial.Serial() ser.port = 'COM3' ser.baudrate = 9600 ser.timeout = 2 # 设置2秒超时,可根据实际情况调整 ser.open()
2. 修正电流读取的核心逻辑
把原来错误的一行拆成几步,先发送命令,再读取响应,最后转换成数值:
# 原来的错误代码 # current = ser.write(str.encode(':READ?'+'\r\n')) #measure current # 修正后的代码 # 发送电流查询命令 ser.write(str.encode(':READ?'+'\r\n')) # 读取设备返回的响应(Keithley通常用\r\n作为终止符) response_bytes = ser.read_until(b'\r\n') # 把字节数据转成字符串,同时去掉首尾的空白字符(比如换行符) response_str = response_bytes.decode('utf-8').strip() # 转换成浮点数类型的电流值 current = float(response_str) currents.append(current) #record current
3. 可选优化:合并重复的SCPI命令
你在循环里反复发送:SOUR:FUNC VOLT、:SOUR:VOLT:MODE FIX这些配置命令,其实这些只需要在循环前执行一次就够了,没必要每次循环都发,这样能提高测试效率:
# 把这些配置命令移到循环外面 ser.write(str.encode(':SOUR:FUNC VOLT'+'\r\n')) ser.write(str.encode(':SOUR:VOLT:MODE FIX'+'\r\n')) ser.write(str.encode(':SOUR:VOLT:RANG 20'+'\r\n')) ser.write(str.encode(':SENS:FUNC "CURR"'+'\r\n')) ser.write(str.encode(':SENS:CURR:PROT 10e-1'+'\r\n')) ser.write(str.encode(':SENS:CURR:RANG 10e-1'+'\r\n')) ser.write(str.encode(':SENS:CURR:RANG:AUTO ON'+'\r\n')) for iterations in range(numberofiterations): #record voltage voltages.append(round(voltage,5)) #supply voltage ser.write(str.encode(':SOUR:VOLT:LEV '+str(voltage)+'\r\n')) #wait time.sleep(1) #measure current(用上面修正后的代码) ...
完整修正后的代码
import pyvisa import time import serial # configure the serial connections (the parameters differs on the device you are connecting to) ser = serial.Serial() ser.port = 'COM3' ser.baudrate = 9600 ser.timeout = 2 # 添加超时设置 ser.open() print(f"串口是否打开: {ser.isOpen()}") # 打印确认串口状态 ###Sweep numberofiterations = 10 stepsize = 0.05 voltage = 0 currents = [] voltages = [] ser.write(str.encode('*RST' + '\r\n')) ser.write(str.encode(':OUTP ON'+'\r\n')) # 提前发送所有固定配置命令,避免循环内重复发送 ser.write(str.encode(':SOUR:FUNC VOLT'+'\r\n')) ser.write(str.encode(':SOUR:VOLT:MODE FIX'+'\r\n')) ser.write(str.encode(':SOUR:VOLT:RANG 20'+'\r\n')) ser.write(str.encode(':SENS:FUNC "CURR"'+'\r\n')) ser.write(str.encode(':SENS:CURR:PROT 10e-1'+'\r\n')) ser.write(str.encode(':SENS:CURR:RANG 10e-1'+'\r\n')) ser.write(str.encode(':SENS:CURR:RANG:AUTO ON'+'\r\n')) for iterations in range(numberofiterations): #record voltage voltages.append(round(voltage,5)) #supply voltage ser.write(str.encode(':SOUR:VOLT:LEV '+str(voltage)+'\r\n')) #wait time.sleep(1) #measure current ser.write(str.encode(':READ?'+'\r\n')) response_bytes = ser.read_until(b'\r\n') response_str = response_bytes.decode('utf-8').strip() current = float(response_str) currents.append(current) #record current #increase voltage voltage += stepsize #Print out values print("读取到的电流值:") for curr in currents: print(curr) print("\n设置的电压值:") for volt in voltages: print(volt) # 测试结束后关闭串口 ser.close()
额外注意事项
- 如果发现读取到的响应是空的或者不完整,可以适当调整
ser.timeout的数值,或者在发送命令后加个短暂的time.sleep(0.5)给设备足够的响应时间(不过超时机制更可靠)。 - 可以查看Keithley的官方手册,确认
:READ?命令的返回格式——有些型号可能返回多个值(比如电压+电流),这时候你需要把字符串按逗号分割再转换数值。不过根据你的描述,设备屏幕显示正确的电流值,所以应该是单个数值返回。
内容的提问来源于stack exchange,提问作者Stella
相关产品推荐
相关产品推荐

