CSharp (C#) Streaming Ain/Aout Function Generator
The example below demonstrates how to stream analog data out the analog output pins while at the same time reading it back in. To keep the program simple, an array is created that contains a waveform and this waveform is continuously written to the output buffer without change. In a more sophisticated program the array data would be changing on each write. To use this program you must have a device that supports hardware analog output scanning at rates of at lest 50,000 per second. At the beginning of the program where the constants are defined there is a section of tested devices. Uncomment the device you have and comment the current device which is the USB-1408FS-Plus.
The example program writes the data to a text file that is compatible with the DASYLab ReadFile module and Excel. To visually verify the data, I found the easiest method was to read the file in with DASYLab and display it in a strip chart. Connect the outputs to the inputs using wire and run the program to generate the data file. Run the attached DASYLab 13.0 test worksheet to see the data. The worksheet will not only display data but will also measure the frequency. If you change the example program's block size and sample rate you must also change it in the DASYLab worksheet in the Read module ASCII Options. If you don't have DASYLab there is 30 day evaluation available on the MCC web site.
The program uses the MccDaq.dll .net assembly API. To be able to access this API, in your project add a reference to it. Adding the reference is usually accomplished by right clicking the Project [under the Project Explorer] and selecting Add Reference. On the .NET page find and select the MccDaq component. My complete Visual Studio 9.0 project is attached to this article further down.
Disclaimer:
The attached Code or Example is provided As Is. It has not been tested or validated as a product, for use in a deployed application or system, or for use in hazardous environments. You assume all risks for use of the Code or Example.
using System; using MccDaq; using System.IO; using System.Linq; namespace Ain_Aout_Continous { class Program { public const int iBLOCKSIZE = 4096; //input block size public const int oBLOCKSIZE = 2048; //output block size public const int iFREQ = 5000; //input sample rate public const int oFREQ = 50000; //output update rate public const int FIRSTCHANNEL = 0; public const int LASTCHANNEL = 1; public const int iCHANCOUNT = LASTCHANNEL - FIRSTCHANNEL +1; //input channel count public const int oCHANCOUNT = LASTCHANNEL - FIRSTCHANNEL + 1; //output channel count public const int iBUFFERSIZE = iBLOCKSIZE * iCHANCOUNT; //input buffer size public const int oBUFFERSIZE = oBLOCKSIZE * oCHANCOUNT; //output buffer size public const int iHALFBUFFSIZE = iBUFFERSIZE / 2; public const int oHALFBUFFSIZE = oBUFFERSIZE / 2; //The following devices have been tried...Uncomment yours //public const string DEVICE = "PCI-DAS6052"; //public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BurstMode | ScanOptions.BlockIo; //public const string DEVICE = "USB-1608GX-2AO"; //public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BurstMode | ScanOptions.BlockIo; //public const string DEVICE = "USB-1616HS-4"; //public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BlockIo; //public const string DEVICE = "USB-1616HS-2"; //public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BlockIo; //public const string DEVICE = "USB-2527"; //public const int RESOLUTION = 65535; public const ScanOptions ExtraOpts = ScanOptions.BlockIo; //public const string DEVICE = "USB-1208HS-4AO"; //public const int RESOLUTION = 4096; public const ScanOptions ExtraOpts = ScanOptions.BurstMode|ScanOptions.BlockIo; public const string DEVICE = "USB-1408FS-Plus"; public const int RESOLUTION = 4096; public const ScanOptions ExtraOpts = ScanOptions.BlockIo; //public const string DEVICE = "USB-1208FS-Plus"; //public const int RESOLUTION = 4096; public const ScanOptions ExtraOpts = ScanOptions.BlockIo; public static StreamWriter fStream; public static IntPtr OutBuf; public static IntPtr buffer; public static bool inLower; public static bool outLower; public static ushort[] inArray; public static ushort[] outArray; public static MccBoard daq; public static MccDaq.ErrorInfo RetVal; // ********************************************************************************************************* // ********************************************************************************************************* // ********************************************************************************************************* static void Main(string[] args) { MccDaq.ErrorInfo RetVal; int BoardNum = 0; int iRate = iFREQ; //input rate int oRate = oFREQ; //output rate inLower = true; outLower = true; Console.WriteLine("Connecting to {0}",DEVICE); BoardNum = GetBoardNum(DEVICE); if (BoardNum == -1) { Console.WriteLine("No {0} detected!", DEVICE); WaitForKey(); return; } else { ///////// BEGIN PROGRAM /////////// daq = new MccDaq.MccBoard(BoardNum); //create the driver buffers OutBuf = MccService.WinBufAllocEx(oBUFFERSIZE); buffer = MccService.ScaledWinBufAllocEx(iBUFFERSIZE); Console.WriteLine("{0} Connected",DEVICE); if ((OutBuf == IntPtr.Zero) || (buffer == IntPtr.Zero)) { Console.WriteLine("Insufficient Memory"); WaitForKey(); return; } //create the user output buffer. outArray = new ushort[oBUFFERSIZE]; //create the waveforms for(int i=0;i<oCHANCOUNT;i++) GetWaveForm(3, i, outArray); //start with sine wave //write the user data to the driver buffer MccService.WinArrayToBuf(outArray, OutBuf, 0, oBUFFERSIZE); //start the waveforms RetVal = daq.AOutScan( FIRSTCHANNEL, LASTCHANNEL, oBUFFERSIZE, ref oRate, Range.Bip10Volts, OutBuf, ScanOptions.Background | ScanOptions.Continuous ); if (IsError("AOutScan",RetVal) == 1) return; short[] chArray = new short[iCHANCOUNT]; //configuration array for channel numbers for(short i=0; i<iCHANCOUNT;i++) chArray[0] = i; fStream = new StreamWriter(@"C:\Users\Public\Documents\DataFile.asc"); CreateFileHeaders(chArray); //writes basic info to the beginning of the file System.ConsoleKeyInfo cki; WaitForKey(); //begin analog input RetVal = daq.AInScan(FIRSTCHANNEL, LASTCHANNEL, iBUFFERSIZE, ref iRate, Range.Bip10Volts, buffer, ScanOptions.Background | ScanOptions.Continuous | ExtraOpts ); if (IsError("AInScan", RetVal) == 1) return; bool exit = false; //do loop to switch waveforms and read/write data do { if (Console.KeyAvailable) { cki = Console.ReadKey(true); switch (cki.Key) { case ConsoleKey.D1: case ConsoleKey.NumPad1: if ((cki.Modifiers & ConsoleModifiers.Alt) != 0) GetWaveForm(1, 1, outArray); else GetWaveForm(1,0,outArray); break; case ConsoleKey.D2: case ConsoleKey.NumPad2: if ((cki.Modifiers & ConsoleModifiers.Alt) != 0) GetWaveForm(2, 1, outArray); else GetWaveForm(2, 0, outArray); break; case ConsoleKey.D3: case ConsoleKey.NumPad3: if ((cki.Modifiers & ConsoleModifiers.Alt) != 0) GetWaveForm(3, 1, outArray); else GetWaveForm(3, 0, outArray); break; case ConsoleKey.D4: case ConsoleKey.NumPad4: if ((cki.Modifiers & ConsoleModifiers.Alt) != 0) GetWaveForm(4, 1, outArray); else GetWaveForm(4, 0, outArray); break; case ConsoleKey.D5: case ConsoleKey.NumPad5: if ((cki.Modifiers & ConsoleModifiers.Alt) != 0) GetWaveForm(5, 1, outArray); else GetWaveForm(5, 0, outArray); break; case ConsoleKey.D6: case ConsoleKey.NumPad6: if ((cki.Modifiers & ConsoleModifiers.Alt) != 0) GetWaveForm(6, 1, outArray); else GetWaveForm(6, 0, outArray); break; case ConsoleKey.Spacebar: exit = true; break; } } if(ReadInputBuffer()==1) return; if(WriteOutputBuffer()==1) return; } while (!exit); //flush buffered data out to disk fStream.Flush(); //close file fStream.Close(); //stop the acquisition RetVal = daq.StopBackground(FunctionType.AiFunction); RetVal = daq.StopBackground(FunctionType.AoFunction); //free up memory MccService.WinBufFreeEx(buffer); MccService.WinBufFreeEx(OutBuf); return; } }
Attachments
ReadDataFile.DSB
AIn_Aout_Continous_Waveform_Generator.zip