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