04-04-2018 08:11 AM
Hello everyone,
I'm actually trying to acquire a waveform of my infiniium DSOZ204A from Keysight.
I use the Visa Library 32bit and VC++ 2008 express edition.
I've copied, pasted and modified the code given by Keysight in their documentation. After a few bug correction the communication was established and I was able to modify some attributes.
But, when the acquiring process comes everything goes wrong. I send the command :WAVeform:DATA? to access the buffer where the data is and when it comes to the reading part I have an error : "VISA error: a format specifier in the format string is not valid". Then, a security implemented by Keysight in the code tell me that the IEEE block buffer is full.
Does anyone know where the problem is?
I thought the problem could come from the runtime Library, but obviously not. Maybe a pointer is not well defined...
Please find the code:
/*
* Keysight VISA Example in C
* ------------------------------------------------------------------
* This program illustrates a few commonly-used programming
* features of your Keysight Infiniium Series oscilloscope.
*/
#include <stdio.h> /* For printf(). */
#include <string.h> /* For strcpy(), strcat(). */
#include <time.h> /* For clock(). */
#include <visa.h> /* Keysight VISA routines. */
#define VISA_ADDRESS "TCPIP0::141.121.237.226::hislip0::INSTR"
#define IEEEBLOCK_SPACE 5000000
/* Function prototypes */
void initialize(void); /* Initialize to known state. */
void capture(void); /* Capture the waveform. */
void analyze(void); /* Analyze the captured waveform. */
void do_command(char *command); /* Send command. */
int do_command_ieeeblock(char *command); /* Command w/IEEE block. */
void do_query_string(char *query); /* Query for string. */
void do_query_number(char *query); /* Query for number. */
void do_query_numbers(char *query); /* Query for numbers. */
int do_query_ieeeblock(char *query); /* Query for IEEE byte block. */
int do_query_ieeeblock_words(char *query); /* Query for word block. */
void check_instrument_errors(); /* Check for inst errors. */
void error_handler(); /* VISA error handler. */
/* Global variables */
ViSession defaultRM, vi; /* Device session ID. */
ViStatus err; /* VISA function return value. */
char str_result[256] = {0}; /* Result from do_query_string(). */
double num_result; /* Result from do_query_number(). */
unsigned char ieeeblock_data[IEEEBLOCK_SPACE]; /* Result from
do_query_ieeeblock(). */
signed short ieeeblock_data_words[IEEEBLOCK_SPACE]; /* Result from
do_query_ieeeblock_words(). */
double dbl_results[10]; /* Result from do_query_numbers(). */
/* Main Program
* --------------------------------------------------------------- */
void main(void)
{
/* Open the default resource manager session. */
err = viOpenDefaultRM(&defaultRM);
if (err != VI_SUCCESS) error_handler();
/* Open the session using the oscilloscope's VISA address. */
err = viOpen(defaultRM, VISA_ADDRESS, VI_NULL, VI_NULL, &vi);
if (err != VI_SUCCESS) error_handler();
/* Set the I/O timeout to fifteen seconds. */
err = viSetAttribute(vi, VI_ATTR_TMO_VALUE, 15000);
if (err != VI_SUCCESS) error_handler();
/* Clear the interface. */
err = viClear(vi);
if (err != VI_SUCCESS) error_handler();
/* Initialize - start from a known state. */
initialize();
/* Capture data. */
capture();
/* Analyze the captured waveform. */
analyze();
/* Close the vi session and the resource manager session. */
viClose(vi);
viClose(defaultRM);
}
/* Initialize the oscilloscope to a known state.
* --------------------------------------------------------------- */
void initialize (void)
{
/* Clear status. */
do_command("*CLS");
/* Get and display the device's *IDN? string. */
do_query_string("*IDN?");
printf("Oscilloscope *IDN? string: %s\n", str_result);
/* Load the default setup. */
do_command("*RST");
}
/* Capture the waveform.
* --------------------------------------------------------------- */
void capture (void)
{
int num_values;
FILE *fp;
/* Set probe attenuation factor. */
do_command(":CHANnel1:PROBe 1.0");
do_query_string(":CHANnel1:PROBe?");
printf("Channel 1 probe attenuation factor: %s\n", str_result);
/* Use auto-scale to automatically configure oscilloscope. */
do_command(":AUToscale");
/* Set trigger mode. */
do_command(":TRIGger:MODE EDGE");
do_query_string(":TRIGger:MODE?");
printf("Trigger mode: %s\n", str_result);
/* Set EDGE trigger parameters. */
do_command(":TRIGger:EDGE:SOURCe CHANnel1");
do_query_string(":TRIGger:EDGE:SOURce?");
printf("Trigger edge source: %s\n", str_result);
do_command(":TRIGger:LEVel CHANnel1,-2E-3");
do_query_string(":TRIGger:LEVel? CHANnel1");
printf("Trigger level, channel 1: %s\n", str_result);
do_command(":TRIGger:EDGE:SLOPe POSitive");
do_query_string(":TRIGger:EDGE:SLOPe?");
printf("Trigger edge slope: %s\n", str_result);
/* Save oscilloscope setup. */
/* Read system setup. */
num_values = do_query_ieeeblock(":SYSTem:SETup?");
printf("Read setup string query (%d bytes).\n", num_values);
/* Write setup string to file. */
fp = fopen ("c:\\scope\\config\\setup.stp", "wb");
num_values = fwrite(ieeeblock_data, sizeof(unsigned char), num_values,
fp);
fclose (fp);
printf("Wrote setup string (%d bytes) to ", num_values);
printf("c:\\scope\\config\\setup.stp.\n");
/* Change settings with individual commands:
/* Set vertical scale and offset. */
do_command(":CHANnel1:SCALe 0.1");
do_query_string(":CHANnel1:SCALe?");
printf("Channel 1 vertical scale: %s\n", str_result);
do_command(":CHANnel1:OFFSet 0.0");
do_query_string(":CHANnel1:OFFSet?");
printf("Channel 1 offset: %s\n", str_result);
/* Set horizontal scale and offset. */
do_command(":TIMebase:SCALe 0.0002");
do_query_string(":TIMebase:SCALe?");
printf("Timebase scale: %s\n", str_result);
do_command(":TIMebase:POSition 0.0");
do_query_string(":TIMebase:POSition?");
printf("Timebase position: %s\n", str_result);
/* Set the acquisition mode. */
do_command(":ACQuire:MODE RTIMe");
do_query_string(":ACQuire:MODE?");
printf("Acquire mode: %s\n", str_result);
/* Or, set up by loading a previously saved setup. */
/* Read setup string from file. */
fp = fopen ("c:\\scope\\config\\setup.stp", "rb");
num_values = fread (ieeeblock_data, sizeof(unsigned char),
IEEEBLOCK_SPACE, fp);
fclose (fp);
printf("Read setup string (%d bytes) from file ", num_values);
printf("c:\\scope\\config\\setup.stp.\n");
/* Restore setup string. */
num_values = do_command_ieeeblock(":SYSTem:SETup", num_values);
printf("Restored setup string (%d bytes).\n", num_values);
/* Set the desired number of waveform points,
* and capture an acquisition. */
do_command(":ACQuire:POINts 32000");
do_command(":DIGitize");
}
/* Analyze the captured waveform.
* --------------------------------------------------------------- */
void analyze (void)
{
double wav_format;
double acq_type;
double wav_points;
double avg_count;
double x_increment;
double x_origin;
double y_increment;
double y_origin;
FILE *fp;
int num_values; /* Number of bytes returned from instrument. */
int i;
/* Make measurements.
* ------------------------------------------------------------- */
do_command(":MEASure:SOURce CHANnel1");
do_query_string(":MEASure:SOURce?");
printf("Measure source: %s\n", str_result);
do_command(":MEASure:FREQuency");
do_query_number(":MEASure:FREQuency?");
printf("Frequency: %.4f kHz\n", num_result / 1000);
do_command(":MEASure:VAMPlitude");
do_query_number(":MEASure:VAMPlitude?");
printf("Vertical amplitude: %.2f V\n", num_result);
/* Download the screen image.
* ------------------------------------------------------------- */
/* Read screen image. */
num_values = do_query_ieeeblock(":DISPlay:DATA? PNG");
printf("Screen image bytes: %d\n", num_values);
/* Write screen image bytes to file. */
fp = fopen ("c:\\scope\\data\\screen.png", "wb");
num_values = fwrite(ieeeblock_data, sizeof(unsigned char), num_values,
fp);
fclose (fp);
printf("Wrote screen image (%d bytes) to ", num_values);
printf("c:\\scope\\data\\screen.bmp.\n");
/* Download waveform data.
* ------------------------------------------------------------- */
/* Get the waveform type. */
do_query_string(":WAVeform:TYPE?");
printf("Waveform type: %s\n", str_result);
/* Get the number of waveform points. */
do_query_string(":WAVeform:POINts?");
printf("Waveform points: %s\n", str_result);
/* Set the waveform source. */
do_command(":WAVeform:SOURce CHANnel1");
do_query_string(":WAVeform:SOURce?");
printf("Waveform source: %s\n", str_result);
/* Choose the format of the data returned: */
do_command(":WAVeform:FORMat WORD");
do_query_string(":WAVeform:FORMat?");
printf("Waveform format: %s\n", str_result);
/* Display the waveform settings: */
do_query_number(":WAVeform:XINCrement?");
x_increment = num_result;
printf("Waveform X increment: %e\n", x_increment);
do_query_number(":WAVeform:XORigin?");
x_origin = num_result;
printf("Waveform X origin: %e\n", x_origin);
do_query_number(":WAVeform:YINCrement?");
y_increment = num_result;
printf("Waveform Y increment: %e\n", y_increment);
do_query_number(":WAVeform:YORigin?");
y_origin = num_result;
printf("Waveform Y origin: %e\n", y_origin);
/* Read waveform data. */
num_values = do_query_ieeeblock_words(":WAVeform:DATA?");
printf("Number of data values: %d\n", num_values);
/* Open file for output. */
fp = fopen("c:\\scope\\data\\waveform_data.csv", "wb");
/* Output waveform data in CSV format. */
for (i = 0; i < num_values - 1; i++)
{
/* Write time value, voltage value. */
fprintf(fp, "%9f, %6f\n",
x_origin + ((float)i * x_increment),
((float)ieeeblock_data_words[i] * y_increment) + y_origin);
}
/* Close output file. */
fclose(fp);
printf("Waveform format WORD data written to ");
printf("c:\\scope\\data\\waveform_data.csv.\n");
}
/* Send a command to the instrument.
* --------------------------------------------------------------- */
void do_command(command)
char *command;
{
char message[80];
strcpy(message, command);
strcat(message, "\n");
err = viPrintf(vi, message);
if (err != VI_SUCCESS) error_handler();
check_instrument_errors();
}
/* Command with IEEE definite-length block.
* --------------------------------------------------------------- */
int do_command_ieeeblock(command, num_bytes)
char *command;
int num_bytes;
{
char message[80];
int data_length;
strcpy(message, command);
strcat(message, " #8%08d");
err = viPrintf(vi, message, num_bytes);
if (err != VI_SUCCESS) error_handler();
err = viBufWrite(vi, ieeeblock_data, num_bytes, &data_length);
if (err != VI_SUCCESS) error_handler();
check_instrument_errors();
return(data_length);
}
/* Query for a string result.
* --------------------------------------------------------------- */
void do_query_string(query)
char *query;
{
char message[80];
strcpy(message, query);
strcat(message, "\n");
err = viPrintf(vi, message);
if (err != VI_SUCCESS) error_handler();
err = viScanf(vi, "%t", str_result);
if (err != VI_SUCCESS) error_handler();
check_instrument_errors();
}
/* Query for a number result.
* --------------------------------------------------------------- */
void do_query_number(query)
char *query;
{
char message[80];
strcpy(message, query);
strcat(message, "\n");
err = viPrintf(vi, message);
if (err != VI_SUCCESS) error_handler();
err = viScanf(vi, "%lf", &num_result);
if (err != VI_SUCCESS) error_handler();
check_instrument_errors();
}
/* Query for numbers result.
* --------------------------------------------------------------- */
void do_query_numbers(query)
char *query;
{
char message[80];
strcpy(message, query);
strcat(message, "\n");
err = viPrintf(vi, message);
if (err != VI_SUCCESS) error_handler();
err = viScanf(vi, "%,10lf\n", dbl_results);
if (err != VI_SUCCESS) error_handler();
check_instrument_errors();
}
/* Query for an IEEE definite-length byte block result.
* --------------------------------------------------------------- */
int do_query_ieeeblock(query)
char *query;
{
char message[80];
int data_length;
strcpy(message, query);
strcat(message, "\n");
err = viPrintf(vi, message);
if (err != VI_SUCCESS) error_handler();
data_length = IEEEBLOCK_SPACE;
err = viScanf(vi, "%#b\n", &data_length, ieeeblock_data);
if (err != VI_SUCCESS) error_handler();
if (data_length == IEEEBLOCK_SPACE )
{
printf("IEEE block buffer full: ");
printf("May not have received all data.\n");
}
check_instrument_errors();
return(data_length);
}
/* Query for an IEEE definite-length word block result.
* --------------------------------------------------------------- */
int do_query_ieeeblock_words(query)
char *query;
{
char message[80];
int data_length;
strcpy(message, query);
strcat(message, "\n");
err = viPrintf(vi, message);
if (err != VI_SUCCESS) error_handler();
data_length = IEEEBLOCK_SPACE;
err = viScanf(vi, "%#hb\n", &data_length, ieeeblock_data_words);
if (err != VI_SUCCESS) error_handler();
if (data_length == IEEEBLOCK_SPACE )
{
printf("IEEE block buffer full: ");
printf("May not have received all data.\n");
}
check_instrument_errors();
return(data_length);
}
/* Check for instrument errors.
* --------------------------------------------------------------- */
void check_instrument_errors()
{
char str_err_val[256] = {0};
char str_out[800] = "";
err = viQueryf(vi, ":SYSTem:ERRor? STRing\n", "%t", str_err_val);
if (err != VI_SUCCESS) error_handler();
while(strncmp(str_err_val, "0,", 2) != 0 )
{
strcat(str_out, ", ");
strcat(str_out, str_err_val);
err = viQueryf(vi, ":SYSTem:ERRor? STRing\n", "%t", str_err_val);
if (err != VI_SUCCESS) error_handler();
}
if (strcmp(str_out, "") != 0)
{
printf("INST Error%s\n", str_out);
err = viFlush(vi, VI_READ_BUF);
if (err != VI_SUCCESS) error_handler();
err = viFlush(vi, VI_WRITE_BUF);
if (err != VI_SUCCESS) error_handler();
}
}
/* Handle VISA errors.
* --------------------------------------------------------------- */
void error_handler()
{
char err_msg[1024] = {0};
viStatusDesc(vi, err, err_msg);
printf("VISA Error: %s\n", err_msg);
if (err < VI_SUCCESS)
{
exit(1);
}
}