Help Icon
Search Results for

    Show / Hide Table of Contents

    LabWindows/CVI SCPI reference

    On this page you will learn how to send SCPI-commands to a Bode device using National Instruments LabWindows/CVI.

    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.

    Include the Visa library at the top of the source file.

    #include <visa.h>
    

    Initializing a Visa Session

    Note

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

    ViRsrc resourceName = "TCPIP::YourIPHere::5025::SOCKET";
    

    Set up a resource manager and open a session with it. Enable the termination character and set it to \n to prevent read timeouts.
    You can also set the Timeout.

    //create a resource manager
    ViSession resourceManager;
    viOpenDefaultRM(&resourceManager);
    	
    //open a visa session
    ViSession instrument;
    viOpen(resourceManager, resourceName, VI_NULL, VI_NULL, &instrument);
    
    //Enable and set the termination character to prevent timeout
    viSetAttribute(instrument, VI_ATTR_TERMCHAR_EN, VI_TRUE);
    viSetAttribute(instrument, VI_ATTR_TERMCHAR, '\n');
    viSetAttribute(instrument, VI_ATTR_TMO_VALUE, 4000); //Timeout 4000 milliseconds (optional)
    

    Sending queries and reading responses

    To send a command you have to create a Visa Buffer containing the command and use the viWrite function to send it.
    If a response is expected catch it with a Visa read Buffer using the viRead function.

    //send command
    ViUInt32 writeCount;
    char command[] = "*IDN?";
    viWrite(instrument, (ViBuf)command, strlen(command), &writeCount);
    	
    //read response
    uint32_t bufSize = 256
    char response[bufSize];
    ViUInt32 readCount;
    viRead(instrument, (ViBuf)response, bufSize, &readCount);
    

    As you can see above, the buffer size can be changed according to your specific needs.

    If you don't know how much data you will get returned you can read the response in a loop without setting a buffer size.

    //sends commands to the instrument
    // Reads response in a loop if response > 1kB
    // Stops when reading termination character \n
    char* queryCommand(ViSession vi, const char* cmd) {
        ViUInt32 retCount;
    	uint16_t loopSize = 1024; //define how much data is read every loop (here 1kB)
    	char currentChars[loopSize+1];
    	size_t responseSize = 0;
    	char *response = NULL;
        sendCommand(vi, cmd); //send the command to the device
    	response = malloc(1); 
    	response[0] = '\0'; //null terminate initial response
    	do
    	{
    		viRead(vi, (ViBuf)currentChars, loopSize, &retCount); //read 1kB
    		currentChars[retCount] = '\0'; //null terminate the current data
    		responseSize += retCount;
    		//reallocate memory for response (size changed)
    		response = realloc(response, responseSize + 1);
    		strcat(response, currentChars); //append current data to response
    	}
    	//loop as long as termination character has not been read
    	while (strchr(currentChars, '\n') == NULL);
    	return response;
    }
    

    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

    //Estimate measurement duration
    char* duration = queryCommand(instrument, ":SENS:SWE:TIME?\n");
    printf("Measurement duration: ");
    printf(duration);
    printf("\n");
    

    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 complete close the session and the resource manager to prevent errors in following command cycles.

    viClose(instrument);
    viClose(resourceManager);
    

    Example connection test

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

    #include <ansi_c.h>
    #include <visa.h>
    #include <stdio.h>
    
    int main (int argc, char *argv[])
    {
    	printf("Hello World\n");
    	
    	//create a resource manager
    	ViSession resourceManager;
    	viOpenDefaultRM(&resourceManager);
    	
    	ViRsrc resourceName = "TCPIP::YourIPHere::5025::SOCKET";
    	
    	//open a visa session
    	ViSession instrument;
    	viOpen(resourceManager, resourceName, VI_NULL, VI_NULL, &instrument);
    	
    	//Enable and set the termination character to prevent timeout
    	viSetAttribute(instrument, VI_ATTR_TERMCHAR_EN, VI_TRUE);
    	viSetAttribute(instrument, VI_ATTR_TERMCHAR, '\n');
    	
    	//send command
    	ViUInt32 writeCount;
    	char command[] = "*IDN?";
    	viWrite(instrument, (ViBuf)command, strlen(command), &writeCount);
    	
    	//read response
    	uint32_t bufSize = 256
    	char response[bufSize];
    	ViUInt32 readCount;
    	viRead(instrument, (ViBuf)response, bufSize, &readCount);
    	
    	printf(response);
    	
    	//close the session
    	viClose(instrument);
    	viClose(resourceManager);
    
    	return 0;
    }
    

    Example Sweep Measurement

    Here is an example on how to perform a sweep measurement

    #include <ansi_c.h>
    #include <visa.h>
    #include <stdio.h>
    #include <windows.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    
    //sends Commands to the instrument
    void sendCommand(ViSession vi, const char* cmd) {
        ViUInt32 retCount;
        viWrite(vi, (ViBuf)cmd, strlen(cmd), &retCount);
    }
    
    //sends commands to the instrument
    // Reads response in a loop if response > 1kB
    // Stops when reading termination character \n
    char* queryCommand(ViSession vi, const char* cmd) {
        ViUInt32 retCount;
    	uint16_t loopSize = 1024; //define how much data is read every loop (here 1kB)
    	char currentChars[loopSize+1];
    	size_t responseSize = 0;
    	char *response = NULL;
        sendCommand(vi, cmd); //send the command to the device
    	response = malloc(1); 
    	response[0] = '\0'; //null terminate initial response
    	do
    	{
    		viRead(vi, (ViBuf)currentChars, loopSize, &retCount); //read 1kB
    		currentChars[retCount] = '\0'; //null terminate the current data
    		responseSize += retCount;
    		//reallocate memory for response (size changed)
    		response = realloc(response, responseSize + 1);
    		strcat(response, currentChars); //append current data to response
    	}
    	//loop as long as termination character has not been read
    	while (strchr(currentChars, '\n') == NULL);
    	return response;
    }
    
    //Method to perform an errorcheck on the SCPI Server
    void checkError(ViSession vi, char when[]){
    	char* error = queryCommand(vi, ":SYST:ERR?\n");
    	printf(when);
    	printf("\n");
    	printf(error);
    	printf("\n");
    }
    
    //count the elements in the result variable
    int countElements(char* str) {
        int count = 1;
        for (char* p = str; *p; p++) {
            if (*p == ',') count++;
        }
        return count;
    }
    
    //convert the results to floats
    void splitAndConvertToFloat(char* str, float* array){
    	char* token = strtok(str, ",");
    	int index = 0;
    	while (token != NULL){
    		array[index++] = atof(token);
    		token = strtok(NULL, ",");
    	}
    }
    
    int main (int argc, char *argv[])
    {
    	clock_t start, end;
    	start = clock();
    	//create a resource manager
    	ViSession resourceManager;
    	viOpenDefaultRM(&resourceManager);
    	
    	ViRsrc resourceName = "TCPIP::172.22.60.91::5025::SOCKET"; //Edit this to your IP
    	
    	printf("Trying to connect to Visa resource: ");
    	printf(resourceName);
    	printf("\n");
    	
    	//open a visa session
    	ViSession instrument;
    	viOpen(resourceManager, resourceName, VI_NULL, VI_NULL, &instrument);
    	
    	//Enable and set the termination character to prevent timeout
    	viSetAttribute(instrument, VI_ATTR_TERMCHAR_EN, VI_TRUE);
    	viSetAttribute(instrument, VI_ATTR_TERMCHAR, '\n');
    	viSetAttribute(instrument, VI_ATTR_TMO_VALUE, 2500);
    	
    	//Get SCPI Server ID
    	char* response = queryCommand(instrument, "*IDN?\n");
    	printf("SCPI Client connected to SCPI Server: ");
    	printf(response);
    	printf("\n");
    	
    	//Trying to lock the Bode device
    	char* lockOK = queryCommand(instrument, ":SYST:LOCK:REQ?\n");
    	printf("Locking status: ");
    	printf(lockOK);
    	printf("\n");
    	
    	//Reset the SCPI-Server
    	sendCommand(instrument, "*CLS\n");
    	sendCommand(instrument, "*RST\n");
    	sendCommand(instrument, "*ESE 255\n"); //Enable errorchecks
    	checkError(instrument, "After reset"); //errorcheck after the resets
    	
    	//configure Measurement
    	sendCommand(instrument, ":CALC:PAR:DEF Z\n"); //one port impedance measurement
    	sendCommand(instrument, ":SENS:FREQ:STAR 10kHz\n"); //start frequency
    	sendCommand(instrument, ":SENS:FREQ:STOP 10MAHz\n"); //stop frequency
    	sendCommand(instrument, ":SENS:SWE:POIN 201\n"); //number of measurement points
    	sendCommand(instrument, ":SENS:SWE:TYPE LOG\n"); //Logarithmic sweep
    	sendCommand(instrument, ":SENS:BAND 300Hz\n");
    	checkError(instrument, "After freq config"); //errorcheck after frequency configs
    
    	//Estimate measurement duration
    	char* duration = queryCommand(instrument, ":SENS:SWE:TIME?\n");
    	printf("Measurement duration: ");
    	printf(duration);
    	printf("\n");
    	
    	sendCommand(instrument, ":CALC:FORM SLIN\n"); //linear magnitude and phase
    	sendCommand(instrument, ":TRIG:SOUR BUS\n");//trigger uses bus as source
    	sendCommand(instrument, ":INIT:CONT ON\n"); //initialize trigger continiously 
    	sendCommand(instrument, ":TRIG:SING\n");// trigger a measurement
    	checkError(instrument, "After trigger config"); //errorcheck after trigger config
    	
    	//Wait until operations are finished
    	char* opc = queryCommand(instrument, "*OPC?\n");
    	printf("Operation finished status: ");
    	printf(opc);
    	printf("\n");
    	
    	//Read the frequency values
    	char* freqValues = queryCommand(instrument, ":SENS:FREQ:DATA?\n");
    	printf("frequencies: ");
    	printf(freqValues);
    	printf("\n");
    	//errorcheck after reading the frequencies
    	checkError(instrument, "After freq data");
    	
    	//read the measurement data
    	char* allResults = queryCommand(instrument, ":CALC:DATA:SDAT?\n");
    	printf("results: ");
    	printf(allResults);
    	printf("\n");
    	//errorcheck after reading measurement data
    	checkError(instrument, "After meas data");
    	
    	//close the session
    	viClose(instrument);
    	viClose(resourceManager);
    	
    	end = clock();
    	
    	double timeUsed = ((double)(end-start))/1000;
    	
    	printf("Measurement complete. Took: %f", timeUsed);
    	printf(" seconds");
    	
    	int x = getchar();
    	return 0;
    }
    
    In this article
    Back to top Generated by DocFX