zoukankan      html  css  js  c++  java
  • 实现与研华PCI采集卡通讯

    如果使用过PCI采集卡的盆友应该对“研华”这个品牌不陌生,可以说研华还是很强大的。最近因为工作需要,使用一块研华的PCI1714UL型号的采集卡,去高速采集电压信号,学习了几天后分享给各位。

    采集卡

    首先介绍一下这块采集卡。品牌:研华Advantech,型号:PCI1714UL,基本参数:4通道,12位精度,采样频率:10MS/s,采样:8192/通道,可采集电压范围有:±5、±2.5、±1、±0.5,每个范围对应的绝对精度不同,所以视情况来决定需要什么样的采样范围。支持PCI总线控制DMA数据传输。

    工作方式

    这块采集卡有两种工作模式:BufferedAI、InstantAI。

    BufferedAI:使用PC的一个存储块,可以实现总线控制数据采集,不需要占用CPU;

    InstantAI:瞬时值,采样率相对没那么高,适合一些对数据要求不算太高的场合。

    资料下载

    官网   资料

    驱动安装

    研华提供了一款DAQNavi软件(见“资料下载”去官网下载),有一个Navigator,可以直接打开可以看到所有支持的卡,选中你需要的卡右键就可以安装驱动了。并且这款软件也提供数据采集展示。

     

    软件二次开发:接口函数---Automation.BDaq4(见“资料下载”去官网下载)

    一、使用研华提供的控件进行二次开发

    研华提供了相关控件:

     WaveformAiCtrl用于BufferedAI读取,InstantAiCtr用于InstantAI读取。 

    二、自己从底层开发

    瞬时电压读取比较简单,直接创建InstantAiCtrl,传递一个设备名称:instantAiCtrl.SelectedDevice = new DeviceInformation(deviceCode);初始化:instantAiCtrl.Initialized,就可以开始读取数据了:instantAiCtrl.Read(channelIndex,out data[channelIndex])。

    BufferedAI代码量多一点:首先需要创建一个线程,用于将采集卡数据读取到内存中,再开一个线程专门见内存中的数据往本地写入(因为数据量太大不能一下处理),最后开一个线程用于将本地的数据读取出来,进行数据处理、分析、展示。

    代码展示

    1. 创建一个AnalogCard父类,利于再添加采集卡型号的时候进行扩展

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.IO;
    
    namespace AdvantechPCIDemo
    {
        /// <summary>
        /// 数据读取策略:
        /// 采集卡读取速度极快(10MS/s、30MS/s),因此现将采集卡数据保存至指定文件,多线程同步将数据读取
        /// 再对数据进行处理、显示
        /// </summary>
        public class AnalogCard
        {
            protected int channelCount;//通道数
            protected uint readLength;//数据一次读取长度
            protected uint readCount;
    
            protected ManualResetEventSlim readEvent = new ManualResetEventSlim(false);
            protected ManualResetEventSlim writeEvent = new ManualResetEventSlim(false);
            protected ManualResetEventSlim readADEvent = new ManualResetEventSlim(false);
    
            protected Task writeTask;//任务:将内存Queue数据写入指定文件
            protected Task readTask;//任务:将指定文件数据读入内存Queue
            protected Task readADTask;//任务:将采集卡数据读取进内存Queue
    
            protected Queue<ushort[]> dataQueue = new Queue<ushort[]>(1000);//先进先出队列,定义初始长度,不足自动增长
            protected CancellationTokenSource source = new CancellationTokenSource();//线程是否取消
            protected string fileName = string.Format("Data\Data-{0}.txt", DateTime.Now.ToString("yy-MM-dd-HH-mm-ss"));//定义数据保存与读取文件名
            protected Action<ushort[][]> ChannelDataAction { get; set; }
    
            public AnalogCard()
            {
                //将内存Queue数据写入指定文件
                writeTask = Task.Factory.StartNew(() =>
                {
                    using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read))
                    {
                        while (true)
                        {
                            writeEvent.Wait(source.Token);//等待开启写入任务
                            if (source.IsCancellationRequested) return;
    
                            if (dataQueue.Count == 0) continue; ;
                            ushort[] us = dataQueue.Dequeue();//将第一个数据去除并移除
                            if (dataQueue.Count > 1000) { dataQueue.Clear(); }
    
                            byte[] bt = new byte[readLength * 2];
    
                            for (int i = 0, j = 0; i < us.Length; i++)
                            {
                                ushort temp = us[i];
                                bt[j++] = (byte)(temp >> 8);//取高八位
                                bt[j++] = (byte)temp;//取低八位
                            }
                            fs.Write(bt, 0, bt.Length);
                        }
                    }
                }, source.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
    
                Thread.Sleep(500);
    
                //将指定文件的数据流写入内存队列Queue
                readTask = Task.Factory.StartNew(() =>
                {
                    using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Write))
                    {
                        int currentLength = 0;
                        byte[] bt=null;
                        while (true)
                        {
                            readEvent.Wait(source.Token);//等待开启读取
                            if (source.IsCancellationRequested) break;//任务被取消
    
                            if (bt == null)
                            {
                                bt = new byte[readLength * 2];//byte数组为需要读取数据的两倍:两个字节转换为一个字符
                            }
                            
                            if (currentLength < bt.Length)
                            {
                                currentLength = fs.Read(bt, currentLength, bt.Length - currentLength);
                            }
                            else
                            {
                                currentLength = 0;
    
                                if (ChannelDataAction == null)
                                    throw new Exception("无通道数据接收方法!");
    
                                ushort[][] us;
                                if (!GetChannelData(bt, out us))
                                    throw new Exception("");
    
                                ChannelDataAction(us);//将读取到的数据向上传递
                            }
                        }
                    }
                });
            }
    
            protected virtual void StartWriteReadTxt()
            {
                writeEvent.Set();
                readEvent.Set();
                readADEvent.Set();
    
                dataQueue.Clear();
            }
    
            protected virtual void StopWriteReadTxt()
            {
                writeEvent.Reset();
                readEvent.Reset();
                readADEvent.Reset();
            }
    
            public virtual void CancelWriteReadTxt()
            {
                source.Cancel();
            }
    
            /// <summary>
            /// 将读取的数据分到各通道
            /// 数据顺序:temp[0]+temp[1]=ch1va1;temp[2]+temp[3]=ch2va1...
            /// </summary>
            /// <param name="temp"></param>
            /// <returns></returns>
            private bool GetChannelData(byte[] temp, out ushort[][] us)
            {
                us = new ushort[channelCount][];
    
                int index = 0;
                for (int i = 0; i < temp.Length; i+=2*channelCount)
                {
                    
                    for (int j = 0; j < channelCount; j++)
                    {
                        if (us[j] == null)
                        {
                            us[j] = new ushort[readLength / channelCount];
                        }
    
                        us[j][index] = (ushort)((temp[i + j * 2] << 8) + temp[i + j * 2 + 1]);
                    }
                    index++;
                }
                return true;
            }
    
    
        }
    }
    View Code

    在父类设置卡的一些基本字段,并创建了两个线程:writeTask、readTask,分别是将内存Queue中数据写入本地txt,将本地txt文件读取进内存Queue。用ManualResetEventSlim对象现将该线程堵塞,等待开启。

    2. 创建一个PCI1714UL子类

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Automation.BDaq;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace AdvantechPCIDemo
    {
        public class PCI1714UL:AnalogCard
        {
            private string deviceCode = "";
            private const int bufferLength = 2048;
            private int channelMax=0;
            private BufferedAiCtrl bufferedCtrl = null;
            private InstantAiCtrl instantAiCtrl = null;
            private ManualResetEventSlim readADInternal = new ManualResetEventSlim(false);//有数据再开启
            private ushort[] data;
            private object locker = new object();
    
            public PCI1714UL(string deviceCode):base()
            {
                this.deviceCode = deviceCode;
            }
    
            public void StartBufferedAI(int channelCount,Action<ushort[][]> channelDataAction)
            {
                bufferedCtrl = new BufferedAiCtrl();
                bufferedCtrl.SelectedDevice = new DeviceInformation(deviceCode);
                
                this.channelCount = channelCount;
                this.readLength = (uint)(bufferLength * channelCount);
                this.readCount = bufferLength;
                this.data = new ushort[readLength];
                this.ChannelDataAction = channelDataAction;
    
                ScanChannel channel = bufferedCtrl.ScanChannel;
                channel.ChannelCount = channelCount;
                channel.ChannelStart = 0;
                channel.IntervalCount = bufferLength; // each channel 触发DataReady事件的采样个数,即到了指定个数之后便触发DataReady事件,可以跟windows的定时器控件类似
                channel.Samples = bufferLength;//采样的个数。例如,我设定采样个数为1024个,Rate是1024/s,那么也就是说采样经过了1秒   
    
                bufferedCtrl.DataReady += new EventHandler<BfdAiEventArgs>(BufferedReady);
                this.channelMax = bufferedCtrl.Features.ChannelCountMax;
                bufferedCtrl.Streaming = false;
                ErrorCode ret = bufferedCtrl.Prepare();//初始化所选设备,准备开始
                if (ret != ErrorCode.Success) throw new InvalidOperationException("Failed to prepare AD!");
    
                //将采集卡数据读取到Queue
                readADTask = Task.Factory.StartNew(() =>
                {
                    while (true)
                    {
                        readADEvent.Wait(source.Token);//等待开启
                        if (source.IsCancellationRequested) return;
    
                        if (!StartDevice()) return;//查看设备是否已运行
                        readADInternal.Wait(source.Token);//先等待,有数据传递触发BufferedReady后再开启
    
                        if (dataQueue.Count > 1000) dataQueue.Clear();
    
                        dataQueue.Enqueue(data);
                    }
                }, source.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
    
                StartWriteReadTxt();
            }
    
            public void StopBufferedAI()
            {
                bufferedCtrl.Stop();
                //bufferedCtrl.Dispose();
                StopWriteReadTxt();
            }
    
            public double[] StartInstantAI()
            {
                instantAiCtrl = new InstantAiCtrl();
                instantAiCtrl.SelectedDevice = new DeviceInformation(deviceCode);
                if (!instantAiCtrl.Initialized)
                {
                    throw new Exception("No device be selected or device open failed!");
                }
                double[] data=new double[4] ;
                ErrorCode er0 = instantAiCtrl.Read(0,out data[0]);
                ErrorCode er1 = instantAiCtrl.Read(1, out data[1]);
                ErrorCode er2 = instantAiCtrl.Read(2, out data[2]);
                ErrorCode er3 = instantAiCtrl.Read(3, out data[3]);
    
                return data;
            }
    
            public void StopInstantAI()
            {
                if (instantAiCtrl.State == ControlState.Running)
                {
                    instantAiCtrl.Dispose(); ;
                }
            }
    
            private bool StartDevice()
            {
                ErrorCode ret;
                if (bufferedCtrl.State != ControlState.Running)
                {
                    readADInternal.Reset();
    
                    ret = bufferedCtrl.Start();
                    //Thread.Sleep(500);
                    if (ret != ErrorCode.Success)
                    {
                        //log.ErrorFormat("Failed to start PCI1714 first time! ErrorCode is {0}.", ret);
    
                        ret = bufferedCtrl.Stop();
                        if (ret != ErrorCode.Success)
                        {
                            //log.ErrorFormat("Failed to stop PCI1714! ErrorCode is {0}.", ret);
                        }
    
                        Thread.Sleep(500);
    
                        ret = bufferedCtrl.Start();
                        if (ret != ErrorCode.Success)
                        {
                            //log.ErrorFormat("Failed to start PCI1714 second time! ErrorCode is {0}.", ret);
                            return false;
                        }
                    }
    
                }
                return true;
            }
    
            public void BufferedReady(object e,BfdAiEventArgs b)
            {
                short[] data = new short[b.Count];
                ErrorCode ret = bufferedCtrl.GetData(b.Count, data);//data存放的是从采集卡得到的数据
                if (ret != ErrorCode.Success)
                {                
                    lock (locker)
                    {
                        this.data = null;
                        readADInternal.Set();
                    }
                }
    
                lock (locker)
                {
                    this.data = data.Select(o => (ushort)o).ToArray();
                    readADInternal.Set();
                }
            }
        }
    }
    View Code

    在这个类里,先继承上面的AnalogCard,再设置一些板卡信息。并提供两种方式的数据读取:StartBufferedAI,StartInstantAI。

    主要说明StartBufferedAI:

    在这里需要再创建一个线程readADTask,用于将采集卡数据读取进内存Queue,同样现将该线程堵塞等待开启。定义一个BufferedReady事件,并进行绑定:bufferedCtrl.DataReady += new EventHandler<BfdAiEventArgs>(BufferedReady);这样采集卡有数据后会自动触发该事件,在该事件中将采集卡数据读取出来。

    3. 桌面数据显示

    参考研华的数据采集样式,根据数据实时画出数据曲线图。

    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 System.Windows.Forms.DataVisualization.Charting;
    using Automation.BDaq;
    
    namespace AdvantechPCIDemo
    {
        public partial class FrmMain : Form
        {
            private ushort[][] us;//接受PCI发生来的数据
            private string deviceName = "PCI-1714UL,BID#13";
            public FrmMain()
            {
                InitializeComponent();
    
                OperateCustomBtn(false);
    
                DrawGrid(this.pbBuffCh1);
                DrawGrid(this.pbBuffCh2);
                DrawGrid(this.pbBuffCh3);
                DrawGrid(this.pbBuffCh4);
    
                DrawGrid(this.pbIstantCh1);
                DrawGrid(this.pbIstantCh2);
                DrawGrid(this.pbIstantCh3);
                DrawGrid(this.pbIstantCh4);
            }
    
            #region 数据列表定义
            private List<Point[]> pointFromBuffAI = new List<Point[]>();
            private List<double[]> dataFromBuffAI = new List<double[]>();
    
            private List<Point[]> pointFromInstantAI = new List<Point[]>();
            private List<double[]> dataFromInstantAI = new List<double[]>();
            #endregion
    
            #region 画网格和曲线
            /// <summary>
            /// 画网格
            /// </summary>
            /// <param name="pb"></param>
            private void DrawGrid(PictureBox pb)
            {
                int width = pb.Width, height = pb.Height;
                int cellWidth = height / 4;
                Color color = Color.Green;//绿色线条
    
                Bitmap bp = new Bitmap(width, height);
                Graphics objG = Graphics.FromImage(bp);
                objG.FillRectangle(new SolidBrush(Color.Black), 0, 0, width, height);//黑色背景
    
                //网格列
                for (int i = 0; i < width; i += cellWidth)
                {
                    objG.DrawLine(new Pen(new SolidBrush(color)), i + cellWidth, 0, i + cellWidth, height);
                }
    
                //网格行
                for (int i = 0; i < width; i += cellWidth)
                {
                    objG.DrawLine(new Pen(new SolidBrush(color)), 0, i + cellWidth, width, i + cellWidth);
                }
    
                pb.Image = bp;
            }
    
    
            /// <summary>
            /// 画动态曲线
            /// </summary>
            /// <param name="channelIndex"></param>
            /// <param name="pb"></param>
            private void DrawBufferedAICurve()
            {
                for (int channel = 0; channel < 4; channel++)
                {
                    PictureBox pbTemp = null;
                    switch (channel)
                    {
                        case 0:
                            pbTemp = this.pbBuffCh1; break;
                        case 1:
                            pbTemp = this.pbBuffCh2; break;
                        case 2:
                            pbTemp = this.pbBuffCh3; break;
                        case 3:
                            pbTemp = this.pbBuffCh4; break;
                    }
    
                    int width = pbTemp.Width, height = pbTemp.Height;
    
                    if (pointFromBuffAI.Count == 0)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            pointFromBuffAI.Add(new Point[width]);
                        }
                    }
                    lock (locker)
                    {
    
    
                        while (dataFromBuffAI.Count >= width + 2)
                        {
                            dataFromBuffAI.RemoveAt(0);
                        }
                    }
    
                    int count = dataFromBuffAI.Count;
    
                    if (count != 0)
                    {
                        pointFromBuffAI[channel] = new Point[count];
                    }
    
                    for (int i = 0; i < width + 1; i++)
                    {
                        if (i >= count) break;
    
                        if (dataFromBuffAI[i] == null) continue;
    
                        pointFromBuffAI[channel][i] = new Point(i, (int)(height - ((dataFromBuffAI[i][channel] + 5) * height) / 10));//从负到正                                                                                                                   //prData[channelIndex][i] = new Point(i, (int)(((Math.Abs(showData[i][channelIndex])) * height) / 10));//全负数
                    }
    
                    pbTemp.Refresh();
                }
            }
    
            private void ClearBufferedAICurve()
            {
                Graphics g = Graphics.FromImage(this.pbBuffCh1.Image);
                g.Clear(this.pbBuffCh1.BackColor);
    
                //DrawGrid(this.pbBuffCh1);
                //DrawGrid(this.pbBuffCh2);
                //DrawGrid(this.pbBuffCh3);
                //DrawGrid(this.pbBuffCh4);
            }
    
            private void DrawInstantAICurve()
            {
                for (int channel = 0; channel < 4; channel++)
                {
                    PictureBox pbTemp = null;
                    switch (channel)
                    {
                        case 0:
                            pbTemp = this.pbIstantCh1; break;
                        case 1:
                            pbTemp = this.pbIstantCh2; break;
                        case 2:
                            pbTemp = this.pbIstantCh3; break;
                        case 3:
                            pbTemp = this.pbIstantCh4; break;
                    }
    
                    int width = pbTemp.Width, height = pbTemp.Height;
    
                    if (pointFromInstantAI.Count == 0)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            pointFromInstantAI.Add(new Point[width]);
                        }
                    }
                    lock (locker)
                    {
                        while (dataFromInstantAI.Count >= width + 2)
                        {
                            dataFromInstantAI.RemoveAt(0);
                        }
                    }
    
                    int count = dataFromInstantAI.Count;
    
                    if (count != 0)
                    {
                        pointFromInstantAI[channel] = new Point[count];
                    }
    
                    for (int i = 0; i < width + 1; i++)
                    {
                        if (i >= count) break;
    
                        if (dataFromInstantAI[i] == null) continue;
    
                        pointFromInstantAI[channel][i] = new Point(i, (int)(height - ((dataFromInstantAI[i][channel] + 5) * height) / 10));//从负到正                                                                                                                   //prData[channelIndex][i] = new Point(i, (int)(((Math.Abs(showData[i][channelIndex])) * height) / 10));//全负数
                    }
    
                    pbTemp.Refresh();
                }
            }
    
            private List<int> data = new List<int>();
    
            private Pen redPen = new Pen(Color.Red, 1);
            private void pBCh_Paint(object sender, PaintEventArgs e)
            {
                PictureBox pb = (PictureBox)sender;
                string pbName = pb.Name;
    
                if (pbName.Contains("pbBuffCh"))
                {
                    if (pointFromBuffAI.Count == 4)
                    {
                        switch (pbName)
                        {
                            case "pbBuffCh1":
                                if (pointFromBuffAI[0].Count() < 3) break;//画曲线至少需要三个点
                                e.Graphics.DrawCurve(redPen, pointFromBuffAI[0]); break;
                            case "pbBuffCh2":
                                if (pointFromBuffAI[1].Count() < 3) break;
                                e.Graphics.DrawCurve(redPen, pointFromBuffAI[1]); break;
                            case "pbBuffCh3":
                                if (pointFromBuffAI[2].Count() < 3) break;
                                e.Graphics.DrawCurve(redPen, pointFromBuffAI[2]); break;
                            case "pbBuffCh4":
                                if (pointFromBuffAI[3].Count() < 3) break;
                                e.Graphics.DrawCurve(redPen, pointFromBuffAI[3]); break;
                        }
                    }
                }
                else if (pbName.Contains("pbIstantCh"))
                {
                    if (pointFromInstantAI.Count == 4)
                    {
                        switch (pbName)
                        {
                            case "pbIstantCh1":
                                if (pointFromInstantAI[0].Count() < 3) break;//画曲线至少需要三个点
                                e.Graphics.DrawCurve(redPen, pointFromInstantAI[0]); break;
                            case "pbIstantCh2":
                                if (pointFromInstantAI[1].Count() < 3) break;
                                e.Graphics.DrawCurve(redPen, pointFromInstantAI[1]); break;
                            case "pbIstantCh3":
                                if (pointFromInstantAI[2].Count() < 3) break;
                                e.Graphics.DrawCurve(redPen, pointFromInstantAI[2]); break;
                            case "pbIstantCh4":
                                if (pointFromInstantAI[3].Count() < 3) break;
                                e.Graphics.DrawCurve(redPen, pointFromInstantAI[3]); break;
                        }
                    }
                }
    
    
            }
            #endregion
    
            #region 界面按钮控制
            private void OperateCustomBtn(bool b)
            {
                this.btnCustomBufferedAI.Enabled = b;
                this.btnCustomInstantAI.Enabled = b;
            }
    
            private void OperateCtrBtn(bool b)
            {
                this.btnControlInstantAI.Enabled = b;
                this.btnControlBufferedAI.Enabled = b;
            }
            #endregion
    
            #region 自定义BufferedAI
            PCI1714UL objPCI1714 = null;
            private void btnConfirm_Click(object sender, EventArgs e)
            {
                try
                {
                    objPCI1714 = new PCI1714UL(deviceName);
                    
                    OperateCustomBtn(true);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }         
            }
    
            private void btnStartRead_Click(object sender, EventArgs e)
            {
                try
                {
                    //ClearBufferedAICurve();
    
                    objPCI1714.StartBufferedAI(4, ChannelDataAction);
                    OperateCtrBtn(false);
                    OperateCustomBtn(false);
    
                    bufferedAITimer.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
    
            private void btnStopCusBuffAI_Click(object sender, EventArgs e)
            {
                try
                {                
                    //if (objPCI1714 != null)
                    //{
                    //    objPCI1714.StopBufferedAI();
                    //    //objPCI1714 = null;
                    //    bufferedAITimer.Stop();
    
                    //    OperateCustomBtn(true);
                    //    OperateCtrBtn(true);
                    //}
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
    
            private void ChannelDataAction(ushort[][] us)//动作方法:接受与处理数据,并交给数据展示列表
            {
                this.us = us;
    
                if (us == null || us[0] == null) return;
    
                dataFromBuffAI.Add(this.us.Select(u1 =>
                {
                    return GetVoltage(u1.Select(u => (double)u).ToList().Average());
                }).ToArray());
            }
    
            private double GetVoltage(double data)
            {
                return data * 10 / 4095 - 5.0190516943459;
            }
    
    
            private void customBufferedAI_Tick(object sender, EventArgs e)
            {
                DrawBufferedAICurve();
            }
            #endregion
    
            #region 自定义InstantAI
            private void btnCustomInstantAI_Click(object sender, EventArgs e)
            {
                try
                {
                    customInstantAI.Start();
    
                    OperateCustomBtn(false);
                    OperateCtrBtn(false);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                
            }
    
            private void btnStopCusInstantAI_Click(object sender, EventArgs e)
            {
                try
                {
                    //if (objPCI1714 != null)
                    //{
                    //    objPCI1714.StopInstantAI();
                    //    objPCI1714 = null;
                    //    customInstantAI.Stop();
                    //}
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
    
            private void customInstantAI_Tick(object sender, EventArgs e)
            {
                dataFromInstantAI.Add(objPCI1714.StartInstantAI());
    
                DrawInstantAICurve();
            }
            #endregion
    
            #region 控件BufferedAI
            //private double[] d;
            private void btnControlBufferedAI_Click(object sender, EventArgs e)
            {
                try
                {
                    waveformAiCtrl1.SelectedDevice = new DeviceInformation(deviceName);
                    if (!waveformAiCtrl1.Initialized)
                    {
                        MessageBox.Show("No device be selected or device open failed!");
                        return;
                    }
    
                    int channelCount = waveformAiCtrl1.Conversion.ChannelCount;
                    int sectionLength = waveformAiCtrl1.Record.SectionLength;
    
                    //d = new double[channelCount*sectionLength];
    
                    waveformAiCtrl1.Prepare();
                    ErrorCode er=ErrorCode.Success;
                    if (waveformAiCtrl1.State != ControlState.Running)
                    {
                        er = waveformAiCtrl1.Start();
                    }
                     
                    if (er != ErrorCode.Success)
                    {
                        MessageBox.Show("设备打开失败!");
                        return;
                    }
    
                    OperateCtrBtn(false);
                    OperateCustomBtn(false);
    
                    bufferedAITimer.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
               
            }
    
            private void btnStopCtrBuffAI_Click(object sender, EventArgs e)
            {
                //if (waveformAiCtrl1.State == ControlState.Idle)
                //{
                //    return;//has been disposed
                //}
                //waveformAiCtrl1.Stop();
                //waveformAiCtrl1.Dispose();
            }
    
            private object locker = new object();
            private void waveformAiCtrl1_DataReady(object sender, BfdAiEventArgs e)
            {
                double[] data = new double[e.Count];
                ErrorCode er = waveformAiCtrl1.GetData(e.Count, data);
                if (er != ErrorCode.Success)
                {
                    return;
                }
    
                lock (locker)
                {
                    for (int i = 0; i < data.Length; i += 4)
                    {
                        double[] temp = new double[4];
                        for (int j = 0; j < 4; j++)
                        {
                            temp[j] = data[i + j];
                        }
                        dataFromBuffAI.Add(temp);
                    }
                }
            }
            #endregion
    
            #region 控件InstantAI
    
            private void btnControlInstantAI_Click(object sender, EventArgs e)
            {
                try
                {
                    instantAiCtrl1.SelectedDevice = new DeviceInformation(deviceName);
                    if (!instantAiCtrl1.Initialized)
                    {
                        MessageBox.Show("No device be selected or device open failed!");
                        return;
                    }
    
                    OperateCtrBtn(false);
                    OperateCustomBtn(false);
    
                    ctrInstant.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }          
            }
    
            private void btnStopCtrInstantAI_Click(object sender, EventArgs e)
            {
                try
                {
                    //ctrInstant.Stop();
                }
                catch (Exception ex)
                {
                    MessageBox.Show( ex.Message);
                }
            }
    
            private void ctrInstant_Tick(object sender, EventArgs e)
            {
                double[] data = new double[4]; ;
                ErrorCode er0 = instantAiCtrl1.Read(0, out data[0]);
                ErrorCode er1 = instantAiCtrl1.Read(1, out data[1]);
                ErrorCode er2 = instantAiCtrl1.Read(2, out data[2]);
                ErrorCode er3 = instantAiCtrl1.Read(3, out data[3]);
    
                dataFromInstantAI.Add(data);
    
                DrawInstantAICurve();           
            }
            #endregion              
        }
    }
    View Code

    样式如下图所示:

     GitHub

    欢迎各位留言讨论!

  • 相关阅读:
    linux 进入 GNOME X 界面
    POJ 3436 ACM Computer Factory (拆点+最大流)
    学习:EF(Entity Framwork)结构【转】
    .net上传Excel,解析Excel,导出CSV
    在Handler里面使用Session
    如何用JavaScript判断访问的来源是电脑还是手机,是什么浏览器?
    ASP.NET List泛型分页代码 【转】
    ASP.NET MVC中实现多个按钮提交的几种方法【转】
    清空数据库所有表,所有存储过程SQL语句
    可以不被浏览器拦截的弹出窗口
  • 原文地址:https://www.cnblogs.com/EasonDongH/p/8818829.html
Copyright © 2011-2022 走看看