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:

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