Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

Agilent 34410A IVIDmm Class-compliant examples

    Hello,
I am extremely new to the IVI world. I would like to program my new digital multimeter using the IVI classes only (not the Agilent 34410A instrument specific interfaces but the standard IVI classes).
Doing so will allow me in the future to use a different DMM (Digital Multimeter) from another manufacturer or still Agilent but with a different newer system.

I would like to know if there is a good website that shows examples on how to initialized and do basic functions using C++ with that DMM?

So far, Agilent provided examples using their instrument specifique interface:

.h file:

#define IVIDRIVERTYPELIB_LIBID "libid:47ed5120-a398-11d4-ba58-000064657374"
#import IVIDRIVERTYPELIB_LIBID version("1.0") no_namespace
#define IVIDMMTYPELIB_LIBID "libid:47ed5122-a398-11d4-ba58-000064657374"
#import IVIDMMTYPELIB_LIBID version("3.0") no_namespace
#define GLOBMGR_LIBID "libid:db8cbf00-d6d3-11d4-aa51-00a024ee30bd"
#import GLOBMGR_LIBID version("3.0") no_namespace
#define Agilent34410_LIBID "libid:7e65c8d3-046f-42d3-ba3f-4c7c31925df5"
#import Agilent34410_LIBID no_namespace

.cpp file

try
    {
        IAgilent34410Ptr spDriver34410(__uuidof(Agilent34410));
               
        // Setup IVI-defined initialization options
        CString strStandardInitOptions =
            "Cache=true, InterchangeCheck=false, QueryInstrStatus=true, RangeCheck=true, RecordCoercions=false, Simulate=false";
           
        // Initialize the driver
        spDriver34410->Initialize("AGILENT_DMM", VARIANT_FALSE, VARIANT_FALSE, LPCTSTR(strStandardInitOptions));   
        IAgilent34410Ptr spAgilent34410 = spDriver34410;
    }

But if this 34410 doesn't exist in 5 years from now, this code become unusable!

Any help using regular IVI compliant interfaces/classes?
Thanks

0 Kudos
Message 1 of 6
(6,249 Views)

Unfortunately I have never seen good example codes for IVI-COM IviDmm class interfaces.

To keep interoperability between different DMM models using IVI-COM DMM class interfaces, first you must forget about IAgilent34410 interface, which always requires the specific Agilent model at runtime.  Instead, your application must only use IVI-defined IIviDmm interfaces. Also, a special appoach that uses IVI Session Factory is required to create a virtualized driver session, bacause IviDmmTypeLib.DLL only provides class interfaces and not provide driver loader engine.

Here is an example I wrote:

/////////////
// STDAFX.H

#import "c:/progra~1/Ivi/bin/IviDriverTypeLib.DLL" no_namespace named_guids
#import "c:/progra~1/Ivi/bin/IviDmmTypeLib.DLL" no_namespace named_guids
#import "c:/progra~1/Ivi/bin/IviSessionFactory.DLL" no_namespace named_guids

////////////////////////////////
// You app code:

 try
  {
   IIviSessionFactoryPtr spSF(__uuidof(IIviSessionFactory));             
   IIviDmmPtr spDmm = spSF->CreateSession( "AGILENT_DMM");

   spDmm->Initialize( "AGILENT_DMM", VARIANT_FALSE, VARIANT_FALSE, "");   

   IIviDmmMeasurementPtr spMeas = spDmm->Measurement;
   double dReading = spMeas->Read( 3000);

   spDmm->Close();

 }
 catch( _com_error e) {
 }

////////////////////////////////

To map your Logical Name ("AGILENT_DMM" in above example), it must be properly configured in NI-MAX, so that it can be associated to Agilent34410 driver including its VISA address. Then make sure to assign Agilent34410 IVI-COM driver for its Software Module. 

To create a DMM driver instance, use CreateSession() method of IIviSessionFactory.  You can just typecast (actually QueryInterface) the returned IUnknown pointer to IIviDmm.  (The driver module loaded by the IVI Session Factory will be an Agilent34410 object, therefore QueryInterface to IIviDmm must succeed.)  After that, you can use any DMM class interfaces without having any dependency to specific Agilent DMM models in your code.  To change your DMM hardware to other model, just change NI-MAX configuration. 

Hope this helps,
Makoto

Message 2 of 6
(6,221 Views)
Makoto,
After a few days trying around this DMM, I noticed that the librairies within the IVI are only interfaces.
In order to use them, they need to be implemented with the Agilent 34410A.
Here is a few lines of code that I put together, do you think  it will be Agilent dependent?


/////////////
stdafx.h

#import "IviDriverTypeLib.dll" no_namespace raw_interfaces_only
#import "IviDMMTypeLib.dll" no_namespace raw_interfaces_only

#define GLOBMGR_LIBID "libid:db8cbf00-d6d3-11d4-aa51-00a024ee30bd"
#import GLOBMGR_LIBID version("3.0") no_namespace


#define Agilent34410_LIBID "libid:7e65c8d3-046f-42d3-ba3f-4c7c31925df5"
#import Agilent34410_LIBID no_namespac

IIviDmmPtr mpDriverDMM;
IIviDmmMeasurementPtr mpDriverDMMMeasurement;

/////////////

//main code

    ::CoInitialize(NULL);
    IAgilent34410Ptr spDriver34410(__uuidof(Agilent34410));

    mpDriverDMM  = spDriver34410;
    mpDriverDMMMeasurement = spDriver34410;

    CString strStandardInitOptions =  "Cache=true, InterchangeCheck=false, QueryInstrStatus=true, RangeCheck=true, RecordCoercions=false, Simulate=false";
               
    mpDriverDMM->Initialize(L"AGILENT_DMM", VARIANT_FALSE, VARIANT_FALSE, CComBSTR(strStandardInitOptions));
    mpDriverDMM->put_Function(IviDmmFunctionACVolts);
    mpDriverDMMMeasurement->Initiate();
    double  Reading = 0.0;
    mpDriverDMMMeasurement->Fetch(500,&Reading);


    mpDriverDMM->Close();
    ::CoUninitialize();

/////////////

However, I will give a try now to the example code you gave me.
Thank you for your answer.



 
0 Kudos
Message 3 of 6
(6,208 Views)
Your approach is still dependent to Agilent34410 driver.
 
IIviDmmPtr mpDriverDMM;
...
IAgilent34410Ptr spDriver34410(__uuidof(Agilent34410));
mpDriverDMM  = spDriver34410;
 
At this point of time, mpDriverDMM is referencing to an Agilent34410 driver instance.  Just loading Agilent34410 driver does not require the 34410A hardware to be connected.  However...
mpDriverDMM->Initialize(L"AGILENT_DMM", .....);

This Initialize() call is actually invoking the Initialize() method that is embedded in the Agilent34410 driver DLL.  Although the Initialize() method takes the logical name "AGILENT_DMM", the method does not reference to Software Module configuration of "AGILENT_DMM" in the IVI Configuration Store.  It just picks up the VISA Address (Hardware Asset) and default IVI settings such as Cache, QueryInstrStatus, etc..., but Software Module (driver DLL) configuration is ignored.

Therefore, even if the "AGILENT_DMM" Logical Name was configured to use any other Software Module such as Fluke45 or Advantest6552 IviDmm IVI-COM driver (assuming they exist), the software module configuration will not be referenced by Initialize() method, therefore Agilent34410 Initialize() function will be finally executed. 

The only DLL module, which dynamically selects a driver DLL by referencing IVI Configuration Store, is the IVI Session Factory in the IVI-COM world.  In contrast, IVI-C class drivers have this kind of loader mechanism in them, therefore no need to use IVI Session Factory. 

Message 4 of 6
(6,196 Views)
Makoto,

Thanks for your answers.
I tried to build your code and in the line I have

IIviDmmPtr spDmm = spSF->CreateSession( "AGILENT_DMM");

I got that error:
Error    1    error C2660: 'IIviSessionFactory::CreateSession' : function does not take 1 arguments  


Do you have the same error message?
0 Kudos
Message 5 of 6
(6,188 Views)
The complier is apparently claiming that the 2nd param is missing. 
 
The CreateSession() method physically has the 2nd parameter in its IDL definition - [out,retval] IUnknown** ppDriver.  If your #import statement (in STDAFX.H) is using raw_interface_only, your app code must pass the 2nd param explicitly to receive the returned IUnknown pointer.  My example was NOT using raw_interface_only on #import, therefore the smart-pointer syntax had replaced the 2nd [out,retval] param with the return value, as if the code were written in Visual Basic.
 
Message 6 of 6
(6,177 Views)