Using DaqCOM with a DaqBoard2000

The DaqCOM Programming tool installation contains program examples for the 3000 series devices. However users of the 2000 and 1000 series devices are left in the dark. This article will discuss a few of the DaqCOM basics in an effort smooth the learning curve a little. For the complete program, download the example attached to this article.

If you need to install the programming object visit the IOtech Software Download page:

To use DaqCOM one only needs to set a reference to the object from within the project. MCC supports Microsoft Visual Studio VB, C++ and CSharp. To set a reference in MS Visual Studio, right mouse click the project in the Project Explorer and select Add References. On the dialog that appears switch over to the COM tab and select IOtech DaqCOM 2.401. Now add a reference to the DaqCOM name space using either imports or using key words.  For example, "Using DAQCOMLib;"

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using DAQCOMLib;

        static void Main(string[] args)

The "using DAQCOMLib" statements references DaqCOM's namespace which enables your program to define DaqCOM object types. For example the DaqSystem is the top level object which contains Acquisition objects. Here we define DaqSystem and obtain an Acquisition object by adding it to the DaqSystem.

            DaqSystem pSys = new DaqSystem();
            Acq pAcq = pSys.Add();

Device communication is established using a naming convention. Below demonstrates the opening procedure in which DaqCOM is told to expect a DaqBoard2000 that has the name "DaqBoard2K0". Upon successful completion of the Open statement communication has been established otherwise an error would have been thrown.

pAcq.Devices.Add(DeviceType.dtDaqBoard2000, "");
pAcq.Devices[1].DeviceIdentity = "DaqBoard2k0";
pAcq.Devices[1].OpenMethod = DeviceOpenMethod.domOpenBySystemName;

There is no need to define a device object because it can always be referenced using the Acquisition object. 

The following defines variable used to add channels to a device object. This is done simply to make the program more readable because some of the names get quite long.
DeviceBaseChannel Channel0 = DeviceBaseChannel.dbcDaqChannel0;
DeviceBaseChannel Channel1 = DeviceBaseChannel.dbcDaqChannel1;
DeviceModulePosition Position0 = DeviceModulePosition.dmpPosition0;
AnalogInputType InputType = AnalogInputType.aitDirect;
The next step is to add channels to the Device object. The Device object has a collection called AnalogInputs which contain an AnalogInput. Notice the first is plural. An AnalogInput can be a single channel or many channels as in the case of DBK and WBK signal conditioning / channel expansion hardware. In its simplest form, the DaqBoard AnalogInput contains one channel object. The following adds an AnalogInput to the AnalogInputs collection located on the device that was added above.

pAcq.Devices[1].AnalogInputs.Add(InputType, Channel0, Position0);

The InputType describes the AnalogInput and tells DaqCOM what hardware to expect. DaqBoard2000 boards have the ability to add expansion hardware so the enumeration would differentiate between an on board channel and perhaps an external connected DBK80, which has 16 channels. The Channel0 variable is the base address and Position0 is a sub address - as in the case where more than one board can be added to one address. For the DaqBoard2000, each channel can be expanded up to 16* however, if the add on board has less than 16 channels more than one board can be added to a particular channel hence, the reason for the sub address.

Here is where I would like to differentiate between two fundamental object types: Generic & Specific. Generic is similar to a base class in C++ in that it has properties and methods common to all hardware. Specific on the other hand, has generic properties/methods plus additional features not common to the rest. The following defines a channel object specific to the 2000 series product line as opposed to a generic AnalogChannel object.
Daq2000DirectAIChannel pch = (Daq2000DirectAIChannel)pAcq.Devices[1].AnalogInputs[1].Channels[1];
pch.DifferentialMode = false;

The Ranges object collection contain individual Range objects. To get the range object use the ByType method designating the range enumeration. The enumeration rtBipolar5 is equivalent to ± 5 volts. If it had been rtUnipolar5 the range would have been 0 to 5 volts. A range type of rtBipolar0_1 is read as ±0.1 volts where the underscore is a decimal point. There are one hundred or so ranges so one needs to check the device specifications to determine the valid ones for the device.

Range pRange = pch.Ranges.get_ItemByType(RangeType.rtBipolar5); 

Finally to make the channel an active one, it must be included in the ScanList object as follows.


The following demonstrates adding a second channel.

pAcq.Devices[1].AnalogInputs.Add(InputType, Channel1, Position0);
pch = (Daq2000DirectAIChannel)pAcq.Devices[1].AnalogInputs[2].Channels[1];
pch.DifferentialMode = false;
pRange = pch.Ranges.get_ItemByType(RangeType.rtBipolar5); 

For a basic acquisition we need to specify how much data to acquire and at what rate. The following configures the acquisition for 100 samples from each channel and to acquire those samples at 1000 Hz. Here the term Scan is define to mean one measurement from each channel in the Scan List. If two channels are in the Scan List then an acquisition consisting of a ScanCount = 100 would return 200 measurements.

pAcq.Config.ScanCount = 100;
pAcq.Config.ScanRate = 1000; 

Now define how the acquisition is to start and stop. This example uses the sttImmediate start type which instructs the driver to start on receiving the Arm command. The stop is set to sptScanCount which means it will stop when the 100 scan have be acquired. Many other starts and stop types are defined but for this basic example I will keep it simple.


Finally, the following algorithm polls the driver for a complete status, reads and displays the data on a console window. If using other start types you might need to first poll for triggered status then poll for data available. For example, if the completion status is equal to AcqCompletionStatus.acsPending the acquisition is active and data can be read. Here you may want to also check for available data via the Acq.DataStore.AvailableScan property.

                } while (pAcq.CompletionStatus != AcqCompletionStatus.acsComplete);

                int ChanCount = pAcq.Config.ScanList.Count;
                int ScanCount = pAcq.Config.ScanCount;

                //allocate an array for the data
                System.Array sampArray = new float[ScanCount * ChanCount];

                int nScans = pAcq.DataStore.FetchData(ref sampArray, 100);
                for (int row = 0; row < nScans; row++)
                    for (int Col = 0; Col < ChanCount; Col++)
                        float channelData = (float)sampArray.GetValue(Col);
                        Console.Write("{0:F} ", channelData.ToString(string.Format("00.0000")));
                sampArray = null;
                Console.Write("Press <ENTER> to exit...\r");


        } // end main bracket

*DBK90 is the only exception to the 16 channel rule and allows 56 channels.

Posted 10/11/2012 11:37:47 AM by Administrator