在测试过程中 不可避免的要用到高精度电压表,如果要搭建自动测试环境,则需要对电压表进行程控;本文对工作中用到的keysight 34420A进行了远程控制,供大家参考。
实现程控时,需要用到VISA库和SCPI命令,这个大家可以参考各自的手册。另外,至于控制语句可以阅读 每个仪器的手册,均有远程控制 编程介绍。
keysight 34420A支持GPIB 和 ASRL接口,所以笔者在调试过程中使用了GPIB 接口。
由于笔者调试的环境是多线程并发测试,所以使用了多台34420A仪器,首先对仪器进行了地址编址,用以区分。
CString DM_instr_list[] = { _T("::1::"), //HEWLETT-PACKARD,34420A,0,10.0-5.0-3.0
_T("::2::"), //HEWLETT-PACKARD,34420A,0,10.0-5.0-3.0
_T("::3::"), //HEWLETT-PACKARD,34420A,0,10.0-5.0-3.0
_T("::4::"), //HEWLETT-PACKARD,34420A,0,10.0-5.0-3.0
_T("NULL")
};
一 扫描设备
int scanDMMeasureDev()
{
ViStatus status;
ViSession defaultRM, instr;
ViFindList fList;
ViChar desc[VI_FIND_BUFLEN];
ViUInt32 numInstrs;
//ViUInt16 iManf, iModel;
int nIdx = 0;
m_nOpenedNum = 0;
for (int nn = 0; nn < DM_MAX_NUM; nn++)
{
viSession[nn] = 0;
}
status = viOpenDefaultRM(&defaultRM);
if (status < VI_SUCCESS) {
/* Error initializing VISA ... exiting */
return status;
}
rm = defaultRM;
/* Find all instruments in the system */
status = viFindRsrc(defaultRM, "[GPIB]?*INSTR", &fList, &numInstrs, desc);
if (status < VI_SUCCESS) {
/* Error finding resources ... exiting */
viClose(defaultRM);
return status;
}
printf("find src: %s \n", desc);
/* Open a session to each and determine if it matches */
while (numInstrs--) {
status = viOpen(defaultRM, desc, VI_NULL, VI_NULL, &instr);
if (status < VI_SUCCESS) {
viFindNext(fList, desc);
continue;
}
printf("open : %s \n", desc);
status = viSetAttribute(instr, VI_ATTR_TERMCHAR_EN, true);
/* Set the timeout for message-based communication*/
status = viSetAttribute(instr, VI_ATTR_TMO_VALUE, 5000);
printf("set Attribute: %s \n", desc);
/* We have a match, return the session without closing it */
CString strTmp(desc);
printf("find a device: %s \n", desc);
int listnum = 0;
while (DM_instr_list[listnum].CompareNoCase(_T("NULL")) != 0)
{
listnum++;
}
int i;
for (i = 0; i < listnum; i++)
{
if (strTmp.Find(DM_instr_list[i]) >= 0)
{
printf("find a DM device! %s\n", desc);
viSession[i] = instr;
v34470A = instr;
m_nOpenedNum++;
break;
}
}
//已打开的设备保存句柄,加入打开设备列表,不需要关闭。
//viClose(instr);
viFindNext(fList, desc);
}
viClose(fList);
if (m_nOpenedNum > 0)
{
return m_nOpenedNum;
}
else
{
AfxMessageBox(_T("DM not in device list!"));
/* No match was found, return an error */
viClose(defaultRM);
return VI_ERROR_RSRC_NFOUND;
}
}
扫描时根据地址保存句柄,用于对应线程使用34420A句柄。
二、电压源初始化及设置
int initDMMeasuremode(ViSession v34470A)
{
double PLC = 10;
int idn_size = 200; // Set this variable to the maximum size of the array.
char* idn = new char[idn_size];
ViBoolean termDefaultv34470A = VI_TRUE;
viSetAttribute(v34470A, VI_ATTR_TERMCHAR_EN, termDefaultv34470A);
viQueryf(v34470A, "*IDN?\n", "%#t", &idn_size, idn);
CString strDev(idn);
if (strDev.Find(_T("34420A")) >= 0)
PLC = 20;
else
PLC = 100;
viPrintf(v34470A, "*CLS\n");
viPrintf(v34470A, "*ESE %@1d\n", 1);
viPrintf(v34470A, "*SRE %@1d\n", 32);
viPrintf(v34470A, ":CONFigure:VOLTage:DC\n");
viPrintf(v34470A, ":SENSe:VOLTage:DC:NPLCycles %@3lf\n", PLC);
viPrintf(v34470A, ":SAMPle:COUNt %@1d\n", _SAMPLE_COUNT_);
viSetAttribute(v34470A, VI_ATTR_TMO_VALUE, 10000);
printf("Digit Multimeter: %s \n", idn);
delete[] idn;
return 0;
}
设置采样平滑次数 及 触发时间。
三、电压源采数
double getDMData(ViSession session)
{
int readings_size = _SAMPLE_COUNT_; // Set this variable to the maximum size of the array.
double* readings = new double[readings_size];
double ret_val = 0;
viPrintf(session, ":INITiate:IMMediate\n");
viPrintf(session, "*OPC\n");
viQueryf(session, ":FETCh?\n", "%,#lf", &readings_size, readings);
for (int i = 0; i < readings_size; i++)
{
ret_val += readings[i];
}
ret_val = ret_val / readings_size;
delete[] readings;
return ret_val;
}
根据采样平滑次数,获取数据,并做平均。
四、电压源Close
void DMClose(ViSession session)
{
viClose(session);
}
void DMCloseAll()
{
int nDMnum = m_nOpenedNum;
int nn = DM_MAX_NUM;
while (nDMnum--)
{
while (--nn >= 0)
{
v34470A = viSession[nn];
if (v34470A == 0)
continue;
else
break;
}
DMClose(v34470A);
}
DMClose(rm);
}
上述就是对电压源的控制软件的编写,已经调试通过,可以完全控制电压源并正确读取电压值。