简仪模拟输出板卡使用指南
来源: | 作者:JYTEK | 发布时间: 2024-10-25 | 325 次浏览 | 分享到:

关键词:模拟输出,板载FIFO,连续非环绕输出,输出保持


导读

在实际工程应用中,经常需要使用模拟输出板卡输出指定的波形作为激励或者仿真,本篇文章以简仪5500系列板卡为例介绍模拟输出功能的使用方式,其余型号的板卡使用方式基本类似。


硬件参数

5500系列板卡的模拟输出参数见图一所示。以5515为例,此板卡有两个同步模拟输出通道,使能一个输出通道时最大更新率为2.86 MS/s,使能两个模拟输出通道时每通道最大更新率为2 MS/s。板卡为单端输出,输出阻抗为2欧姆低阻。每通道最大电流驱动能力为10 mA,因此需要外接功放才能拥有更大的驱动能力。所有输出通道共享32 M采样点的板载FIFO,如果使能2通道输出,每通道最大可用的板载FIFO是16 M采样点。


图一 5500系列板卡模拟输出参数


5500系列板卡有两个输出电压输出范围,分别是±5 V和±10 V,不同输出范围的电压输出精度见图二所示。

图二 5500系列板卡模拟输出参数


输出模式详解

5500系列板卡的模拟输出通道支持单点、有限点、连续环绕和连续非环绕这四种输出模式,其中后三种模式都需要事先向板载FIFO中写入数据,然后使用硬件时钟根据设定的时钟速率参数进行确定性波形输出。整个过程中用户可以直接针对板载FIFO进行操作,而无需经过PC内存。

下面针对这四种输出模式做个简单说明:

  1. 单点模式输出(Single):输出一个固定直流信号,如果在循环中持续更新输出电压值,就相当于软件定时的波形输出。此时输出速率决定于操作系统或程序(在生成循环中添加延时)。

  2. 有限点模式输出(Finite):事先向板载FIFO写入指定长度的波形数据,然后按照指定时钟速率开始对外输出,数据全部输出完毕后任务自动停止,整个输出过程的持续时间等于输出数组长度除以更新率。每个通道输出数据的最大长度取决于板载FIFO大小除以通道数。

  3. 连续环绕模式输出(ContinuousWrapping):事先向板载FIFO写入指定长度的波形数据,然后按照指定时钟速率开始对外循环输出,直到上位机发送停止输出指令为止。因为数据被预存到了板载FIFO中,在整个模拟输出的过程中都没有数据总线和内存的交互操作。由于了减少了系统的交互,使用这种模式的模拟输出更新率最大。

  4. 连续非环绕模式输出(ContinuousNoWrapping):事先向板载FIFO写入指定长度的波形数据,然后按照指定时钟速率开始对外输出,在此过程中用户需要不停地向板载FIFO中写入新数据。旧数据在输出之前都不会被新写入的数据覆盖,如果PC端写入/发送数据的速度小于板载FIFO的输出速度,就会产生underflow错误,如果PC端写入/发送数据的速度超过板载FIFO的输出速度,板载FIFO可能处于满载状态,需要等待板载FIFO有空余位置时才可以写入新数据,或者达到指定的超时时间后报错。


限点输出模式的进一步说明

有限点输出模式下,当写入的数据全部输出完毕后,输出任务也就自动停止了。可以通过WaitUntilDone(int timeout = -1)方法查询输出任务是否完成,括号中的输入参数含义是单位为ms的超时时间,设置为-1代表永不超时。

此外,在有限点输出模式下,所有通道加起来一共的写入点数不能超过板载FIFO大小,否则就会产生”Error_AO_SamplesToUpdateOverRange”的异常。那么如果需要输出的点数超过板载FIFO,可以参考下文提到的连续非环绕模式,将总数据切分为多个小于板载FIFO大小的数组,分次写入板载FIFO再进行输出即可,还需要在循环中需要手动设置停止输出条件。


连续非环绕模式输出的进一步说明

为了能够在波形输出的同时程序地更改DAQ设备输出的波形,必须使用连续非环绕模式进行输出,此时板载FIFO在输出旧的数据的同时也需要有新数据的持续写入。在使用过程中,我们经常会遇到以下两个问题:

  • 为什么会产生underflow报错?

  • 为什么写入的新数据要过好几秒甚至几十秒才会出现在输出端,怎样才能让新数据尽快地进行输出?


首先我们来看第一个问题,在前面介绍连续非环绕模式输出时我们提到过如果PC端写入/发送数据的速度一直小于板载FIFO的输出速度,那么当板载FIFO为空的时候就没有数据输出了,此时驱动就会产生underflow的报错。因此必须保证板载FIFO不能为空才会避免出现此类报错。


刚才提到的板载FIFO为空是一个极端,针对第二个问题我们来看另一个极端,也就是板载FIFO一直处于满载状态。此时如果继续调用写入方法向缓冲区写入新数据,必须要等待板载FIFO出现空位置才可以写入,而且由于FIFO的先进先出特性,此时写入的数据需要几秒钟甚至更长时间才能反映到输出端,因为新的波形数据需要传过整个板载的FIFO。如果想要使得写入的新数据尽可能快的出现在输出端,就要在板载FIFO几乎是空的状态时进行写入,此时新数据在输出前不需要经过整个FIFO,在到达DAQ板卡的时候已经在FIFO的末端,能够立即出现在输出端。


下面我们来看下在C#代码中如何实现刚才提到的问题,我们可以参考Winform AO Continuous NoWrapping这个范例。整个代码的执行分为以下几个步骤:

  1. 初始化模拟输出任务;

  2. 添加通道,设置更新率参数,设置输出模式为ContinuousNoWrapping;

  3. 写入一段数据到板载FIFO中;

  4. 开始输出任务;

  5. 在定时器循环中持续向板载FIFO中写入新数据;

  6. 停止输出任务并清除通道参数设置。


在驱动中提供了两个属性节点可以查询板载FIFO的内部状态:

  • AvaliableLenInSamples:当前每通道可以写入板载FIFO的点数,也就是当前板载FIFO空余的点数

  • BufLenInSamples:板载FIFO中能够容纳的每通道的最大点数


目前范例中的写入条件是aoTask.AvaliableLenInSamples >= writeValue.Length,也就是说当每次板卡板载FIFO不是满的,就会写入新的数据,此时板载FIFO总是保持接近满载的状态,这意味着如果要改变波形的输出,这种改变需要很长的时间才能反映到输出端。


如果希望新写入的数据尽可能快的出现在板卡输出端,建议尝试以下设置:

  • 让循环运行的速度尽可能快,比如while循环减少sleep时间,定时器的Interval尽可能小,禁用界面控件更新等;

  • 减小每次写入的数据块大小;

  • 降低更新率,从而减缓板载FIFO的清空速度;

  • 修改循环中的写入条件,使得板载FIFO处于近乎空的状态。使用BufLenInSamples减去AvaliableLenInSamples可以得到当前板载FIFO中剩余等待输出的点数,可以根据这个差值的大小来控制写入新数据的条件,但前提是不能让板载FIFO为空,否则就会产生前面提到的underflow报错。比如如下代码,当检测到板载FIFO中的点数小于1000时就会写入一次新数据。

              if (aoTask.BufLenInSamples - aoTask.AvaliableLenInSamples <= 1000)

              {

                     aoTask.WriteData(writeValue, -1);

              }             

             

这里给出一个参考的参数设置,可以维持较快的新数据更新:

  • 将定时器的Interval设置为1 ms;

  • 假设输出信号频率和每次写入的数据块大小都为A,可以设置板卡的更新率为100*A,即每次写入的波形长度是100个周期;

  • 循环中的写入条件为aoTask.BufLenInSamples - aoTask.AvaliableLenInSamples <= 10*A,即当板载FIFO中的数据量小于10个周期波形时执行一次新数据写入。


输出保持

在进行模拟输出操作时,当停止运行程序后,不同的应用场景对最终输出状态的要求是不同的。如果是使用模拟输出控制一个设备的运行比如电机,那么用户一般的预期是程序停止后设备也应当停止运行,此时板卡的输出应当归零。如果使用模拟输出控制一台显微镜的振镜偏转,那么一般的预期是程序停止后振镜应当保持在最终的偏转位置,此时板卡的输出应当保持当前输出的最终状态。默认情况下,应用程序完成后,写入设备的最后一个值将被继续保留,也就是维持上一次输出时最后一个点的电压。除非重启计算机,否则板卡会一直保持输出状态。对于某些第三方板卡来讲,只能在程序结束之前,手动地将零伏特(0V)写入通道中。对于5500系列板卡而言,可以通过CompleteState这个属性来设定输出完成状态,默认值Hold表示输出保持,将属性设置为Zero就可以将输出完成状态设置为归零。


需要注意的是这个CompleteState属性是通过是否复位DAC来控制所有通道的输出完成状态,如果需要每个通道的输出完成状态不同,需要设置此属性为Hold,然后在停止任务前对需要归零的通道单独写入0伏特的电压。