Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

tek210 gpib programming

Hi,


Im dealing with grabbing curve data from a old tek210 scope with the
gpib interface. Since its crucial to get both channels at the same
time, my adquisition cycle is:

im pausing the scope
grabbing each channel separately
and then resume adquisition

I do this with a compiled .dll that uses the NI-488-Gpib api and then
call it from a program. The strange problem is that in a PIV with
Windows2000 professional this works nicely for my purpose. But in a
PIII machine with Windows98 i get an "unable to serial poll scope"
error

ibwrt(Dev, "CURVE?\n", 7 );
ibwait(Dev, TIMO | RQS);
ibrsp(Dev, &ResByte);

//either i grab a positive error 3 in this test in windows98
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to serial poll oscilloscope");
return 3;
}

//or either i grab later a "cannot get waveform preamble" error


Any ideas what may cause the different behaviour of the same dll both
in windows 98/P3 and W2000Pro/P4? even the scope is the same in both
cases




The code of the cycle is the following (the called functions code are
displayed at the end of the post)


*-----------------------------------------*------------------------------------*
device = Init_Osciloscopio( "DAT:SOU CH1;:DAT:ENC RIBinary;:DAT:WID
1;:DAT:STAR 1;:DAT:STOP 2500;:HOR:MAIN:SCALE 5e-4;:CH1:SCALE
5e-1;:CH2:SCALE 5e-3\n"
, "SEL:CH1 ON;:SEL:CH2 ON;:ACQ:MOD SAMPLE\n" );

error_code = SendString(device, "ACQUIRE:STATE ON\n");

// Done initialization, now we start adquisition

error_code = Pause(device);

error_code = 1;
while (error_code != 0)
{
device = Init_Osciloscopio( "DAT:SOU CH1;:DAT:ENC RIBinary;:DAT:WID
1;:DAT:STAR 1;:DAT:STOP 2500;:HOR:MAIN:SCALE 5e-4;:CH1:SCALE
5e-1;:CH2:SCALE 5e-3\n"
, "SEL:CH1 ON;:SEL:CH2 ON;:ACQ:MOD SAMPLE\n" );
error_code = SendString(device, "CURVE?\n");
error_code := WriteWaveform(device, CH1_fileout);
}

error_code = 1;
while (error_code != 0)
{
device = Init_Osciloscopio( "DAT:SOU CH1;:DAT:ENC RIBinary;:DAT:WID
1;:DAT:STAR 1;:DAT:STOP 2500;:HOR:MAIN:SCALE 5e-4;:CH1:SCALE
5e-1;:CH2:SCALE 5e-3\n"
, "SEL:CH1 ON;:SEL:CH2 ON;:ACQ:MOD SAMPLE\n" );
error_code = SendString(device, "CURVE?\n");
error_code := WriteWaveform(device, CH2_fileout);
}

error_code = Resume(device);
*-----------------------------*------------------------------------------*






-------------------*---------------------*---------------------------
DLL functions

////////////////////////////////////////////
// INIT_OSCILOSCOPIO( SCOPECONFIG ; ACQWFM )

extern "C" int Init_Osciloscopio(char* ScopeConfigString

, char* AcqWaveformString )
{
int Dev,
LoopCount = 0,
Done = 0;
char ResByte;

/*
char ScopeConfigString[] = "DAT:SOU CH1;:DAT:ENC RIBinary;:DAT:WID
1;"
":DAT:STAR 1;:DAT:STOP 2500;"
":HOR:MAIN:SCALE 5e-4;"
":CH1:SCALE
5e0\n";
char AcqWaveformString[] = "SEL:CH1 ON;:ACQ:MOD SAMPLE\n";
*/

Dev = ibdev(BDINDEX, PRIMARY_ADDR_OF_SCOPE, NO_SECONDARY_ADDR,
TIMEOUT, EOTMODE, EOSMODE);
if (ibsta & ERR)
{
printf("Unable to open device\nibsta = 0x%x iberr = %d\n",
ibsta, iberr);
return 1;
}

ibwrt(Dev, ScopeConfigString, strlen(ScopeConfigString));
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to set waveform characteristics");
return 1;
}

ibwrt(Dev, AcqWaveformString, strlen(AcqWaveformString));
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to set up acquisition");
return 1;
}

ibwrt(Dev, "*SRE 16\n", 8L);
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to set SRE");
return 1;
} return Dev;
}

//////////////////////////////////////////////////
// SENDSTRING( DEV ; MSG )

extern "C" int SendString(int Dev, char* message)
{
ibwrt(Dev, message, strlen(message));
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to set message");
return 1;
} return 0;
}

/////////////////////////////////////
// PAUSE ( DEV )

extern "C" int Pause(int Dev)
{
ibwrt(Dev , "ACQuire:STATE STOP\n", 18L);
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to resume");
return 5;
}
//ibwrt(Dev , "ACQuire:STATE RUN\n", 18L);
}


//////////////////////////////////////
// RESUME ( DEV )

extern "C" int Resume(int Dev)
{
ibwrt(Dev , "ACQuire:STATE RUN\n", 18L);
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to resume");
return 1;
}
//ibwrt(Dev , "ACQuire:STATE RUN\n", 18L);
}

/////////////////////////////////////////////////////////
// WRITEWAVEFORM ( DEV ; FILENAME )

extern "C" int WriteWaveform(int Dev, char* filename)
{
const Addr4882_t address = 7; //the address of the scope
(change to fit your configuration)
const int BUF_SIZE = 2048; //the total buffer size
const int NUM_DEVICES = 31; //maximum number of devices on the bus

char buffer[BUF_SIZE];
char data_buf[BUF_SIZE];
int LoopCount = 0,
Done = 0;

char ResByte;
/*
* The application waits for either the oscilloscope to request
* service or the call to timeout. The wait mask supplied to
* ibwait contains two bits: TIMO and RQS. The TIMO bit limits
* the wait period to the timeout value that was specified in
* the ibdev call; the RQS bit instructs the application to wait
* until the device has requested service. The ibwait call is
* completed when one or more of the specified wait conditions
* becomes true.
*/
ibwait(Dev, TIMO | RQS);
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Error occurred while waiting for Service
Request");
return 1;
}

/*
* If after the ibwait call, the RQS bit in ibsta is not set,
* the Oscilloscope did not request sevice.
*/
if (!(ibsta & RQS))
{
GPIBCleanup(Dev, "Error : Oscilloscope did not request
service");
return 2;
}

ibrsp(Dev, &ResByte);
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to serial poll oscilloscope");
return 3;
}

/*
* If the value is not 0x50, the device did not request service
* as a result of completing the acquisition. In this case, an
* error message is printed and the program exited.
*/
if (ResByte != SERPOLLRESPONSE)
{
printf("Error : Unexpected serial poll response. Expected :
0x%x "
"Received : 0x%x\n", SERPOLLRESPONSE, ResByte);
printf("Cleanup: Taking device off-line\n");
ibonl (Dev, 0);
return 4;
}

/*
* The Curve string from the oscilloscope is read into the
* character variable ValueStr
*/
ibrd(Dev, ValueStr, ARRAYSIZE);
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to read curve data");
return 5;
}

LoopCount++;

ValueStr[ibcntl - 1] = '\0';

printf("\nWaveform No: %d\n\n", LoopCount);
cout << ValueStr<< " :"<< ibcntl << endl;

ibwrt(Dev , "WFMPre?\n" , 8L);
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to request curve preamble");
return 6;
}
ibrd(Dev, data_buf, ARRAYSIZE);
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to read curve preamble");
return 7;
}
data_buf[ibcntl - 1] = '\0';
cout << " preamble: "<< data_buf << endl;



/*
* The application writes the command 'CURVE?' to the
oscilloscope.
* This command requests the oscilloscope to supply the waveform
* data before serial polling it again.
*/

ibwrt(Dev, "CURVE?\n", 7L);
if (ibsta & ERR)
{
GPIBCleanup(Dev, "Unable to request curve data");
return 8;
}

cout << "string conversion "<< endl;
//decode the byte-stream that represents the waveform
TekWaveform wfm = DecodeWaveform(data_buf , ValueStr);
cout << "Desc: " << wfm.description.c_str() << endl;
cout << "Num points: " << wfm.num_points << endl;
cout << "x units: " << wfm.x_units.c_str() << endl;
cout << "x increment: " << wfm.x_increment << endl;
cout << "x offset: " << wfm.x_offset << endl;
cout << "y units: " << wfm.y_units.c_str() << endl;
cout << "y multiplier: " << wfm.y_multiplier << endl;
cout << "y offset: " << wfm.y_offset << endl;
cout << "y zero: " << wfm.y_zero << endl;

ofstream outfile(filename, ios::out);
outfile << wfm.x_units.c_str() << "\t" << wfm.y_units.c_str()
<< endl;
//the x-values are calculated using the x_increment and
x_offset
for(int i = 0; i < wfm.num_points; i++)
outfile << wfm.x_zero + wfm.x_increment * (i -
wfm.x_offset)
<< "\t" << wfm.data_points[i] << endl;
outfile.close();

//clean up after ourselves
DeleteTekWaveform(wfm);

return 0;
}


////////////////////////// Local Library functions
DecodeWaveform( databuffer , valuestr )

struct TekWaveform {
string description; //a string with the description of the
waveform
int num_points; //the number of points in the waveform
string x_units; //a string with the x axis units
double x_increment; //x-axis inter-point spacing
double x_offset; //trigger point offset index
double x_zero;
string y_units; //a string with the y axis units
double y_multiplier; //y-value multiplier
float y_offset; //y-value offset
double y_zero; //y zero intercept
double *data_points; //the points in the waveform


};



TekWaveform DecodeWaveform(char *preamble, char *curve) {
TekWaveform wfm; //declare a waveform
wfm.data_points = NULL; //set to zeros
wfm.num_points = 0;
wfm.x_increment = 0;
wfm.x_offset = 0;
wfm.y_multiplier = 0;
wfm.y_offset = 0;
wfm.y_zero = 0;

string pre(preamble); //make a string out of char*

int byte_number = atoi(pop_string(pre, ';').c_str()); //get
byte number
int bit_number = atoi(pop_string(pre, ';').c_str()); //get bit
number
string encoding = pop_string(pre, ';'); //get encoding
string binary_format = pop_string(pre, ';'); //get binary
format
string byte_order = pop_string(pre, ';'); //get byte order

wfm.num_points = atoi(pop_string(pre, ';').c_str()); //get the
number of points

cout << " numpoints "<< wfm.num_points << endl;

cout << "byteN: "<< byte_number << " bitN: "<< bit_number <<
endl;
cout << "encoding "<<< endl;
cout << "bf " << binary_format << endl;
cout << "bo "<< byte_order<< endl;

/*
if((byte_number != 2) || (bit_number != 16) //check for proper
conditions
|| (encoding.compare("BIN") != 0)
|| (binary_format.compare("RI") != 0)
|| (byte_order.compare("LSB") != 0)
)
return wfm; //return the null waveform if bad
conditions
*/

pop_string(pre, '\"'); //ignore a quote char
wfm.description = pop_string(pre, '\"'); //get the description
pop_string(pre, ';'); //ignore the semicolon

string point_format = pop_string(pre, ';'); //get the point
format
cout << " point format "<< point_format << endl;
if(point_format.compare("Y") != 0) {
wfm.num_points = 0;
return wfm;
}

//this format is describe in the tektronix developer manual
// pag 2-159

wfm.x_increment = atof(pop_string(pre, ';').c_str()); //get x
increment
cout << " x_inc " << wfm.x_increment<< endl;

wfm.x_offset = atoi(pop_string(pre, ';').c_str()); //get x
offset
cout << " x_off " << wfm.x_offset << endl;

wfm.x_zero = atof(pop_string(pre, ';').c_str()); //get x
offset
cout << " x_zero " << wfm.x_zero << endl;

pop_string(pre, '\"'); //ignore a quote char
wfm.x_units = pop_string(pre, '\"'); //get the x-axis units
cout << " x_units " << wfm.x_units << endl;
pop_string(pre, ';'); //ignore the semicolon


wfm.y_multiplier = atof(pop_string(pre, ';').c_str());
cout << " y_mult " << wfm.y_multiplier << endl;


wfm.y_zero = atof(pop_string(pre, ';').c_str());
cout << " y_zero " << wfm.y_zero << endl;

wfm.y_offset = atof(pop_string(pre, ';').c_str());
cout << " y_off " << wfm.y_offset << " cast " <<
*(int*)(&wfm.y_offset)<

pop_string(pre, '\"'); //ignore a quote char
wfm.y_units = pop_string(pre, '\"'); //get y-axis units
cout << " y_units " << wfm.y_units << endl;
pop_string(pre, ';'); //ignore the semicolon




/* Process the data itself. To get values in the right units,
we have to use the multipliers and offsets.
So we have X_i = x_increment * (i - x_offset)
and Y_i = y_zero + y_multiplier * (y_i - y_offset)
where y_i is the value from the byte-stream.
The y-value conversion is done here into the
array of doubles data_points. The x-axis conversion
is done outside, where applicable. */
int start = ((int) curve[1]) - ((int) '0'); //get some header
info
wfm.data_points = new double[wfm.num_points]; //allocate space
char *curve_data = (char *) (curve + 2 ); //pointer magic
for(int i = 0; i < wfm.num_points; i++) //calculate the y
values
//wfm.data_points[i] = ((curve_data[i]);
wfm.data_points[i] = wfm.y_zero + wfm.y_multiplier *
(curve_data[i] - (char)wfm.y_offset);

return wfm; //return the completed waveform
}
0 Kudos
Message 1 of 2
(2,862 Views)
In working through a calibration script for the TDS I have seen issues trying to take readings before the device has had ample time to sync, or settle, to the source. The GPIB returns a Device Dependant Error. Adding a bit of delay before the readings are initially taken resolves the issue.

Not sure if this is a similar situation, just thought I'd mention it in case it was.
0 Kudos
Message 2 of 2
(2,862 Views)