3

**注: LabVIEW フォーラムに相互投稿: http://forums.ni.com/t5/LabVIEW/C-VISA-wait-on-RQS/td-p/3122939

VISA GPIB 経由で Keithley 2400 SMU を制御する単純な C# (.NET 4.0) プログラムを作成しようとしていますが、スイープの最後に Keithley が送信する Service Request をプログラムが待機するのに問題があります。 .

掃引は単純な線形電圧掃引で、ケースレーユニットによって内部で制御されます。スイープの終了時またはコンプライアンスに達したときに ServiceRequest 信号を送信するようにユニットをセットアップしました。

コマンドを SMU に送信してデータ バッファーを読み取ることはできますが、スイープ開始コマンドとデータ読み取りコマンドの間に手動でタイムアウトを入力した場合に限ります。

私が抱えている問題の 1 つは、私が 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 コードを模倣することになっています。 シンプルなケースレー スイープ

それで、私がどこで間違っているのかについてのアイデアはありますか?

ありがとう、

編集:

もう少しいじった後、Service Request 関数OnServiceRequestが実際に適切なタイミングで起動されることがわかりました (「Service Request Received!」がコンソールに出力されます)。

4

2 に答える 2

2

イベントをハンドラーではなくキューとして有効にする必要があることがわかりました。この行:

mbSession.EnableEvent(srq, EventMechanism.Handler);

実際には次のようになります。

mbSession.EnableEvent(srq, EventMechanism.Queue);

出典: 「備考」のドキュメント。ドキュメントを見つけるのは大変でした... 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();
于 2015-04-22T16:51:18.507 に答える
1

あなたがしていることは私には正しいように見えるので、NI ライブラリに問題がある可能性があります。

私が試みることができる唯一のことは、「ServiceRequest」だけでなく「すべてのイベント」を待つことです。このような:

mbSession.WaitOnEvent(MessageBasedSessionEventType.AllEnabledEvents, timeout);

注: すべてのイベントを「有効」にできるようには見えません (したがって、その部分は変更しないでください)。

また、他の人がケースレー スイープを行っている例をいくつか探したところ、これこれ(Matlab ex) が見つかりました。私が疑ったように、どちらもイベントを使用してスイープがいつ終了するかを判断するのではなく、「ケースレーをポーリングし続けるwhileループ」を使用します(最初のリンクは実際にはスレッドを使用しますが、同じ考えです)。これは、おそらくそれがあなたの最善の策だと思います。したがって、これを行うことができます:

        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); 
            }
        }

(データが null かどうかも確認する必要があるかもしれませんが、スイープがいつ終了したかを知る方法が必要です)。

于 2015-04-22T14:56:28.917 に答える