问题
**Note: Cross-posted at LabVIEW forums: http://forums.ni.com/t5/LabVIEW/C-VISA-wait-on-RQS/td-p/3122939
I'm trying to write a simple C# (.NET 4.0) program to control a Keithley 2400 SMU over VISA GPIB and I'm having trouble with getting the program to wait for the Service Request that the Keithley sends at the end of the sweep.
The sweep is a simple linear voltage sweep, controlled internally by the Keithley unit. I've got the unit set up to send a ServiceRequest signal at the end of the sweep or when compliance is reached.
I'm able to send the commands to the SMU and read the data buffer, but only if I manually enter a timeout between the sweep start command and the read data command.
One issue I'm having is that I'm quite new to C# - I'm using this project (porting parts of my LV code) to learn it.
Here is what I have so far for my C# code:
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;
}
All the above is supposed to mimic this LabVIEW code:
So, any ideas on where I'm going wrong?
Thanks,
Edit:
After a little more fiddling, I've found that the Service Request function OnServiceRequest
is actually fired at the right time ("Service Request Received!" is printed to the console).
回答1:
It turns out that I need to enable the event as a Queue rather than a handler. This line:
mbSession.EnableEvent(srq, EventMechanism.Handler);
Should actually be:
mbSession.EnableEvent(srq, EventMechanism.Queue);
Source: The documentation under "Remarks". It was a pain to find the docs on it... NI needs to make it easier :-(.
With this change, I also don't need to create the MessageBasedSessionEventHandler
.
The final, working code looks like:
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();
回答2:
What you're doing looks correct to me so it's possible that there's an issue with the NI library.
The only thing I can think of to try is waiting for "all events" instead of just "ServiceRequest." like this:
mbSession.WaitOnEvent(MessageBasedSessionEventType.AllEnabledEvents, timeout);
Note: that it doesn't look like you can "enable" all events (so don't change that part).
I also looked for some examples of how other people are doing Keithley sweeps and I found this and this(Matlab ex). As I suspected in both they don't use events to determine when the sweep is finished, but rather a "while loop that keeps polling the Keithley" (the first link actually uses threads, but it's the same idea). This makes me think that maybe that's your best bet. So you could just do this:
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);
}
}
(You may also have to check if data is null, but there has to be some way of knowing when the sweep is finished).
来源:https://stackoverflow.com/questions/29785006/how-to-wait-on-service-request-rqs