Agilent 34401A台式万用表支持RS232和GPIB的方式读数据。
一、RS232读表
将台式万用表的模式调为RS232-9600-8-1-none
测试代码
class MultimeterStrategy:def __init__(self, port, baudrate=9600):self.port = portself.baudrate = baudrateself.serial = Noneself.retry_max = 5def connect(self):self.serial = serial.Serial()self.serial.port = self.portself.serial.baudrate = self.baudrateself.serial.timeout = 0.05try: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 = Nonedef disconnect(self):if self.serial:self.serial.close()print("Disconnected from multimeter")self.serial = Nonedef _read(self):if not self.serial:print("Serial port is not connected")return Nonetry: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_floatexcept 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 Nonedef read(self):data = []errcnt = 0okcnt = 0self.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 += 1errcnt = 0time.sleep(1)else:errcnt += 1if errcnt > self.retry_max:print("Exceeded maximum retry count")return Noneif okcnt >= self.retry_max:breakif 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 = Noneself.retry_max = 5def 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 = Nonedef _read(self):if not self.inst:print("Serial port is not connected")return Nonetry:# 发送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_floatexcept 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 Nonedef read(self):data = []errcnt = 0okcnt = 0while True:read_data = self._read()if read_data is not None:print(f"测量{okcnt}结果: {read_data}")data.append(read_data)okcnt += 1errcnt = 0time.sleep(1)else:errcnt += 1if errcnt > self.retry_max:print("Exceeded maximum retry count")return Noneif okcnt >= self.retry_max:breakif 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只需要发送一次。具体原因未知。哪位大神知道原因的可以告知下。