/* * K195A Keithley digital multimeter control program * * This program demonstrates the use of the INES GPIB * native C++ API for instrument control purposes. * * (c) 2005, 2006 */ #include <iostream> /* for console messages */ #include <assert.h> /* to catch the unexpected ... */ /* * inclusion of the API header files */ #include "gpib/gu_c.hxx" #include "umi/umi_k.hxx" namespace Gif=INdepGpib100; /* namespace shorthands */ namespace Umi=INdepUmi100; UMI_KERNEL_INIT; /* kernel interface initializer */ int k195a(Gif::GpibControl *pgc); /* forward declaration */ /* * main() function * * one invocation argument is required (the interface descriptor), * which tells us which GPIB interface to work with. * * the format of the interface descriptor depends on the operating system * and the particular interface adaptor used. */ int main(int argc, char **argv) { if (argc < 2) { std::cerr << "usage: " << argv[0] << " <interface>" << std::endl; /* can't work without interface descriptor */ return 2; } /* * Gif::GpibInterfaceControl is a factory class, i.e. is * required to construct the API object. * * It requires the interface descriptor string as it's argument. */ Gif::GpibInterfaceControl gi(argv[1]); if (!gi) { /* * The creation of the API object may fail. For this case * an error message is provided. */ std::cerr << argv[0] << ": can't open " << argv[1] << ' ' << gi << std::endl; /* can't work without API object */ return 2; } /* * Now, as we are sure to have an interface to work with, * call the instrument handler. The API object to * work with is read from the factory 'gi' by the member pGuc() */ return k195a(gi.pGuc()); } /* * definition the the controller GPIB address (GAD_CO) * and the instrument address (GAD_K195A). * * Instrument addresses are set up at the instruments control panels or * switches. * * For the controller address, any non-conflicting, valid GPIB address * may be used. * */ #define GAD_CO 0x1e #define GAD_K195A 9 /* * failed() sends an error message composed from several sources * to the user. It returns an int to make it convenient to return * from a function in a single line, e.g. return failed(...); */ int failed( const Gif::GpibControl *pgc, const char *sz, int iLine=0 ) { std::cerr << *pgc << std::endl; return 2; } /* * k195a() -- The instrument handler. * * pgc - Controller API object to work with. * * return 0 on success, nonzero otherwise. */ int k195a(Gif::GpibControl *pgc) { /* * Initialize the interface and provide the interface (controller) address */ if (!pgc->open( true, GAD_CO)) return failed(pgc, "open"); /* * Send the interface clear signal. This resets the interfaces * of the connected devices. */ if (!pgc->ifc(UmiTime(1,0))) return failed(pgc, "ifc"); /* * Set the REMOTE ENABLE line true. This * makes all instruments ready for remote control. */ if (!pgc->ren( true)) return failed(pgc,"ren"); /* * Optionally enable logging to the supplied std::ostream * Use this option to trace bus operations. */ pgc->setLog(&std::cerr); /* * Send the SDC (Selected Device Clear) to the addressed * instrument. This should clear (reset) the instruments * functions. */ if (!pgc->clear(GAD_K195A, UmiTime(1,0))) return failed(pgc, "clear"); int cRun; /* counter */ for (cRun=0; cRun<10; cRun++ ) { /* * Send data from a \0 terminated string to the instrument. * * These data are instrument specific and _not_ defined by the IEEE488.1 * standard. See the documents provided with your instrument(s). */ if (!pgc->sendsz(GAD_K195A, "F0R7Z0P0Q0X")) return failed(pgc, "send", __LINE__); /* * Receive data (measurement samples) from the K195A DMM */ char mpch[2048]; /* buffer */ unsigned c=sizeof(mpch); /* size */ if (!pgc->receive(mpch, &c, GAD_K195A)) return failed(pgc, "receive", __LINE__); /* show the data */ std::cout.write((char*)mpch, c); std::cout.flush(); /* * Read pending SRQ (Service Request) indications from the instrument. * The timeout is 0, thus the wait returns immediately, * regardless if there was any indication. */ pgc->wait(Gif::E_SRQI, 0); if (1) { /* Sample into internal buffer */ if (!pgc->sendsz(GAD_K195A, "D RUNX")) return failed(pgc, "send", __LINE__); /* High speed sample until buffer full */ if (!pgc->sendsz(GAD_K195A, "S0M4X")) return failed(pgc, "send", __LINE__); /* Enable auto range */ if (!pgc->sendsz(GAD_K195A, "R0X")) return failed(pgc, "send", __LINE__); /* Clear buffer */ if (!pgc->sendsz(GAD_K195A, "Q0X")) return failed(pgc, "send", __LINE__); /* No delay */ if (!pgc->sendsz(GAD_K195A, "Q01X")) return failed(pgc, "send", __LINE__); } /* * Wait for the buffer to fill, but not longer than 10 sec. */ std::cout << "wait..." << std::endl; if (!pgc->wait(Gif::E_SRQI, Umi::Time(10))) return failed(pgc, "wait", __LINE__); std::cout << "done" << std::endl; if (1) { /* * Read the status byte (we do not evaluate) * Required to reset the SRQ indication */ char ch; if (!pgc->readStatusByte(&ch, GAD_K195A)) return failed(pgc, "spoll", __LINE__); std::cout << std::hex << (int)((unsigned char)ch) << std::endl; /* Read complete buffer on next transfer */ if (!pgc->sendsz(GAD_K195A, "B1X")) return failed(pgc, "send", __LINE__); /* * Read the buffer data */ c=sizeof(mpch); if (!pgc->receive(mpch, &c, GAD_K195A)) return failed(pgc, "receive", __LINE__); /* show the data */ std::cout.write((char*)mpch, 24) << std::endl; std::cout << std::dec << c << std::endl; } } /* * Send 'raw' commands to the bus. * * Here, the GPIB commands UNL and UNT (ASCII codes '?' and '_' ) * are sent to unaddress all interfaces. */ pgc->cmd("?_", 2, Umi::Time(1,0)); if (pgc->isFail()) return failed(pgc, "cmd"); std::cout << cRun << " done " << std::endl; /* * Close the interface. */ if (!pgc->close()) return failed(pgc, "close"); /* * Now we're done */ return 0; }