How to Wait on Service Request (RQS)

谁说胖子不能爱 提交于 2020-01-02 07:54:07

问题


**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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!