Agilent 34401A台式万用表远程读表
Agilent 34401A台式万用表支持RS232和GPIB的方式读数据。
一、RS232读表
将台式万用表的模式调为RS232-9600-8-1-none

测试代码
class MultimeterStrategy:
def __init__(self, port, baudrate=9600):
self.port = port
self.baudrate = baudrate
self.serial = None
self.retry_max = 5
def connect(self):
self.serial = serial.Serial()
self.serial.port = self.port
self.serial.baudrate = self.baudrate
self.serial.timeout = 0.05
try:
self.serial.open()
print(f"Connected to multimeter at {self.port} with baudrate {self.baudrate}")
self.serial.write(b"*CLS\n")
#self.serial.write(b"MEAS:VOLT:DC?AUTO,MIN\n")
self.serial.write(b"SYSTEM:REMOTE\n")
time.sleep(1)
read_data = self._read() #前两次读不到数据,未知原因
read_data = self._read()
except serial.SerialException as e:
print(f"Failed to connect to multimeter at {self.port}: {e}")
self.serial = None
def disconnect(self):
if self.serial:
self.serial.close()
print("Disconnected from multimeter")
self.serial = None
def _read(self):
if not self.serial:
print("Serial port is not connected")
return None
try:
self.serial.write(b'READ?\n')
time.sleep(0.1)
result = self.serial.read(100)
if result:
result_str = result.decode('utf-8', errors='ignore').strip()
try:
result_float = float(result_str)
#print(f"测量结果: {result_float}")
return result_float
except ValueError as e:
print(f"无法将字符串转换为浮点数: {result_str}")
time.sleep(0.5)
else:
print("未读取到测量数据")
time.sleep(1)
except serial.SerialException as e:
print(f"Error reading from multimeter: {e}")
return None
def read(self):
data = []
errcnt = 0
okcnt = 0
self.serial.write(b"SYSTEM:REMOTE\n")
time.sleep(1)
while True:
read_data = self._read()
if read_data is not None:
print(f"测量{okcnt}结果: {read_data}")
data.append(read_data)
okcnt += 1
errcnt = 0
time.sleep(1)
else:
errcnt += 1
if errcnt > self.retry_max:
print("Exceeded maximum retry count")
return None
if okcnt >= self.retry_max:
break
if okcnt < 3: # 如果成功读取的数据少于3次,无法去掉最大值和最小值
print("Not enough valid readings to process")
return None
# 去掉最大值和最小值
data.remove(max(data))
data.remove(min(data))
# 计算平均值并返回,保留6位小数
return round(sum(data) / len(data), 6)
#------------------------------------------------------------
# Example usage
#------------------------------------------------------------
if __name__ == "__main__":
multimeter = MultimeterStrategy('COM6', 9600)
multimeter.connect()
if multimeter.serial:
while True:
result = multimeter.read()
if result is not None:
print(f"Measured voltage: {result} V")
time.sleep(0.5)
multimeter.disconnect()
测试结果:
Connected to multimeter at COM6 with baudrate 9600
未读取到测量数据
测量0结果: -9.4
测量1结果: 3.13e-07
测量2结果: 9.4e-08
测量3结果: 3.03e-07
测量4结果: 1.57e-07
Measured voltage: 0.0 V
测量0结果: 3.03e-07
测量1结果: 2.61e-07
测量2结果: 3.34e-07
测量3结果: 1.15e-07
测量4结果: 2.3e-07
Measured voltage: 0.0 V
二、GBIP读表

配置成gpib模式,地址配置为21
测试代码
class MultimeterStrategy:
def __init__(self, addr):
self.gpib_address = f"GPIB0::{addr}::INSTR"
# 初始化VISA资源管理器
self.rm = pyvisa.ResourceManager()
self.inst = None
self.retry_max = 5
def connect(self):
try:
self.inst = self.rm.open_resource(self.gpib_address)
self.inst.write("*IDN?")
result = self.inst.read()
print(result)
self.inst.write("*CLS")
self.inst.write("SYSTEM:REMOTE")
except pyvisa.VisaIOError as e:
print(f"无法连接到设备 {self.gpib_address}。错误信息: {e}")
exit()
def disconnect(self):
if self.inst:
# 关闭设备连接
self.inst.close()
print("Disconnected from multimeter")
self.inst = None
def _read(self):
if not self.inst:
print("Serial port is not connected")
return None
try:
# 发送READ?命令并读取响应
self.inst.write("READ?")
result = self.inst.read()
if result:
result_str = result.strip()
try:
result_float = float(result_str)
# print(f"测量结果: {result_float}")
return result_float
except ValueError as e:
print(f"无法将字符串转换为浮点数: {result_str}")
time.sleep(0.5)
else:
print("未读取到测量数据")
time.sleep(1)
except Exception as e:
print(f"Error reading from multimeter: {e}")
return None
def read(self):
data = []
errcnt = 0
okcnt = 0
while True:
read_data = self._read()
if read_data is not None:
print(f"测量{okcnt}结果: {read_data}")
data.append(read_data)
okcnt += 1
errcnt = 0
time.sleep(1)
else:
errcnt += 1
if errcnt > self.retry_max:
print("Exceeded maximum retry count")
return None
if okcnt >= self.retry_max:
break
if okcnt < 3: # 如果成功读取的数据少于3次,无法去掉最大值和最小值
print("Not enough valid readings to process")
return None
# 去掉最大值和最小值
data.remove(max(data))
data.remove(min(data))
# 计算平均值并返回,保留6位小数
return round(sum(data) / len(data), 6)
#------------------------------------------------------------
# Example usage
#------------------------------------------------------------
if __name__ == "__main__":
multimeter = MultimeterStrategy(21)
multimeter.connect()
if multimeter.inst:
while True:
result = multimeter.read()
if result is not None:
print(f"Measured voltage: {result} V")
time.sleep(0.5)
multimeter.disconnect()
测试结果:
HEWLETT-PACKARD,34401A,0,11-5-2
测量0结果: -5.7611e-05
测量1结果: -6.5935e-05
测量2结果: -5.1576e-05
测量3结果: -4.5573e-05
测量4结果: -4.1727e-05
Measured voltage: -5.2e-05 V
测量0结果: -6.4649e-05
测量1结果: -6.0684e-05
测量2结果: -6.6349e-05
三、其它
我在测试使用GPIB有可以访问失败。可以使用NI自带工具先验证。配置成如下效果, 再次运行程序正常。

另外,补充说明,在使用RS232模式的时候,每次都需要优先发送SYSTEM:REMOT指令,而使用GPIB只需要发送一次。具体原因未知。哪位大神知道原因的可以告知下。

浙公网安备 33010602011771号