主要内容

用软件模拟触发捕获数据

这个例子展示了如何基于软件中定义的触发器条件实现触发的数据捕获。数据采集工具箱为硬件触发数据采集对象提供了功能,例如基于外部数字触发信号(上升或下降边缘)从DAQ设备开始采集。然而,对于某些应用来说,最好是基于被测量的模拟信号开始捕获或记录数据,只允许从连续的数字化测量数据流中捕获感兴趣的信号(例如当信号水平超过某个阈值时的音频记录)。

自定义图形用户界面(UI)用于显示连续模式下采集的数据的实时图,并允许您根据所采集的模拟输入信号水平和斜率为自定义触发条件输入触发器参数值。捕获的数据显示在交互式UI中,并保存到MATLAB基本工作区变量中。

这个示例可以很容易地修改为使用支持DirectSound的音频设备的音频输入通道。金宝app

代码结构为单个程序文件,包含一个主函数和几个局部函数。

硬件设置

  • 一种具有模拟输入通道的DAQ设备(如NI USB-6218)金宝appDataAcquisition后台采集模式下的接口。

  • 外部信号连接到模拟输入通道。本例中的数据表示串联电阻-电容(RC)电路的测量电压:RC的总电压(在本例中由函数发生器提供)在通道AI0上测量,而电容的电压在通道AI1上测量。

配置数据采集与捕获参数(主要功能)

配置具有两个模拟输入通道的数据采集对象,并设置采集参数。后台连续采集模式在发生ScansAvailable事件时,通过调用用户定义的回调函数(dataCapture)来提供所采集的数据。自定义图形用户界面(UI)用于实时获取的数据可视化和基于用户指定的触发器参数的交互式数据捕获。

函数softwareAnalogTriggerCapturesoftwareAnalogTriggerCapture使用软件模拟触发的DAQ数据捕获softwareAnalogTriggerCapture为实时的DAQ数据启动一个用户界面可视化和基于软件模拟的交互式数据捕获。%触发条件。配置数据采集对象,增加输入通道S = daq(“倪”);Ch1 = addinput(s,“Dev1”0,“电压”);Ch2 = addinput(s,“Dev1”, 1“电压”);为每个通道设置采集配置ch1。TerminalConfig =“SingleEnded”;ch2。TerminalConfig =“SingleEnded”;ch1。Range = [-10.0 10.0];ch2。Range = [-10.0 10.0];设置采集速率,单位为扫描/秒s.速率= 10000;为数据捕获和实时绘图指定所需的参数。数据捕获参数按结构数据类型分组,%,因为这样可以更简单地将它们作为函数参数传递。指定触发的捕获时间跨度,以秒为单位捕捉。TimeSpan = 0.45;指定连续数据图时间跨度,以秒为单位捕捉。plotTimeSpan = 0.5;确定与所提供样品块相对应的时间跨度%添加到ScansAvailable事件回调函数。callbackTimeSpan = double(s.ScansAvailableFcnCount)/s.Rate;确定所需的缓冲区时间跨度,秒捕捉。bufferTimeSpan = max([capture.]plotTimeSpan,捕获。TimeSpan * 3, callbackTimeSpan * 3]);确定数据缓冲区大小捕捉。bufferSize = round(捕获。bufferTimeSpan * s.Rate);显示图形用户界面hGui = createDataCaptureUI(s);配置ScansAvailableFcn回调函数指定的数据捕获参数和UI图形的句柄%元素作为附加参数传递给回调函数。s.ScansAvailableFcn = @(src,event) dataCapture(src, event, capture, hGui);为采集错误配置erroroccurs fcn回调函数%事件,可能发生在后台获取s. erroroccurs fcn = @(src,event) disp(getReport(event. error));开始持续的后台数据采集开始(年代,“连续”等待用户界面上的数据采集对象停止s.Running暂停(0.5)结束%与硬件断开连接删除(年代)结束

后台采集回调函数

每次发生ScansAvailable事件时,都会重复调用dataCapture用户定义回调函数。随着每个回调函数的执行,最新获取的数据块和时间戳被添加到一个持久的FIFO数据缓冲区,一个连续获取的数据图被更新,最新的数据被分析,以检查触发条件是否满足,并且——一旦捕获被触发,并且已经为指定的时间跨度捕获了足够的数据——捕获的数据被保存在基本工作区变量中。捕获数据为N × M矩阵,对应于N次采集数据扫描,时间戳为第一列,每个通道对应的采集数据为列2:M。

函数dataCapture(src, ~, c, hGui)当ScansAvailable事件调用时,处理DAQ采集的数据。% datcapture处理最新获取的数据和数据的时间戳%的采集对象(src),并且,基于指定的捕获参数(c% structure)和从用户界面触发配置参数% elements (hGui处理结构),更新UI绘图和捕获数据。% c.TimeSpan =触发的捕获时间间隔(秒)% c.bufferTimeSpan =所需的数据缓冲区时间间隔(秒)% c.bufferSize =所需的数据缓冲区大小(扫描次数)% c.plotTimeSpan =连续采集数据时间间隔(秒)[eventData, eventTimestamps] = read(src, src.]ScansAvailableFcnCount,...“OutputFormat”“矩阵”);读取数据存储在一个持久缓冲区(dataBuffer)中,即%大小允许触发数据捕获。%,因为需要多次调用dataccapture来触发%捕获,触发条件标志(trigActive)和相应的% data时间戳(trigMoment)被用作持久变量。持久变量在调用函数之间保留它们的值。持续的dataBuffer trigActive trigMoment%如果datapcapture是第一次运行,初始化持久变量如果eventTimestamps(1)==0 dataBuffer = [];%数据缓冲区trigActive = false;%触发条件标志trigMoment = [];满足触发条件时%数据时间戳prevData = [];%上次回调执行的最后一个数据点其他的prevData = dataBuffer(end,:);结束在持久先进先出中存储连续采集时间戳和数据数据缓冲latestData = [eventTimestamps, eventData];dataBuffer = [dataBuffer;latestData];numSamplesToDiscard = size(dataBuffer,1) - c.bufferSize;如果(numSamplesToDiscard > 0) dataBuffer(1:numSamplesToDiscard,:) = [];结束更新实时数据图绘制最新的plotTimeSpan秒数据在dataBuffersamplesToPlot = min([round(c;plotTimeSpan * src.Rate), size(dataBuffer,1)]);firstPoint = size(dataBuffer, 1) - samplesToPlot + 1;更新x轴限制xlim (hGui。Axes1, [dataBuffer(firstPoint,1), dataBuffer(end,1)]);每个获取渠道都有一条线路。ii = 1:numel(hGui.LivePlot) set(hGui.LivePlot(ii),“XData”, dataBuffer(firstPoint:end, 1),...“YData”, dataBuffer(firstPoint:end, 1+ii))结束%如果请求捕获,分析最新获取的数据,直到触发%条件满足。在获得足够的数据进行完全捕获之后,中指定的捕获时间间隔,从%数据缓冲区,并将其保存到基本工作区变量。从UI获取捕获切换按钮值(1或0)capturerrequested = hGui.CaptureButton.Value;如果捕获请求&& (~trigActive)%状态:“正在寻找触发事件”%更新UI状态hGui.StatusText.String =“等待触发”从UI文本输入和获取触发器配置参数把它们放在一个结构中。为简单起见,本例中不涉及用户输入的验证。。trigConfig。Channel = sscanf(hGui.TrigChannel.String,' % u ');trigConfig。Level = sscanf(hGui.TrigLevel.String,' % f ');trigConfig。斜率= sscanf(hGui.TrigSlope.String,' % f ');%确定在最新获取的数据中是否满足触发条件在trigDetect用户函数中定义了一个自定义触发器条件[trigActive, trigMoment] = trigDetect(prevData, latestData, trigConfig);elseifcapturerequered && trigActive && ((dataBuffer(end,1)-trigMoment) > c.TimeSpan)%状态:“已获得足够的数据以完成捕获”%如果触发,如果在dataBuffer中有足够的数据触发% capture,则可以从dataBuffer中获取captureData。在时间戳值为trigMoment的dataBuffer中查找样本的索引trigSampleIndex = find(dataBuffer(:,1) == trigMoment, 1,“第一”);在dataBuffer中找到样本的索引来完成捕获lastSampleIndex = round(trigSampleIndex + c.TimeSpan * src.Rate());captureData = dataBuffer(trigSampleIndex:lastSampleIndex,:);重置触发标志,以允许新的触发数据捕获trigActive = false;%更新捕获的数据图(每个采集通道一行)ii = 1:numel(hGui.CapturePlot) set(hGui.CapturePlot(ii),“XData”, captureData(:, 1),...“YData”, captureData(:, 1+ii))结束更新UI以显示已完成捕获hGui.CaptureButton.Value = 0;hGui.StatusText.String =''将捕获的数据保存到基本工作区变量为简单起见,验证用户输入并检查变量是否。在此示例中没有指定已存在的相同名称的%。从UI文本输入中获取变量名varName = hGui.VarName.String;使用assignin函数将捕获的数据保存在基本工作区变量中assignin (“基地”, varName, captureData);elseifcapturerequrequested && trigActive && ((dataBuffer(end,1)-trigMoment) < c.TimeSpan)%状态:“正在捕获数据”在此回调执行期间,获取的数据不足以覆盖捕获时间跨度hGui.StatusText.String =“触发”elseif~ captureRequested%状态:"未请求捕获"%捕获切换按钮未按下,设置触发标志并更新UItrigActive = false;hGui.StatusText.String =''结束drawnow结束

为实时数据捕获创建图形用户界面

通过编程方式创建一个用户界面,包括创建一个图、一个用于实时采集数据的图、一个用于捕获数据的图、启动捕获和停止捕获的按钮以及用于输入触发器配置参数和状态更新的文本字段。

为了简单起见,图形和所有用户界面组件都有固定的大小和位置,用像素定义。对于高DPI显示,位置值可能必须调整为最佳尺寸和布局。创建自定义UI的另一个选项是使用App Designer。

函数hGui = createDataCaptureUI(s)为数据捕获创建一个图形用户界面。% hGui = createDataCaptureUI(s)返回图形结构% components处理(hGui)并创建图形用户界面以编程方式创建图形并添加所需图形。组件,用于从数据采集中获得的数据的可视化%对象。创建一个图并配置回调函数(在窗口关闭时执行)hGui。图= figure(“名字”“软件模拟触发数据捕获”...“NumberTitle”“关闭”“调整”“关闭”...“工具栏”“没有”“菜单”“没有”...“位置”, [100 100 750 650]);hGui.Fig.DeleteFcn = {@endDAQ, s};uiBackgroundColor = hGui.Fig.Color;使用图例创建连续数据图轴。%(每个采集通道一行)hGui。坐标轴1 =坐标轴;hGui。LivePlot = plot(0,零(1,numel(s.Channels)));包含(“时间(s)”);ylabel (“电压(V)”);标题(连续数据的);传奇({s.Channels.ID},“位置”“northwestoutside”) hGui.Axes1。单位=“像素”;hGui.Axes1。位置= [207 391 488 196];关闭实时绘图轴的轴工具栏和数据提示。hGui.Axes1.Toolbar。可见=“关闭”;disableDefaultInteractivity (hGui.Axes1);创建捕获的数据图轴(每个采集通道一行)hGui。=坐标轴(“单位”“像素”“位置”, [207 99 488 196]);hGui。CapturePlot = plot(NaN, NaN(1, numel(s.Channels)));包含(“时间(s)”);ylabel (“电压(V)”);标题(获取的数据的);hGui.Axes2.Toolbar。可见=“关闭”;disableDefaultInteractivity (hGui.Axes2);创建停止采集按钮,并配置回呼功能。hGui。DAQButton = uicontrol(“风格”“按钮”“字符串”“停止采集”...“单位”“像素”“位置”, [65 394 81 38]);hGui.DAQButton.Callback = {@endDAQ, s};创建数据捕获按钮并配置回调功能。hGui。CaptureButton = uicontrol(“风格”“togglebutton”“字符串”“捕捉”...“单位”“像素”“位置”, [65 99 81 38]);hGui. capturebutton . callback = {@startCapture, hGui};创建一个状态文本字段hGui。StatusText = uicontrol(“风格”“文本”“字符串”''...“单位”“像素”“位置”, [67 28 225 24],...“HorizontalAlignment”“左”“写成BackgroundColor”, uiBackgroundColor);为捕获的数据变量名创建一个可编辑的文本字段hGui。VarName = uicontrol(“风格”“编辑”“字符串”“mydata”...“单位”“像素”“位置”, [87 159 57 26]);为触发通道创建一个可编辑文本字段。hGui。TrigChannel = uicontrol(“风格”“编辑”“字符串”' 1 '...“单位”“像素”“位置”, [89 258 56 24]);为触发信号级别创建一个可编辑的文本字段hGui。TrigLevel = uicontrol(“风格”“编辑”“字符串”“1.0”...“单位”“像素”“位置”, [89 231 56 24]);为触发信号斜率创建一个可编辑文本字段hGui。TrigSlope = uicontrol(“风格”“编辑”“字符串”“200.0”...“单位”“像素”“位置”, [89 204 56 24]);%创建文本标签hGui。txtTrigParam = uicontrol(“风格”“文本”“字符串”“触发参数”...“位置”, [39 290 114 18],“写成BackgroundColor”, uiBackgroundColor);hGui。txtTrigChannel = uicontrol(“风格”“文本”“字符串”“通道”...“位置”, [37 261 43 15],“HorizontalAlignment”“对”...“写成BackgroundColor”, uiBackgroundColor);hGui。txtTrigLevel = uicontrol(“风格”“文本”“字符串”“水平(V)”...“位置”, [35 231 48 19],“HorizontalAlignment”“对”...“写成BackgroundColor”, uiBackgroundColor);hGui。txtTrigSlope = uicontrol(“风格”“文本”“字符串”“斜率(V / s)”...“位置”, [17 206 66 17],“HorizontalAlignment”“对”...“写成BackgroundColor”, uiBackgroundColor);hGui。txtVarName = uicontrol(“风格”“文本”“字符串”“变量名”...“位置”, [35 152 44 34],“写成BackgroundColor”, uiBackgroundColor);结束函数startCapture(obj, ~, hGui)如果obj。价值%如果按下按钮清除数据捕获图ii = 1:numel(hGui.CapturePlot) set(hGui.CapturePlot(ii),“XData”南,“YData”、南);结束结束结束函数endDAQ(~, ~, s)如果isvalid (s)如果s.Running停止(s);结束结束结束
后台操作已启动。要停止后台操作,使用stop。要读取获取的扫描,使用read。

检测采集数据中的触发条件

在本例中,触发条件由触发通道上的信号电平和相应的斜率定义。根据所获取的应用程序和实际数据,可以实现数据过滤或更复杂的触发器条件。

函数[trigDetected, trigMoment] = trigDetect(prevData, latestData, trigConfig)%trigDetect检测获取数据中是否满足触发条件% [trigDetected, trigMoment] = trigDetect(prevData, latestData, trigConfig)返回一个检测标志(trigDetected)和相应的时间戳满足触发条件的第一个数据点的% (trigMoment)%,根据信号电平和触发参数指定的斜率% structure (trigConfig)。输入数据(latestData)是一个N × M矩阵,对应于获取的N%数据扫描,时间戳作为第一列,通道数据%作为列2:M。前一个数据点prevData (1 × M时间戳向量%和通道数据)用于确定第一个数据点的斜率。% trigConfig。Channel =数据采集对象通道中触发通道的索引% trigConfig。信号触发电平(V)% trigConfig。斜率=信号触发斜率(V/s)信号触发级别的条件trigCondition1 = latestData(:, 1+trigConfig.Channel) > trigConfig.Level;data = [prevData;]latestData];%计算信号数据点的斜率从时间戳计算时间步长dt = latestData(2,1)-latestData(1,1);斜率= diff(data(:, 1+trigConfig.Channel))/dt;%信号触发斜率条件trigCondition2 =坡度>;如果获取第一个数据块,则不定义第一个数据点的斜率如果isempty(prevData) trigCondition2 = [false;trigCondition2];结束%要使用的组合触发条件trigCondition = trigCondition1 & trigCondition2;trigDetected = any(trigCondition);trigMoment = [];如果trigDetected%查找满足触发条件的时间时刻trigTimeStamps = latestData(trigCondition, 1);trigMoment = trigTimeStamps(1);结束结束