Simulink中的数据采集工具箱(基于会话的接口),具有2级M-S功能或C库

时间:2013-04-06 10:58:01

标签: matlab simulink

我目前正在开发一个涉及Simulink中数据采集和实时处理的项目。我们有一些专门为这个项目购买的DAQ硬件 - 即National Instruments DAQ设备(USB)。

我必须使用基于会话的界面。 我尝试写一个2级M-S函数,但我的问题是,我不知道我应该在哪里用daq.createSession函数创建会话,我可以在哪里创建模拟输出。有人代码示例或建议吗?

或者编写C库是否容易?哪个Simulink块我可以用于这个C库? Matlab的功能?我可以使用DAQmxErrChk(DAQmxCreateAOVoltageChan(taskHandle,“Dev1 / ao0”,“”, - 10.0,10.0,DAQmx_Val_Volts,NULL));在Simulink whitout问题中DAQmx示例的功能?

1 个答案:

答案 0 :(得分:0)

我无法发布我的整个解决方法,因为它有很多行代码,而且有点违反SO法规。但是,我会尽力解释它是如何工作的,以便你可以做类似的事情。我的生活在编写时肯定变得更容易了,因为我有一组允许你在一个类中编写Level-2 M-S函数的类,但你当然可以不用。

基本上你最好的选择是为你的街区创建一个面具。每次修改掩码参数时,Simulink都会调用您的onSetup回调 - 您通常会在其中设置频道/注册其他M-S函数回调。正是在这个函数中,我创建了我的DAQ会话,如果它尚未创建,则更新通道计数,采样率和通道模式(以及任何其他会话信息)。然后,您可以将块的UserData属性设置为DAQ会话接口,或者某个句柄或具有DAQ会话引用的句柄类的实例。

您还需要一些排队传入数据的方法。您可以从FileExchange获取队列类(我认为有一些),虽然我不确定这些的速度。我创建了一个使用循环缓冲区作为其数据存储的队列类,因为这里可能没有必要完全实现链表,这可能更快(不需要每个都删除/实例化一个类)一个新样本进来的时间)。如果您尝试弹出空队列,则会出现类错误,如果您按下完整队列,则会发出“队列溢出”类型错误警告。队列分别在onPostPropagationSetuponTerminate中分配/取消分配。

从DAQ会话收到数据时,将调用以下函数

function onDaqDataAvailable(self, data)
    self.sampleQueue.push(data.Data);
    self.updateOutputStatus();
end

function updateOutputStatus(self)
    if self.sampleQueue.filledLocs >= 0.5 * self.sampleQueue.queueLength
        self.bOutput = true;
    else
        self.bOutput = false;
    end

    drawnow update;
end

我不确定那里的门槛是否真的有必要,实际上认为它可能有点太高了,但你可以自己动摇它。然后,在onOutputs回调中,我们有

    function onOutputs(self, block)
        if ~self.daqSess.IsRunning
            self.daqSess.startBackground();
        end

        while ~self.bOutput
            pause(0.1 * self.frameLength / self.sampleRate);
            // Displaying number of samples in queue is useful for debugging here...
            // But we should really use a scope instead
            disp(self.sampleQueue.filledLocs)
            self.updateOutputStatus();
        end

        // Displaying number of samples in queue is useful for debugging here...
        // But we should really use a scope instead
        //disp(self.sampleQueue.filledLocs)
        samples = self.sampleQueue.pop(self.frameLength);
        for nChan = 1:self.nChannels
            block.OutputPort(nChan).Data = samples(:, nChan);
        end

        self.updateOutputStatus();
    end

这是块实际工作方式的基础。需要注意的是,您需要将DAQ会话的NotifyWhenDataAvailableExceeds属性设置为合理的,这样每秒最多可以调用20次onDaqDataAvailable,但是一旦有了示例队列,这就相当简单了。另请注意,在模型准备就绪之前,DAQ会话实际上并未启动。事先启动会导致大量队列超支,因为范围等会打开他们的UI。

我希望这已经足以为您提供类似的解决方法。