1 /*
   2  * $RCSfile: extcal.cpp,v $
   3  * $Revision: 1.12 $
   4  * $Date: 2009/11/29 20:19:19 $
   5  * jEdit:tabSize=4:indentSize=4:collapseFolds=1:
   6  *
   7  * program to externally calibrate USB-AI16-16
   8  */
   9 
  10 
  11 // {{{ build instructions
  12 /*
  13  * g++ extcal.cpp -lclassaiousb -laiousbcpp -lusb-1.0 -o extcal
  14  *   or
  15  * g++ -ggdb extcal.cpp -lclassaiousbdbg -laiousbcppdbg -lusb-1.0 -o extcal
  16  */
  17 // }}}
  18 
  19 // {{{ includes
  20 #include <iostream>
  21 #include <iomanip>
  22 #include <stdio.h>
  23 #include <stdlib.h>
  24 #include <string.h>
  25 #include <USBDeviceManager.hpp>
  26 #include <USB_AI16_Family.hpp>
  27 // }}}
  28 
  29 using namespace AIOUSB;
  30 using namespace std;
  31 
  32 int main( int argc, char *argv[] ) {
  33 /*API*/ USBDeviceManager deviceManager;
  34     try {
  35         const int CAL_CHANNEL = 0;
  36         cout <<
  37             "USB-AI16-16 sample program version 1.12, 29 November 2009\n"
  38 /*API*/     "  AIOUSB C++ class library version " << deviceManager.VERSION_NUMBER << ", " << deviceManager.VERSION_DATE << "\n"
  39 /*API*/     "  AIOUSB library version " << deviceManager.getAIOUSBVersion() << ", " << deviceManager.getAIOUSBVersionDate() << "\n"
  40             "\n"
  41             "  This program demonstrates external calibration of a USB-AI16-16 device\n"
  42             "  on the USB bus. For simplicity, it uses the first such device found on\n"
  43             "  the bus.\n"
  44             "\n"
  45             "  This external calibration procedure allows you to inject a sequence of\n"
  46             "  precise voltages into the USB-AI16-16 that will be used to calibrate its\n"
  47             "  A/D. This procedure calibrates the A/D using channel " << CAL_CHANNEL << " on the 0-10V range.\n"
  48             "  A minimum of 2 calibration points are required. The procedure is as follows:\n"
  49             "\n"
  50             "  1) Adjust a precision voltage source to a desired target voltage. These\n"
  51             "     target voltages do not have to be evenly spaced or provided in any\n"
  52             "     particular order.\n"
  53             "\n"
  54             "  2) When you have adjusted the precision voltage source to your desired\n"
  55             "     target, type in the exact voltage being fed into the USB-AI16-16 and\n"
  56             "     press <Enter>. This program will read the A/D and display the reading,\n"
  57             "     asking you to accept it or not. If it looks acceptable, press 'y'.\n"
  58             "     Otherwise, press any other key and the program will retake the reading.\n"
  59             "\n"
  60             "  3) When you are finished calibrating, press <Enter> without entering a\n"
  61             "     voltage, and the A/D will be calibrated using the data entered, and\n"
  62             "     the calibration table will be saved to a file in a format that can be\n"
  63             "     subsequently loaded into the A/D.\n"
  64             "\n";
  65 
  66 /*API*/ deviceManager.open();
  67 /*API*/ DeviceList devices = deviceManager.getDeviceByProductID( USB_AI16_16A, USB_AI12_128E );
  68         if( devices.size() > 0 ) {
  69 /*API*/     deviceManager.printDevices();
  70             USB_AI16_Family *const device = ( USB_AI16_Family * ) devices.at( 0 );  // get first device found
  71             try {
  72                 /*
  73                  * set up A/D in proper mode for calibrating, including a default calibration table
  74                  */
  75                 cout << "Calibrating A/D, may take a few seconds ... " << flush;
  76 /*API*/         device->reset()
  77 /*API*/             .setCommTimeout( 1000 );
  78 /*API*/         device->adc()
  79 /*API*/             .setCalMode( AD_CAL_MODE_NORMAL )
  80 /*API*/             .setDiscardFirstSample( true )
  81 /*API*/             .setTriggerMode( AD_TRIGGER_SCAN )
  82 /*API*/             .setGainCodeAndDiffMode( AD_GAIN_CODE_0_10V, false )
  83 /*API*/             .setOversample( 100 )
  84 /*API*/             .calibrate( false, false, "" );
  85                 cout << "successful" << endl;
  86                 DoubleArray points;             // voltage-count pairs
  87                 while( true ) {
  88                     std::string commandLine;
  89                     unsigned short counts;
  90                     cout
  91                         << "Measuring calibration point " << points.size() / 2 + 1 << ':' << endl
  92                         << "  Feed a voltage into channel " << CAL_CHANNEL << " and enter voltage here" << endl
  93                         << "  (enter nothing to finish and calibrate A/D): ";
  94                     getline( cin, commandLine );
  95                     if( commandLine.empty() )
  96                         break;                  // from while()
  97                     points.insert( points.end(), strtod( commandLine.c_str(), 0 ) );
  98 #if defined( SIMULATE_AD )
  99                     cout << "  Enter A/D counts: ";
 100                     getline( cin, commandLine );
 101                     if( commandLine.empty() )
 102                         break;                  // from while()
 103                     counts = strtol( commandLine.c_str(), 0, 0 );
 104                     points.insert( points.end(), counts );
 105 #else
 106                     try {
 107 /*API*/                 counts = device->adc().read( CAL_CHANNEL );
 108                         cout << "  Read " << counts << " A/D counts ("
 109 /*API*/                     << device->adc().countsToVolts( CAL_CHANNEL, counts )
 110                             << " volts), accept (y/n)? ";
 111                         getline( cin, commandLine );
 112                         if( commandLine.compare( "y" ) == 0 )
 113                             points.insert( points.end(), counts );
 114                     } catch( exception &ex ) {
 115                         cerr << "Error \'" << ex.what() << "\' occurred while reading A/D input" << endl;
 116                     }   // catch( ...
 117 #endif
 118                 }   // while( true )
 119                 if( points.size() >= 4 ) {
 120                     try {
 121                         char fileName[ 100 ];
 122 /*API*/                 sprintf( fileName, "ADC-Ext-Cal-Table-%llx", ( long long ) device->getSerialNumber() );
 123 /*API*/                 device->adc().calibrate( points, false, fileName );
 124                         cout << "External calibration of A/D successful, table saved in " << fileName << endl;
 125                     } catch( exception &ex ) {
 126                         cerr << "Error \'" << ex.what() << "\' occurred while externally calibrating A/D."
 127                             << " This usually occurs because the input voltages or measured counts are not unique and ascending." << endl;
 128                     }   // catch( ...
 129                 } else
 130                     cerr << "Error: you must provide at least two points" << endl;
 131             } catch( exception &ex ) {
 132                 cerr << "Error \'" << ex.what() << "\' occurred while configuring device" << endl;
 133             }   // catch( ...
 134         } else
 135             cout << "No USB-AI16-16 devices found on USB bus" << endl;
 136 /*API*/ deviceManager.close();
 137     } catch( exception &ex ) {
 138         cerr << "Error \'" << ex.what() << "\' occurred while initializing device manager" << endl;
 139 /*API*/ if( deviceManager.isOpen() )
 140 /*API*/     deviceManager.close();
 141     }   // catch( ...
 142 }   // main()
 143 
 144 
 145 /* end of file */