Ubuntu下使用NI-VISA控制USB接口仪器(示波器)
需要用到的工具:Ubuntu 21.04 (NI-VISA官网上要求使用 Ubuntu 18.04 或 20.04,实测 21.04 也是可以的)普源示波器 DS1054Z (其它使用NI-VISA标准的仪器也可以用本文方法进行试验)用来连接电脑与示波器的 USB 数据线操作步骤:1. 下载并解压 NI-VISA 安装包:下载NI Linux设备驱动程序 - NI2. 安装 NI-VISA,在解压
本文使用SCPI协议与C语言编程,在 Ubuntu 下实现了简单的上位机软件。
需要的工具:
- 已安装 Ubuntu 20.04 的电脑一台,虚拟机或物理机均可,(现在 NI-VISA 建议使用的版本: Ubuntu 18.04 / 20.04 / 22.04,其它版本请自行测试)
- 普源示波器 DS1054Z (本文也适用于其它使用SCPI协议的仪器,不限于普源品牌,不限于示波器)
- 用来连接电脑与示波器的 USB 数据线
NI-VISA 安装与配置:
1. 下载设备驱动程序安装包:下载NI Linux设备驱动程序 - NI ,需要注意的,安装包支持的内核版本与你所使用的 Ubuntu 的内核版本必须相同,否则会安装失败,可以在下载页面上点击 “查看自述文件” 查看安装包支持的内核版本,如果内核版本不一致,可以在下载页面上选择其它版本的安装包;
查看 Ubuntu 内核版本:
uname -r
2. 安装 NI-VISA:解压下载的安装包,在解压后的路径下运行下面的命令:
sudo apt install ./ni-ubuntu2004-drivers-2024Q1.deb
sudo apt update
sudo apt install ni-visa
3. 如果你使用的操作系统是 Ubuntu 20.04 / 22.04,请执行下面这些命令,这样做的目的是让普通权限用户也能访问 USB 仪器,Ubuntu 18.04 用户请略过此步。
sudo mkdir -p /etc/udev/agents.d/usb
sudo ln -s /usr/lib/x86_64-linux-gnu/ni-visa/usb/nivisa_usbraw /etc/udev/agents.d/usb/
sudo ln -s /usr/lib/x86_64-linux-gnu/ni-visa/usb/nivisa_usbtmc /etc/udev/agents.d/usb/
sudo ln -s /usr/lib/x86_64-linux-gnu/ni-visa/usb/nivisa_usbtmc.rules /etc/udev/rules.d/
4. 禁用 Ubuntu 系统原生的 usbtmc 模块,因为这个模块会独占仪器的 USB 资源,导致 NI-VISA 无法访问仪器,使用下面的命令禁止 usbtmc 模块加载:
$ sudo su
# echo 'blacklist usbtmc' > /etc/modprobe.d/nousbtmc.conf
5. 收藏或标记本文,然后重启 Ubuntu
reboot
===== NI-VISA 的安装与配置至此完成 =====
上位机编程:
1. 编译控制仪器源代码 scope.c:
gcc -o scope scope.c -lvisa
scope.c 源码:
#include <ni-visa/visa.h>
#include <stdio.h>
#include <string.h>
#define MAX_SCPI_LEN 4096
void ReadWriteFunc_1(ViSession vi, ViByte* pBuf)
{
const ViChar szCmd[] = "*IDN?\n";
ViUInt32 nRwCount;
// 写入命令,并读取命令回应
if (VI_SUCCESS <= viWrite(vi, szCmd, strlen(szCmd), &nRwCount) &&
VI_SUCCESS <= viRead(vi, pBuf, MAX_SCPI_LEN - 1, &nRwCount))
{
pBuf[nRwCount] = '\0';
printf("%s\n", pBuf);
}
}
void ReadWriteFunc_2(ViSession vi, ViByte* pBuf)
{
// 写入命令,并读取命令回应,pBuf 缓冲区大小必须大于要读取的数据大小
// "%t"表示遇到终止符结束读取,默认终止符是'\n',终止符是可设置的
if (VI_SUCCESS <= viPrintf(vi, "%s\n", "*IDN?") &&
VI_SUCCESS <= viScanf(vi, "%t", pBuf))
{
printf("%s\n", pBuf);
}
}
void ReadWriteFunc_3(ViSession vi, ViByte* pBuf)
{
// 写入并读取,pBuf 缓冲区大小必须大于要读取的数据大小
// "%t"表示遇到终止符结束读取,默认终止符是'\n',终止符是可设置的
if (VI_SUCCESS <= viQueryf(vi, "%s\n", "%t", "*IDN?", pBuf))
{
printf("%s\n", pBuf);
}
}
int main()
{
ViStatus nRet;
ViSession viDef = 0;
ViSession vi;
char szAddr[VI_FIND_BUFLEN];
ViUInt32 numInstrs;
ViFindList findList;
ViByte btBuf[MAX_SCPI_LEN];
nRet = viOpenDefaultRM(&viDef);
if (nRet < VI_SUCCESS)
return -1;
// 查找地址以 USB 开头的仪器资源,并把找到的第一个资源地址放在 szAddr 中
nRet = viFindRsrc (viDef, "USB?*INSTR", &findList, &numInstrs, szAddr);
if (nRet < VI_SUCCESS)
{
printf("Error code: %X\n", nRet);
viClose(viDef);
return -1;
}
nRet = viOpen(viDef, szAddr, VI_NULL, VI_NULL, &vi);
if (nRet < VI_SUCCESS)
{
printf("Error code: %X\n", nRet);
viClose(viDef);
return -1;
}
// 下面 3 个函数功能是相同的,根据实际编程情况选择其一
ReadWriteFunc_1(vi, btBuf);
ReadWriteFunc_2(vi, btBuf);
ReadWriteFunc_3(vi, btBuf);
viClose(vi);
viClose(viDef);
return 0;
}
2. 用 USB 数据线连接电脑与仪器,运行控制程序,运行之后会在命令行窗口上显示仪器的基本信息。
./scope
3. 如果想要在上位机软件中实现更多功能,可以在仪器生产商官网上下载编程手册(通信协议)。
更多推荐
所有评论(0)