How to wait for a request for service (RQS)

** Note. Cross-posting on the 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 via VISA GPIB and I'm having trouble getting the program to wait for a service request that Keithley sends at the end of a sweep.

The swing is a simple linear voltage sweep, controlled internally by the Keithley device. I have a device configured to send a ServiceRequest at the end of a sweep or when a match is reached.

I can send commands to the SMU and read the data buffer, but only if I manually enter a timeout between the sweep start command and the data read command.

One problem I am running into is that I am fairly new to C # - I am using this project (porting parts of my LV code) to find out.

Here's what I've used 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 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 of the above should mimic this LabVIEW code: simple keithley sweep

So, any ideas on where I am going wrong?

Thank,

Edit:

After a little twisting, I found that the service request feature OnServiceRequest

actually triggered at the right time (β€œService request received!” Is printed on the console).

+3


source to share


2 answers


It turns out that I need to include the event as a Queue and not a handler. This line:

mbSession.EnableEvent(srq, EventMechanism.Handler);

      

In fact, it should be:

mbSession.EnableEvent(srq, EventMechanism.Queue);

      



Source: Documentation in the Notes section. Was a pain to find documents on it ... NI needs to be relieved: - (.

With this change, I also don't need to create MessageBasedSessionEventHandler

.

The last working code looks like this:

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


source


What you are doing looks right to me, so it is possible that there is a problem with the NI library.

The only thing I can think of is to wait for "all events", not just "ServiceRequest". eg:

mbSession.WaitOnEvent(MessageBasedSessionEventType.AllEnabledEvents, timeout);

      

Note: it doesn't seem like you can "enable" all events (so don't change this part).



I also searched for some examples of other people doing Keithley sweeps and I found this and this (Matlab ex). As I suspected in both cases, they don't use events to determine when the sweep is complete, but rather a "while loop that continues polling Keithley" (the first link actually uses streams, but it's the same idea). This makes me think that this is perhaps the best choice. Therefore, you can simply 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 need to check if the data is null, but there must be some way to know when the sweep is complete).

+1


source







All Articles