Python 控制 Keysight N9010B 频谱仪

目录

 

前言 

频谱仪简介

硬件接线图

实现原理

代码详解

 步骤1: 建立连接

步骤2: 发送SCPI指令

步骤3: 根据需求封装函数实现功能

项目源码

支持的设备信号


 

前言 

为什么要实现频谱仪的控制呢?起因是因为我司RF的同事们需要对通信模块进行GSM的带内杂散进行测试,由于该测试的频点涉及900多个,所以急需开发一款自动化测试工具。

该工具需同时实现对无线通讯仪和频谱仪的控制,这篇文章主要介绍一下频谱仪的控制!

 

频谱仪简介

做通信的应该对频谱仪都不陌生,不过我之前做的都是软件相关行业,所以我对频谱仪其实还是很陌生的;不过好在我的同时们都很热心,加上仪器的文档,一段时间下来,也算是熟悉了一些。

N9010B EXA 信号分析仪,分析的频域范围是10 Hz 至 44 GHz:

 

Python 控制 Keysight N9010B 频谱仪_第1张图片

 

硬件接线图

Python 控制 Keysight N9010B 频谱仪_第2张图片

 

实现原理

如何用python实现对频谱仪的远程控制,这里可以参考我之前的一篇远程Fluke设备的文章,其中原理大致类似。主要是通过pyvisa库实现PC和设备之间的通信,然后再根据设备的官方手册,将其中的SCPI指令按照需求进行封装,从而实现你想要的功能。

由于我这里GPIB线材资源不足,且GPIB的成本较高,所以我这里采用的是Ethernet通信的方式来控制频谱仪。

所以,在开始之前,需要安装NI软件(自行百度),安装完毕后打开NI MAX 添加设备(在此之前需将PC的IP地址改为和频谱仪同一网段,否则无法找到设备)

步骤1:点击展开->右键设备和接口 -> 新建 -> 选择VISA TCP/IP Resources

Python 控制 Keysight N9010B 频谱仪_第3张图片

步骤2: 选择Auto-detect of LAN instrument -> 点击下一步:

 Python 控制 Keysight N9010B 频谱仪_第4张图片

步骤3: 选择 Manually specify address information of LAN instrument

 Python 控制 Keysight N9010B 频谱仪_第5张图片

步骤4: 点击下一步 -> 输入 Signal Analyzer 的IP地址 -> 点击Validate ->完成:

Python 控制 Keysight N9010B 频谱仪_第6张图片

若验证失败,请检查PC和Signal Analyzer的IP地址是否在同一网段)。

 

代码详解

 步骤1: 建立连接

先写一个连接的底层函数,主要是验证资源名称是否在当前可用资源列表中: 

	def _sigAnalyzer_connection(cls, resourceName):
        # 这里是建立连接的私有函数,主要通过pyvisa库列出所有的资源,判断我的设备是否在已有的资源列表中
		resourceName = str(resourceName)

		rm = pyvisa.ResourceManager()
		resource_list = rm.list_resources(query='?*::INSTR')

		if resourceName in resource_list:
			cls.inst = rm.open_resource(resourceName)
			cls.inst.clear()
			cls.inst.timeout = 8000
			return cls.inst
		else:
			raise AssertionError("The signal analyzer is not online.")

然后,将仪器的IP地址按照固定格式组成资源名称,再去调用连接的底层函数封装一个建立仪器连接的函数:

@classmethod
	def _open_signal_analyzer_connection(cls, ipAddress):
		ipAddress = str(ipAddress)
		resourceName = 'TCPIP0::{:s}::inst0::INSTR'.format(ipAddress)

		connectionID = cls.get_connectionID(resourceName)

		if connectionID not in cls._connections:
			cls._connections[connectionID] = cls._sigAnalyzer_connection(resourceName)

		cls._active_connection = connectionID

		print('Connect to SA successful')

		return (connectionID, cls._connections[connectionID])

 

步骤2: 发送SCPI指令

这里是封装一个发送所有SCPI指令的函数,该函数可将传入的SCPI指令发送至仪表并检查返回是否出错:

@classmethod
	def _send_raw_command(cls, command, connectionID=None):
		command = str(command)
		connectionID = cls._check_connectionID(connectionID)

		if not command:
			raise ValueError('Command string is empty')

		_SAKeywords._connections[connectionID].write(command)

		try:
			cls._error_query()  # 另外封装的私有方法,检查返回内容
		except:
			raise IOError('Send command ({:s}) to signal analyzer failed.'.format(command))

 

步骤3: 根据需求封装函数实现功能

以上两个步骤完成后剩下的就比较简单了,只需要熟读仪器的手册,根据需求找到相关的SCPI指令,然后进行封装即可,下面简单举几个例子:

(1)设置频谱仪测试模式

这里以设置频谱仪测试模式的函数为例,首先呢,写一个设备支持的测试模式的枚举类:

class TestMode(enum.Enum):
	SAN = 0
	SPEC = 1

然后,在文档中找到设置测试模式的指令为 “CONF:模式名” ,然后直接调用之前的send_raw_comman()方法向设备发送相应的指令即可:

	def set_signal_analyzer_test_mode(self, mode=TestMode.SAN):
		mode = Utils.to_enum(mode, TestMode)
		command = 'CONF:{:s}'.format(mode.name)

		_SAKeywords._send_raw_command(command)

		print('Set SA to {:s} mode'.format(mode.name))

所有其他功能都是相似的道理,核心在于熟读设备的官方手册,由于这些仪器仪表的手册多为英文,所以有时候英文水平还是相当重要的!!!

 

(2) 设置频谱仪的频率

从仪器的官方手册中可得知设置中心频率的SCPI指令为“CENT 频率”,比如“CENT 900MHZ”就是设置中心频率为900MHz。设置扫宽的指令是“SPAN 频率”,所以封装成函数如下:

	def set_signal_analyzer_freq_configuration(self, centerFreq=None, spanFreq=None):
		"""
		:param centerFreq: e.g 10ghz(GHZ), 10mhz(MHZ), 10khz(KHZ), 10hz(HZ)
		:param spanFreq: e.g 10ghz(GHZ), 10mhz(MHZ), 10khz(KHZ), 10hz(HZ)
		:return:None
		"""
		centerFreq = str(centerFreq) if centerFreq is not None else centerFreq
		spanFreq = str(spanFreq) if spanFreq is not None else spanFreq
		freqParams = []

		print('Set SA frequency to {}'.format(centerFreq))

		if centerFreq is not None:
			freqParams.append('CENT {:s}'.format(centerFreq))
		if spanFreq is not None:
			freqParams.append('SPAN {:s}'.format(spanFreq))

		if len(freqParams) >= 1:
			_SAKeywords._send_raw_command('FREQ:{:s}'.format(';'.join(freqParams)))
		else:
			print('No frequency command sent, no parameter was set')

该函数可以设置频谱仪的中心频率和扫宽,直接传入参数即可,关于参数的格式在代码注释中有写。 

 

(3)设置频谱仪的分析带宽RBW和视频带宽VBW 

查阅仪器的官方手册可得知设置RBW的SCPI指令是“:BAND 带宽”;设置VBW的指令是“:BAND:VID 带宽”,所以封装成函数如下:

	def set_signal_analyzer_bw_configuration(self, resBW=None, videoBW=None):
		"""
		:param resBW: e.g 10ghz(GHZ), 10mhz(MHZ), 10khz(KHZ), 10hz(HZ)
		:param videoBW: e.g 10ghz(GHZ), 10mhz(MHZ), 10khz(KHZ), 10hz(HZ)
		:return: None
		"""
		resBW = str(resBW) if resBW is not None else resBW
		videoBW = str(videoBW) if videoBW is not None else videoBW
		bwParams = []

		print('Set SA RBW to {}, VBW to {}'.format(resBW, videoBW))

		if resBW is not None:
			bwParams.append(':BAND {:s}'.format(resBW))
		if videoBW is not None:
			bwParams.append(':BAND:VID {:s}'.format(videoBW))

		if len(bwParams) >= 1:
			_SAKeywords._send_raw_command('{:s}'.format(';'.join(bwParams)))
		else:
			print('No BW command sent, no parameter was set')

 

 

后记

我这里控制频谱仪是为了开发GSM的带内杂散的测试工具,所以只封装了仪器的部分功能。后面工具开发完成后我会再写一篇文章(包括工具的结构,频谱仪的控制,无线通讯测试仪的控制)。

该频谱仪的功能很全,但是我们常用的只是九牛一毛而已。如果以上内容有错误之处,还请各位指出,感谢!

以上的部分只为了提供思路和方法;如果有需要源码的朋友可以在下方评论或者私信我!

 

支持的设备型号

由于我这边设备有限,以上代码只在keysight的N9010B, N9020B, B9030B等仪器上适配过,其他仪器暂未确定是否支持!!!

 

有需要源码的同学,可以CSDN私聊我或者wx直接加我: xgh321324  

 

 

 

 

你可能感兴趣的:(仪器仪表控制,网络,python,仪表控制,Pyvisa,SCPI)