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号
浙公网安备 33010602011771号