如何等待服务请求 (RQS)
How to Wait on Service Request (RQS)
**注意:在 LabVIEW 论坛上交叉发布:http://forums.ni.com/t5/LabVIEW/C-VISA-wait-on-RQS/td-p/3122939
我正在尝试编写一个简单的 C# (.NET 4.0) 程序来通过 VISA GPIB 控制 Keithley 2400 SMU,但我无法让程序等待 Keithley 发送的服务请求扫描结束。
扫描是一种简单的线性电压扫描,由吉时利装置在内部控制。我已将设备设置为在扫描结束时或达到合规性时发送 ServiceRequest 信号。
我能够将命令发送到 SMU 并读取数据缓冲区,但前提是我在扫描开始命令和读取数据命令之间手动输入超时。
我遇到的一个问题是我对 C# 很陌生 - 我正在使用这个项目(移植我的 LV 代码的一部分)来学习它。
这是我目前的 C# 代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using NationalInstruments.VisaNS;
private void OnServiceRequest(object sender, MessageBasedSessionEventArgs e)
{
Console.WriteLine("Service Request Received!");
}
// The following code is in a class method, but
public double[,] RunSweep()
{
// Create the session and message-based session
MessageBasedSession mbSession = null;
Session mySession = null;
string responseString = null;
// open the address
Console.WriteLine("Sending Commands to Instrument");
instrAddr = "GPIB0::25::INSTR";
mySession = ResourceManager.GetLocalManager().Open(instrAddr);
// Cast to message-based session
mbSession = (MessageBasedSession)mySession;
// Here's where things get iffy for me... Enabling the event and whatnot
mbSession.ServiceRequest += new MessageBasedSessionEventHandler(OnServiceRequest);
MessageBasedSessionEventType srq = MessageBasedSessionEventType.ServiceRequest;
mbSession.EnableEvent(srq, EventMechanism.Handler);
// Start the sweep (SMU was set up earlier)
Console.WriteLine("Starting Sweep");
mbSession.Write(":OUTP ON;:INIT");
int timeout = 10000; // milliseconds
// Thread.Sleep(10000); // using this line works fine, but it means the test always takes 10s even if compliance is hit early
// This raises error saying that the event is not enabled.
mbSession.WaitOnEvent(srq, timeout);
// Turn off the SMU.
Console.WriteLine("I hope the sweep is done, cause I'm tired of waiting");
mbSession.Write(":OUTP OFF;:TRAC:FEED:CONT NEV");
// Get the data
string data = mbSession.Query(":TRAC:DATA?");
// Close session
mbSession.Dispose();
// For now, create a dummy array, 3x3, to return. The array after is the starting value.
double[,] dummyArray = new double[3, 3] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
return dummyArray;
}
以上所有内容都应该模仿这个 LabVIEW 代码:
那么,我哪里出错了?
谢谢,
编辑:
稍加调整后,我发现服务请求函数 OnServiceRequest
实际上是在正确的时间触发的("Service Request Received!" 打印到控制台)。
我认为您所做的是正确的,因此 NI 库可能存在问题。
我唯一能想到的尝试就是等待 "all events" 而不是像这样 "ServiceRequest.":
mbSession.WaitOnEvent(MessageBasedSessionEventType.AllEnabledEvents, timeout);
注意:您似乎无法 "enable" 所有事件(因此请不要更改该部分)。
我还寻找了其他人如何进行 Keithley 扫描的一些示例,我发现了 this and this(Matlab ex)。正如我在两者中所怀疑的那样,他们不使用事件来确定扫描何时完成,而是使用 "while loop that keeps polling the Keithley"(第一个 link 实际上使用线程,但它是相同的想法)。这让我觉得也许这是你最好的选择。所以你可以这样做:
int timeout = 10000;
int cycleWait = 1000;
for (int i = 0; i < timeout / cycleWait; i++)
{
try
{
string data = mbSession.Query(":TRAC:DATA?");
break;
}
catch
{
Thread.Sleep(cycleWait);
}
}
(您可能还需要检查数据是否为空,但必须有某种方式知道扫描何时完成)。
事实证明,我需要将事件启用为 Queue 而不是处理程序。这一行:
mbSession.EnableEvent(srq, EventMechanism.Handler);
实际应该是:
mbSession.EnableEvent(srq, EventMechanism.Queue);
来源:"Remarks" 下的 The documentation。很难找到它的文档......NI需要让它更容易:-(。
通过此更改,我也不需要创建 MessageBasedSessionEventHandler
。
最终的工作代码如下所示:
rm = ResourceManager.GetLocalManager().Open("GPIB0::25::INSTR");
MessageBasedSession mbSession = (MessageBasedSession)rm;
MessageBasedSessionEventType srq = MessageBasedSessionEventType.ServiceRequest;
mbSession.EnableEvent(srq, EventMechanism.Queue); // Note QUEUE, not HANDLER
int timeout = 10000;
// Start the sweep
mbSession.Write(":OUTP ON;:INIT");
// This waits for the Service Request
mbSession.WaitOnEvent(srq, timeout);
// After the Service Request, turn off the SMUs and get the data
mbSession.Write(":OUTP OFF;:TRAC:FEED:CONT NEV");
string data = mbSession.Query(":TRAC:DATA?");
mbSession.Dispose();
**注意:在 LabVIEW 论坛上交叉发布:http://forums.ni.com/t5/LabVIEW/C-VISA-wait-on-RQS/td-p/3122939
我正在尝试编写一个简单的 C# (.NET 4.0) 程序来通过 VISA GPIB 控制 Keithley 2400 SMU,但我无法让程序等待 Keithley 发送的服务请求扫描结束。
扫描是一种简单的线性电压扫描,由吉时利装置在内部控制。我已将设备设置为在扫描结束时或达到合规性时发送 ServiceRequest 信号。
我能够将命令发送到 SMU 并读取数据缓冲区,但前提是我在扫描开始命令和读取数据命令之间手动输入超时。
我遇到的一个问题是我对 C# 很陌生 - 我正在使用这个项目(移植我的 LV 代码的一部分)来学习它。
这是我目前的 C# 代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using NationalInstruments.VisaNS;
private void OnServiceRequest(object sender, MessageBasedSessionEventArgs e)
{
Console.WriteLine("Service Request Received!");
}
// The following code is in a class method, but
public double[,] RunSweep()
{
// Create the session and message-based session
MessageBasedSession mbSession = null;
Session mySession = null;
string responseString = null;
// open the address
Console.WriteLine("Sending Commands to Instrument");
instrAddr = "GPIB0::25::INSTR";
mySession = ResourceManager.GetLocalManager().Open(instrAddr);
// Cast to message-based session
mbSession = (MessageBasedSession)mySession;
// Here's where things get iffy for me... Enabling the event and whatnot
mbSession.ServiceRequest += new MessageBasedSessionEventHandler(OnServiceRequest);
MessageBasedSessionEventType srq = MessageBasedSessionEventType.ServiceRequest;
mbSession.EnableEvent(srq, EventMechanism.Handler);
// Start the sweep (SMU was set up earlier)
Console.WriteLine("Starting Sweep");
mbSession.Write(":OUTP ON;:INIT");
int timeout = 10000; // milliseconds
// Thread.Sleep(10000); // using this line works fine, but it means the test always takes 10s even if compliance is hit early
// This raises error saying that the event is not enabled.
mbSession.WaitOnEvent(srq, timeout);
// Turn off the SMU.
Console.WriteLine("I hope the sweep is done, cause I'm tired of waiting");
mbSession.Write(":OUTP OFF;:TRAC:FEED:CONT NEV");
// Get the data
string data = mbSession.Query(":TRAC:DATA?");
// Close session
mbSession.Dispose();
// For now, create a dummy array, 3x3, to return. The array after is the starting value.
double[,] dummyArray = new double[3, 3] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
return dummyArray;
}
以上所有内容都应该模仿这个 LabVIEW 代码:
那么,我哪里出错了?
谢谢,
编辑:
稍加调整后,我发现服务请求函数 OnServiceRequest
实际上是在正确的时间触发的("Service Request Received!" 打印到控制台)。
我认为您所做的是正确的,因此 NI 库可能存在问题。
我唯一能想到的尝试就是等待 "all events" 而不是像这样 "ServiceRequest.":
mbSession.WaitOnEvent(MessageBasedSessionEventType.AllEnabledEvents, timeout);
注意:您似乎无法 "enable" 所有事件(因此请不要更改该部分)。
我还寻找了其他人如何进行 Keithley 扫描的一些示例,我发现了 this and this(Matlab ex)。正如我在两者中所怀疑的那样,他们不使用事件来确定扫描何时完成,而是使用 "while loop that keeps polling the Keithley"(第一个 link 实际上使用线程,但它是相同的想法)。这让我觉得也许这是你最好的选择。所以你可以这样做:
int timeout = 10000;
int cycleWait = 1000;
for (int i = 0; i < timeout / cycleWait; i++)
{
try
{
string data = mbSession.Query(":TRAC:DATA?");
break;
}
catch
{
Thread.Sleep(cycleWait);
}
}
(您可能还需要检查数据是否为空,但必须有某种方式知道扫描何时完成)。
事实证明,我需要将事件启用为 Queue 而不是处理程序。这一行:
mbSession.EnableEvent(srq, EventMechanism.Handler);
实际应该是:
mbSession.EnableEvent(srq, EventMechanism.Queue);
来源:"Remarks" 下的 The documentation。很难找到它的文档......NI需要让它更容易:-(。
通过此更改,我也不需要创建 MessageBasedSessionEventHandler
。
最终的工作代码如下所示:
rm = ResourceManager.GetLocalManager().Open("GPIB0::25::INSTR");
MessageBasedSession mbSession = (MessageBasedSession)rm;
MessageBasedSessionEventType srq = MessageBasedSessionEventType.ServiceRequest;
mbSession.EnableEvent(srq, EventMechanism.Queue); // Note QUEUE, not HANDLER
int timeout = 10000;
// Start the sweep
mbSession.Write(":OUTP ON;:INIT");
// This waits for the Service Request
mbSession.WaitOnEvent(srq, timeout);
// After the Service Request, turn off the SMUs and get the data
mbSession.Write(":OUTP OFF;:TRAC:FEED:CONT NEV");
string data = mbSession.Query(":TRAC:DATA?");
mbSession.Dispose();