using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using AIOUSBNet; // the namespace exposes the AIOUSB Class interface // You must also add a reference to the AIOUSBnet.dll in the project settings namespace Sample1 { public partial class Form1 : Form { // One and only Device Index: public UInt32 DeviceIndex; bool bCal = true; // Num channels we will be using: public const int numAnalogInputs = 16; // Array of controls for GUI updates: public ProgressBar[] VoltProgress = new ProgressBar[numAnalogInputs]; public Label[] VoltLabel = new Label[numAnalogInputs]; public double[] ChannelVolts = new double[numAnalogInputs]; // buffer data for display // Struct for AI Board Config: public struct TUSBAI1616Config { public TUSBAI1616Config(int size) { ChannelRange = new byte[size]; CalibMode = 0; TrigMode = 0; StartStopCH = 0; Oversample = 0; } public byte[] ChannelRange; public byte CalibMode; public byte TrigMode; public byte StartStopCH; public byte Oversample; } // Struct for Configuration must pass number of channels for array size: public TUSBAI1616Config Config = new TUSBAI1616Config(numAnalogInputs); // Required for ADC_SetConfig() dll calls: UInt32 ConfigBufSize = numAnalogInputs + 4; // sizeof(Config); // could be better // Temp array for ADC_SetConfig() dll calls: public byte[] configArray = new byte[20]; // Array for AD Data the counts are unsigned 16 bit numbers (ushort) public UInt16[] ADData = new UInt16[128 * 1024]; //8K scans of 16 channels, or 16K scans of 8 differential channels. public bool bGoing; public UInt32 KnownBytesLeft; public int NextSample, NextChannel; // Interval Timer for data acquire and GUI update: // (Note: A Windows Forms timer designed for single threaded environments not a System Timer 55 ms min res) static System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer(); public Form1() { InitializeComponent(); // Arrays of the controls: VoltProgress[0] = progressBar1; VoltProgress[1] = progressBar2; VoltProgress[2] = progressBar3; VoltProgress[3] = progressBar4; VoltProgress[4] = progressBar5; VoltProgress[5] = progressBar6; VoltProgress[6] = progressBar7; VoltProgress[7] = progressBar8; VoltProgress[8] = progressBar9; VoltProgress[9] = progressBar10; VoltProgress[10] = progressBar11; VoltProgress[11] = progressBar12; VoltProgress[12] = progressBar13; VoltProgress[13] = progressBar14; VoltProgress[14] = progressBar15; VoltProgress[15] = progressBar16; VoltLabel[0] = lblVolt0; VoltLabel[1] = lblVolt1; VoltLabel[2] = lblVolt2; VoltLabel[3] = lblVolt3; VoltLabel[4] = lblVolt4; VoltLabel[5] = lblVolt5; VoltLabel[6] = lblVolt6; VoltLabel[7] = lblVolt7; VoltLabel[8] = lblVolt8; VoltLabel[9] = lblVolt9; VoltLabel[10] = lblVolt10; VoltLabel[11] = lblVolt11; VoltLabel[12] = lblVolt12; VoltLabel[13] = lblVolt13; VoltLabel[14] = lblVolt14; VoltLabel[15] = lblVolt15; } private void Form1_Load(object sender, EventArgs e) { // Called before Form is displayed Initialize resources: // Initialize default Device Only: DeviceIndex = AIOUSB.diOnly; // Device data: UInt32 Status; UInt32 PID = 0; UInt32 NameSize = 256; string strName = "name"; UInt32 DIOBytes = 0; UInt32 Counters = 0; UInt64 SerNum; UInt32 ERROR_SUCCESS = 0; bool deviceIndexValid = false; // Get The Device Information test for valid device found: Status = AIOUSB.QueryDeviceInfo(DeviceIndex, out PID, out NameSize, out strName, out DIOBytes, out Counters); if ( (Status == ERROR_SUCCESS) && ( (PID >= 0x8040) && (PID <= 0x815D) ) ) // AIO and AI { deviceIndexValid = true; } else { // If Only device is not valid then Launch connect device dialog box: // New parent aware subform: FormDetect DetectSubForm = new FormDetect(this); DetectSubForm.ShowDialog(); Status = AIOUSB.QueryDeviceInfo(DeviceIndex, out PID, out NameSize, out strName, out DIOBytes, out Counters); if (Status == ERROR_SUCCESS && PID >= 0x8040 && PID <= 0x815D) deviceIndexValid = true; } if (!deviceIndexValid) { // No valid device found should exit // this.Close(); } // Check device status: Status = AIOUSB.ClearDevices(); // Cleans up any orphaned indexes Status = AIOUSB.GetDevices(); Status = AIOUSB.GetDeviceSerialNumber(DeviceIndex, out SerNum); if (AIOUSB.ADC_QueryCal(DeviceIndex) != ERROR_SUCCESS) { //this board doesn't have calibration bCal = false; lblCal.Visible = false; comboBoxCalibration.Visible = false; } UInt32 count; //Stop the counter, in case it was running. double Hz = 0; UInt32 BlockIndex = 0; AIOUSB.CTR_StartOutputFreq(DeviceIndex, BlockIndex, out Hz); comboBoxRange.SelectedIndex = 0; // Init all config values: Config.CalibMode = 0; //Take actual data, not internal calibration sources. Config.TrigMode = 5; //Scan selected channels each counter rising edge. Config.StartStopCH = 0xF0; //Scan selected channels each counter rising edge. Config.Oversample = 0;//No oversample. //ConfigBufSize = 20; // Note This is set once above NextChannel = 0; for (int i = 0; i < numAnalogInputs; i++) { Config.ChannelRange[i] = 0; } // Temp copy struct to array for dll call: for (int i = 0; i < numAnalogInputs; i++) { configArray[i] = Config.ChannelRange[i]; } configArray[16] = Config.CalibMode; configArray[17] = Config.TrigMode; configArray[18] = Config.StartStopCH; configArray[19] = Config.Oversample; AIOUSB.ADC_SetConfig(DeviceIndex, configArray, out ConfigBufSize); for (count = 0; count < 16; count++) { //VoltProgress[count].SetRange32(-10000, 10000); VoltProgress[count].Value = 0; // SetPos(0); } comboBoxCalibration.SelectedItem = ":AUTO:"; // Add the event and the event handler for the method that will // process the timer event to the timer: myTimer.Tick += new EventHandler(TimerEventProcessor); // Set the timer interval in miliseconds and start 55ms min resolution: myTimer.Interval = 100; myTimer.Start(); // dont start until setup } private void btnDevice_Click_1(object sender, EventArgs e) { // Need to stop the timer change board and GUI: myTimer.Stop(); // Launch connect device dialog box // Switch between multiple devices or reconnect // New parent aware subform: FormDetect DetectSubForm = new FormDetect(this); DetectSubForm.ShowDialog(); // Restart timer thread: myTimer.Enabled = true; } private void comboBoxRange_SelectedIndexChanged(object sender, EventArgs e) { int i; byte RangeCode; //The ranges in the combo box are listed in order, so that the index is equal //to the range code. RangeCode = (byte)comboBoxRange.SelectedIndex; if (checkBoxDIFF.Checked) RangeCode |= 0x08; for (i = 0; i < numAnalogInputs; i++) Config.ChannelRange[i] = RangeCode; } private void checkBoxDIFF_CheckedChanged(object sender, EventArgs e) { comboBoxRange_SelectedIndexChanged(sender, e); } private void btnExecute_Click(object sender, EventArgs e) { // Need to stop the timer change board and GUI: myTimer.Stop(); // Variables: UInt32 Status = 0; int i; byte RangeCode; // Test and set calibration: if (bCal) { Status = AIOUSB.ADC_SetCal(DeviceIndex, comboBoxCalibration.SelectedItem.ToString()); if (Status != 0) //ERROR_SUCCESS ) { comboBoxRange.Enabled = true; btnExecute.Enabled = true; bGoing = false; myTimer.Stop(); MessageBox.Show("Calibration Error!"); return; } } //Stop the counter. double dHz = 0; AIOUSB.CTR_StartOutputFreq(DeviceIndex, 0, out dHz); // Set Range: //The ranges in the combo box are listed in order, so that the index is equal to the range code. RangeCode = (byte)comboBoxRange.SelectedIndex; if (checkBoxDIFF.Checked) RangeCode |= 0x08; for (i = 0; i < numAnalogInputs; i++) Config.ChannelRange[i] = RangeCode; // Set stop channel: if (checkBoxDIFF.Checked) Config.StartStopCH = 0x70; //Select all 8 differential channels, from 0 to 7. else Config.StartStopCH = 0xF0; //Select all 16 channels, from 0 to 15. // set Config: // Temp copy struct to array for Config dll call: for (i = 0; i < numAnalogInputs; i++) { configArray[i] = Config.ChannelRange[i]; } configArray[16] = Config.CalibMode; configArray[17] = Config.TrigMode; configArray[18] = Config.StartStopCH; configArray[19] = Config.Oversample; // ConfigBufSize = sizeof(Config); AIOUSB.ADC_SetConfig(DeviceIndex, configArray, out ConfigBufSize); // Set Channel Displays if (checkBoxDIFF.Checked) { for (i = 8; i <= 15; i++) { //VoltProgress[i].Enabled = false; VoltProgress[i].Hide(); VoltLabel[i].Hide(); } } else { for (i = 8; i <= 15; i++) { VoltProgress[i].Show(); VoltLabel[i].Show(); } } //Since we've put it in scan mode above, this is 1kHz per channel, or 16kHz total. double Hz = 1000; AIOUSB.CTR_StartOutputFreq(DeviceIndex, 0, out Hz); //Set the streaming block size fairly small, to make the UI more responsive. //The default (large) streaming block size is necessary for a slow computer, //or when acquiring close to the max for a fast board. UInt32 BlockSize = 512; AIOUSB.AIOUSB_SetStreamingBlockSize(DeviceIndex, BlockSize); // Setup Bulk Acquire //KnownBytesLeft = (UInt32)ADData.Length * 2; // buffer size num bytes 2 bytes per UInt16 ushort KnownBytesLeft = 128 * 1024 * 2; // buffer size num bytes 2 bytes per UInt16 ushort Status = AIOUSB.ADC_BulkAcquire(DeviceIndex, KnownBytesLeft, ADData); // start acquiring data NextSample = 0; NextChannel = 0; // Set Gui enable states: btnExecute.Enabled = false; checkBoxDIFF.Enabled = false; comboBoxCalibration.Enabled = false; comboBoxRange.Enabled = false; //Flag bGoing = true; // Restart timer thread: myTimer.Enabled = true; } private void TimerEventProcessor(Object myObject, EventArgs myEventArgs) { // This is the method that runs when the timer event is raised: myTimer.Stop(); UpdateGUIState(); if(!bGoing && checkBoxLoop.Checked) { btnExecute_Click(myObject, myEventArgs); } myTimer.Enabled = true; } private void UpdateGUIState() { // Read data and set GUI state: UInt32 Status; UInt32 BytesLeft; double Volts; byte RangeCode; ushort Counts; BytesLeft = 0; Status = AIOUSB.ADC_BulkPoll(DeviceIndex, out BytesLeft); // see how many bytes are left to be acquiered if (BytesLeft >= KnownBytesLeft) // Test to see if we got no bytes yet happens first time through { myTimer.Enabled = true; // keep timer going return; // bail out of this timer loop } if (BytesLeft > 0 ) // Test to see if we got some bytes yet { myTimer.Enabled = true; // keep timer going and continue } //If we get here, some data has been taken. if (BytesLeft == 0) // should have all bytes requested if 0 so done for this run { //Stop the counter. double dHz = 0; Status = AIOUSB.CTR_StartOutputFreq(DeviceIndex, 0, out dHz); // Set Gui enable states: btnExecute.Enabled = true; checkBoxDIFF.Enabled = true; comboBoxCalibration.Enabled = true; comboBoxRange.Enabled = true; bGoing = false; myTimer.Stop(); //return; } //We're going to use the range code to convert to volts. RangeCode = (byte)comboBoxRange.SelectedIndex; do { Counts = ADData[NextSample]; Volts = (double)(Counts) / (double)(0xFFFF); //"Volts" now holds a value from 0 to 1. if ((RangeCode & 0x01) != 0) //Bit 0(mask 01 hex) indicates bipolar. { Volts = Volts * 2 - 1; //"Volts" now holds a value from -1 to +1. } if ((RangeCode & 0x02) == 0) //Bit 1(mask 02 hex) indicates x2 gain. { Volts *= 2; } if ((RangeCode & 0x04) == 0) //Bit 2(mask 04 hex) indicates x5 gain. { Volts *= 5; } //"Volts" now holds volts. //Because the display can be slow, we just display the last reading for each channel. ChannelVolts[NextChannel] = Volts; KnownBytesLeft -= 2; NextSample++; NextChannel++; if (NextChannel > 15) NextChannel = 0; } while (KnownBytesLeft != BytesLeft); // both decreaseing over time for (int i = 0; i <= 15; i++) { // Update GUI ooutside the previous loop: string strVolt; string strFormat = "Ch {0,2:D2}: {1,8:F4} V"; strVolt = String.Format(strFormat, i, ChannelVolts[i]); VoltLabel[i].Text = strVolt; VoltProgress[i].Value = 10000 + (int)(1000 * ChannelVolts[i]); } } } }