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