Help Icon
Search Results for

    Show / Hide Table of Contents

    C# SCPI reference

    On this page you will learn how to send SCPI-commands to a Bode device using the programming language C# and .NET Framework.

    Preconditions

    National Instruments' NI-Visa is installed on the client device (e.g. PC).
    SCPI-Server of the Bode is up and running and the IP-address as well as port are known.
    The 3 required DLLs are downloaded on the programming device:

    • Ivi.Visa.dll
      (default path: C:\Windows\assembly\GAC_MSIL\Ivi.Visa\7.2.0.0__a128c98f1d7717c1)
    • NationalInstruments.Visa.dll
      (default path: C:\Windows\Microsoft.NET\assembly\GAC_MSIL\NationalInstruments.Visa\
      v4.0_24.5.0.49303__2eaa5af0834e221d)
    • NationalInstruments.Common.dll
      (default path: "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\NationalInstruments.Common\
      v4.0_19.1.40.49152__dc6ad606294fc298)

    Please consider that the paths can be different depending on the installed version of NI-Visa. These DLLs need to be referenced in your C# project. When using Visual Studio open the reference manager by right-clicking your projects and selecting Add->Project Reference.

    This will open the following window, where you click on the Browse tab and then on Browse:

    CSReferenceManager

    Add the DLLs one by one.


    Also import the corresponding namespaces into your project

    using Ivi.Visa;
    using NationalInstruments.Visa;
    

    Initializing a Visa Session

    Note

    The resource name consists of the SCPI-Server-IP and the used port number in the following form unless modified
    The default port is 5025 for all Bode devices

    var visaResourceName = "TCPIP0::172.22.44.19::5025::SOCKET";
    

    Now a Visa Session can be opened using a TCPIP-Socket.

    TcpipSocket visaSession;
    
    var visaResourceName = "TCPIP0::172.22.44.19::5025::SOCKET";
    
    //opening a visa session
    visaSession = new TcpipSocket(visaResourceName);
    

    After opening the session enable the termination character and set it to \n to prevent read/write misbehaviours and time-outs. Or you can append the \n to every command and query.
    You can also set the timeout.

    //enabling and setting the termination character
    visaSession.TerminationCharacterEnabled = true;
    visaSession.TerminationCharacter = (byte)'\n';
    //(optional) setting the timeout
    visaSession.TimeoutMilliseconds = 4_000;
    

    There are a few things that need to be considered while setting up the session further based on your individual needs:

    • IO-Protocol
    • formatted / raw IO

    For further information refer to the National Instruments documentation

    Sending queries and reading responses

    There are several possibilities to send queries with these libraries. For your specific needs referring to the NI-Visa .NET documentation is recommended.

    However, here is one example using the RawIO

    //get the id of bode device
    string id = Query("*IDN?\n");
    
    //This function sends a command to the Visa instrument
    void Write(string input)
    {
        if (!input.EndsWith('\n'))
            input += "\n";
        visaSession.RawIO.Write(input);
    }
    
    // This function sends a command to the Visa instrument
    // And reads the response in a loop, until the terminataion character \n is read
    // This way responses that exceed the default Visa Buffer size
    // can be read without setting a buffer size
    string Query(string input)
    {
        Write(input);
        List<string> list = new List<string>();
        string currentChar;
        do
        {
            currentChar = visaSession.RawIO.ReadString();
            list.Add(currentChar);
        }
        while (!currentChar.Contains("\n"));
        string response = String.Join("", list);
        response = response.Trim();
        return response;
    }
    

    If you rather want to set the buffer size by yourself, you can set the amount of bytes to read in the ReadString() function.

    visaSession.RawIO.ReadString(10); //Reads 10 bytes
    

    Estimating Measurement duration

    Important

    If you want many measurement points, the measurement is going to take longer. Therefore, you might need to reconfigure the timeout as shown above to ensure the measurement is finished, before a timeout occurs.

    The timeout needs to be longer than the duration of the measurement. You can calculate how long the measurement is going to take with this simple query

    string time = Query(":SENS:SWE:TIME?\n");
    Console.WriteLine("Time needed for the Measurement: " + time + "seconds");
    

    This will give you an estimation on the duration and you can configure the timeout value based on this result.

    Note

    Calculate the duration of the measurement only after configuring the sweep settings.

    Terminate

    After the communication is finished don't forget to dispose the session as the Bode device would stay locked otherwise.

    //Dispose the session when done
    visaSession.Dispose();
    

    Example connection test

    Here is an example on how to test your connection to the SCPI-Server on any Bode device.

    using Ivi.Visa;
    using NationalInstruments.Visa;
    
    TcpipSocket visaSession;
    
    var visaResourceName = "TCPIP0::172.22.44.19::5025::SOCKET";
    
    //opening a visa session
    visaSession = new TcpipSocket(visaResourceName);
    
    //enabling and setting the termination character
    visaSession.TerminationCharacterEnabled = true;
    visaSession.TerminationCharacter = (byte)'\n';
    //(optional) setting the timeout
    visaSession.TimeoutMilliseconds = 60_000;
    
    //Configuring the session to your individual needs
    visaSession.IOProtocol = Ivi.Visa.IOProtocol.Ieee4882;
    visaSession.SendEndEnabled = true;
    
    //get the id of bode device
    string id = Query("*IDN?\n");
    Console.WriteLine(id);
    
    //Dispose the session when done
    visaSession.Dispose();
    
    //This function sends a command to the Visa instrument
    void Write(string input)
    {
        if (!input.EndsWith('\n'))
            input += "\n";
        visaSession.RawIO.Write(input);
    }
    
    // This function sends a command to the Visa instrument
    // And reads the response in a loop, until the terminataion character \n is read
    // This way responses that exceed the default Visa Buffer size
    // can be read without setting a buffer size
    string Query(string input)
    {
        Write(input);
        List<string> list = new List<string>();
        string currentChar;
        do
        {
            currentChar = visaSession.RawIO.ReadString();
            list.Add(currentChar);
        }
        while (!currentChar.Contains("\n"));
        string response = String.Join("", list);
        response = response.Trim();
        return response;
    }
    

    Example Sweep Measurement

    Here is an example on how to perform a Sweep Measurement

    using Ivi.Visa;
    using NationalInstruments.Visa;
    using System.Diagnostics.Metrics;
    using System.Globalization;
    
    TcpipSocket visaSession;
    
    var visaResourceName = "TCPIP0::172.22.44.19::5025::SOCKET";
    
    //adjust these values
    string startfreq = "10kHz";
    string stopfreq = "10MAHz";
    int numberOfPoints = 201;
    string sweepType = "LOG";
    string receiverBandwidth = "300Hz";
    
    Console.WriteLine("Trying to connect to Visa resource: " + visaResourceName);
    
    DateTime start = DateTime.Now;
    //opening a visa session
    visaSession = new TcpipSocket(visaResourceName);
    
    //enabling and setting the termination character
    visaSession.TerminationCharacterEnabled = true;
    visaSession.TerminationCharacter = (byte)'\n';
    //(optional) setting the timeout
    visaSession.TimeoutMilliseconds = 4_000;
    
    //Configuring the session to your individual needs
    //visaSession.IOProtocol = IOProtocol.Ieee4882;
    //visaSession.SendEndEnabled = true;
    
    //Get the id of the SCPI Server
    string id = Query("*IDN?\n");
    Console.WriteLine("SCPI client connected to SCPI server: " + id);
    
    //Trying to lock the Bode device
    string lockOK = Query(":SYST:LOCK:REQ?");
    
    if (lockOK == null)
    {
        Console.WriteLine("Locking unsuccessful, exiting");
        return;
    }
    else
    {
        Console.WriteLine("Locking successful");
    }
    
    //Measurement configuration
    Write(":SENS:FREQ:STAR " + startfreq);
    Write(":SENS:FREQ:STOP " + stopfreq);
    Write(":SENS:SWE:POIN " + numberOfPoints.ToString());
    Write(":SENS:SWE:TYPE " + sweepType);
    Write(":SENS:BAND " + receiverBandwidth);
    
    //Estimate measurement duration
    string time = Query(":SENS:SWE:TIME?");
    Console.WriteLine("Time needed for the Measurement: " + time + "seconds");
    
    //One-port impedance measurement
    Write(":CALC:PAR:DEF Z");
    //linear magnitude in ohms + phase (deg)
    Write(":CALC:FORM SLIN");
    
    //Initialize trigger system use bus as source
    Write(":TRIG:SOUR BUS");
    
    //Set trigger in continious mode
    Write(":INIT:CONT ON");
    Write(":TRIG:SING");
    
    //Wait for all operations to finish
    var opc = Query("*OPC?");
    Console.WriteLine("operations: " + opc);
    
    //get measurement results
    string frequencyValues = Query(":SENS:FREQ:DATA?");
    string allResults = Query(":CALC:DATA:SDAT?");
    
    Console.WriteLine("frequencies: " + frequencyValues);
    Console.WriteLine("results: " + allResults);
    
    //Convert results into readable arrays
    string[] allRes_String = allResults.Split(",");
    double[] allRes_Double = new double[allRes_String.Length];
    CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
    for (int i = 0; i < allRes_String.Length; i++)
    {
        allRes_Double[i] = Double.Parse(allRes_String[i], culture);
    }
    string[] freqlist_String = frequencyValues.Split(",");
    double[] freqlist_Double = new double[freqlist_String.Length];
    for (int i = 0;i < freqlist_String.Length; i++)
    {
        freqlist_Double[i] = Double.Parse(freqlist_String[i], culture);
    }
    var magnitude = allRes_Double.Take(numberOfPoints).ToArray();
    var phase = allRes_Double.Skip(numberOfPoints).ToArray();
    
    //Printing example of the first measurement point
    Console.WriteLine("Frequency: " + freqlist_Double[0] + "Hz;" + 
    "\tMagnitude: " + magnitude[0] + "Ω;" + "\tPhase: " + phase[0] + "°");
    
    //trying to release the bode device
    string relOK = Query(":SYST:LOCK:REL?");
    //Wait for operation to finish
    
    if (relOK == null)
    {
        Console.WriteLine("Release unsuccesful");
    }
    else
    {
        Console.WriteLine("Release succesful");
    }
    
    //Dispose the session when done
    visaSession.Dispose();
    //Calculate duration of the measurement
    TimeSpan duration = DateTime.Now - start;
    
    Console.WriteLine("Duration of Measurement: " + duration.ToString() + " seconds");
    
    //This function sends a command to the Visa instrument
    void Write(string input)
    {
        if (!input.EndsWith('\n'))
            input += "\n";
        visaSession.RawIO.Write(input);
    }
    
    // This function sends a command to the Visa instrument
    // And reads the response in a loop, until the terminataion character \n is read
    // This way responses that exceed the default Visa Buffer size
    // can be read without setting a buffer size
    string Query(string input)
    {
        Write(input);
        List<string> list = new List<string>();
        string currentChar;
        do
        {
            currentChar = visaSession.RawIO.ReadString();
            list.Add(currentChar);
        }
        while (!currentChar.Contains("\n"));
        string response = String.Join("", list);
        response = response.Trim();
        return response;
    }
    
    In this article
    Back to top Generated by DocFX