The example below demonstrates how to read a buffer that is being filled continuously with live data. It uses ALoadQueue(..), AInScan(...) and ScaledWinBufToArray(...), GetStatus(...) to read a group of analog input channels. Data is written to an ASCII text file that can be viewed and verified using Excel, DASYLab, NI LabVIEW, MatLab® and other programs capable of text import.
The functionality is as follows, the acquisition puts data into a continuously looping buffer and the program retrieves it one half buffer at a time. The continuous mode is set using the Scan Options enumeration Background and Continuous. Data is collected by ping-pongs between the lower half then the upper looping fast enough to keep up. Care should be taken that data doesn't come in so fast that the program fails to keep up. When this happens a buffer overrun occurs which is condition where unread data get overwritten.
Although not shown below, a few convenience functions were added such as IsError, GetBoardNum, DisplayData, CreateFileHeader and WaitForKey. To view all the functions download the complete Visual Studio 2008 project by extracting the zip file at the bottom.
If starting a new project using Visual Studio, you must first add a reference to the MccDaq object before objects and variables. Adding the reference is usually accomplished by right clicking the Project [under the Project Explorer] and selecting Add Reference.
using System;
using MccDaq;
using System.IO;
namespace AinScanBackgroundContinuousScan
{
class Program
{
public const int BLOCKSIZE = 50;
public const int CHANCOUNT = 4;
public const int FIRSTCHANNEL = 0;
public const int LASTCHANNEL = 3;
public const int FREQ = 100;
public const int BUFFERSIZE = BLOCKSIZE * CHANCOUNT;
public const int HALFBUFFSIZE = BUFFERSIZE / 2;
public const string DEVICE = "1608G";
public static StreamWriter fStream;
static void Main(string[] args)
{
MccDaq.ErrorInfo RetVal;
int BoardNum = 0;
int DeviceChannels = 0;
int Rate = FREQ;
bool ReadLower = true;
BoardNum = GetBoardNum(DEVICE);
if( BoardNum == -1 )
Console.WriteLine("No USB-{0} detected!", DEVICE );
else
{
MccBoard daq = new MccDaq.MccBoard( BoardNum );
daq.BoardConfig.GetNumAdChans(out DeviceChannels);
if (DeviceChannels > 8)
Console.WriteLine( "Single-Ended Channels" );
else
Console.WriteLine( "Differentially-Ended Channels" );
IntPtr buffer = MccService.ScaledWinBufAllocEx( BUFFERSIZE );
if( buffer == IntPtr.Zero )
{
Console.WriteLine( "Bad Handle" );
return;
}
short[] chArray = new short[CHANCOUNT]; //configuration array for channel numbers
Range[] chRange = new Range[CHANCOUNT]; //configuration array for input ranges
chArray[0] = 0;
chArray[1] = 1;
chArray[2] = 2;
chArray[3] = 3;
chRange[0] = Range.Bip10Volts;
chRange[1] = Range.Bip10Volts;
chRange[2] = Range.Bip10Volts;
chRange[3] = Range.Bip10Volts;
RetVal = daq.ALoadQueue( chArray, chRange, CHANCOUNT );
IsError(RetVal);
//setup the acquisiton
RetVal = daq.AInScan( FIRSTCHANNEL,
LASTCHANNEL,
BUFFERSIZE,
ref Rate,
Range.Bip10Volts,
buffer,
ScanOptions.Background | ScanOptions.ScaleData | ScanOptions.Continuous
);
IsError(RetVal);
fStream = new StreamWriter(@"C:\Users\Public\Documents\DataFile1608G.asc");
CreateFileHeaders(chArray); //writes basic info to the beginning of the file
int Count = 0;
int Index = 0;
short daqStatus;
double[] theArray = new double[BUFFERSIZE];
System.ConsoleKeyInfo cki = new System.ConsoleKeyInfo();
//Loop until key press
do{
RetVal = daq.GetStatus( out daqStatus, out Count, out Index, FunctionType.AiFunction );
if ((Index >= HALFBUFFSIZE) & ReadLower) //check for 50% more data
{
//get lower half of buffer - ScaledWinBufToArray returns engineering units
RetVal = MccService.ScaledWinBufToArray(buffer, theArray, 0, HALFBUFFSIZE);
IsError(RetVal);
DisplayData(theArray, HALFBUFFSIZE/CHANCOUNT);
ReadLower = false; //flag that controls the next read
}
else if ((Index < HALFBUFFSIZE) & !ReadLower)
{
//get the upper half - ScaledWinBufToArray returns engineering units
RetVal = MccService.ScaledWinBufToArray(buffer, theArray, HALFBUFFSIZE, HALFBUFFSIZE);
IsError(RetVal);
DisplayData(theArray, HALFBUFFSIZE/CHANCOUNT);
ReadLower = true;//flag that controls the next read
}
} while (!Console.KeyAvailable);
cki = Console.ReadKey();
//flush any buffered data out to disk
fStream.Close();
//stop the acquisition
RetVal = daq.StopBackground(FunctionType.AiFunction);
//free up memory
MccService.WinBufFreeEx(buffer);
WaitForKey();
}
}