【问题标题】:Real time NI-DAQ data plot in MatlabMatlab中的实时NI-DAQ数据图
【发布时间】:2021-06-18 21:58:04
【问题描述】:

我正在尝试获取我使用 NI USB-6008 采集的数据的实时图。我尝试用 arduino 做同样的事情,得到了一个完全符合我要求的图(见这里https://i.stack.imgur.com/08kzU.jpg),x 轴会实时移动,但我无法定义采样率。使用 NI,我能够定义我想要的采样率,但我无法在连续的实时图中显示数据,我一次只能看到 1 秒,我需要能够访问所有因为我想测量实时脑电图而获得的数据。我是matlab新用户,所以请不要考虑以前的知识。

这是我目前得到的代码:

clear
close all

dq = daq("ni");
ch1 = addinput(dq, "Dev1", "ai0", "Voltage");
dq.Rate = 1000;
dq.ScansAvailableFcn = @(src,evt) plotDataAvailable(src, evt);
dq.ScansAvailableFcnCount = 100;
start(dq, "Duration", seconds(5))

while dq.Running
    pause(0.5);
end

time = 0;
data = 0;
n = ceil(dq.Rate/10);

%Set up Plot
figure(1)
plotGraph = plot(time,data); 
title('DAQ data log','FontSize',15);
xlabel ('Elapsed Time (s)','FontSize',10); ylabel('Voltage (V)','FontSize',10);
h = animatedline;
ax = gca;
ax.YGrid = 'on';
ax.XGrid = 'on';
h = animatedline;
function plotDataAvailable(src, ~)
    while ishandle(plotGraph) % Loop when Plot is Active will run until plot is closed
        data = read(dq,n);
        t =  datetime('now');
        % Add points to animation
        addpoints(h,datenum(t),data)
        % Update axes
        ax.XLim = datenum([t-seconds(15) t]);
        datetick('x','keeplimits')
        drawnow
    end
end

这是我之前的 arduino 代码,它向我展示了我需要的图(采样率错误):

clear
clc

%User Defined Properties 
a = arduino('com4','uno');              % Define the Arduino Communication port
plotTitle = 'Arduino Data Log';         % Plot title

%Define Function Variables
time = 0;
data = 0;

%Set up Plot
figure(1)
plotGraph = plot(time,data,'-r' ); 
title(plotTitle,'FontSize',15);
xlabel ('Elapsed Time (s)','FontSize',10); ylabel('Voltage (V)','FontSize',10);
h = animatedline;
ax = gca;
ax.YGrid = 'on';
ax.XGrid = 'on';
ax.YLim = [0 5];            % Sets y-min and y-max
while ishandle(plotGraph) % Loop when Plot is Active will run until plot is closed
        startIteration = tic;
        voltagem = readVoltage(a,'A0')
        t =  datetime('now');
        % Add points to animation
        addpoints(h,datenum(t),voltagem)
        % Update axes
        ax.XLim = datenum([t-seconds(15) t]);
        datetick('x','keeplimits')
        drawnow
end

我尝试在我的 NI 数据上使用这个 while 循环,但它不起作用。

非常感谢您的帮助。

【问题讨论】:

  • 您以 1000Hz 的频率进行采样,并且只要缓冲区中有 1000 个样本,就会调用您的回调函数,因此很自然地会以(大约)1 秒的间隔调用它。一般来说,如果你想以fCallback的频率调用回调函数,你需要将可用样本数设置为fSampling/fCallback。因此,例如,如果要以 10Hz(每 0.1s)的频率进行绘图,则必须将样本数设置为 1000/10 = 100
  • 此外,您在每次调用回调函数时都会创建新的animatedlines,这正是animatedlines 应该帮助您防止这样做的。在开始采样之前创建animatedlines,然后只要有新数据可用,就只给他们addpoints
  • 但是我需要绘图来显示至少 10 秒的数据,并且我需要能够访问我记录的所有数据,而不仅仅是最后 10 秒。关于addpoints函数,它不起作用,因为我从NI得到的数据不是double
  • 1) 总采样持续时间(您的 10 秒)与ScansAvailableFcnCount 属性无关。正如我上面所说,这只告诉程序多久调用一次回调函数,所以这就是你需要改变的。 2)read()返回double,所以没有问题。 3) 即使没有,您也可以随时将变量转换为其他类型。
  • 哦!好的,我已经解决了。现在我无法弄清楚为什么我的代码根本不起作用。我不知道我是否可以像使用 arduino 一样做,但这就是我目前所拥有的。你能看看吗?非常感谢你的帮助顺便说一句

标签: matlab real-time-data nidaqmx


【解决方案1】:

您的操作顺序错误。您的代码目前正在执行的操作是:

  1. 初始化数据采集
  2. 在尝试将数据添加到不存在的行时从硬件读取数据
  3. 初始化动画线条。

此外,在您的 addpoints 调用中,您尝试绘制 t(标量)和数据(数组)。

你应该做的是:

clear
close all

% Set up the plot
figure(1)
title('DAQ data log','FontSize',15);
xlabel ('Elapsed Time (s)','FontSize',10)
ylabel('Voltage (V)','FontSize',10);
h = animatedline;
ax = gca;
ax.YGrid = 'on';
ax.XGrid = 'on';

% Set up the data acquisition
dq = daq("ni");
ch1 = addinput(dq, "Dev1", "ai0", "Voltage");
dq.Rate = 1000;
dq.ScansAvailableFcn = {@plotDataAvailable, h, ax}; % pass also the handle to the line and to the axes
dq.ScansAvailableFcnCount = 100;

% Now you start the data acquisition
start(dq, "Duration", seconds(5))


function plotDataAvailable(src, evt, h, ax)
    data = read(dq, n);
    % maybe your time array should look something like this?
    t = datetime(now) - seconds((length(data)-1:-1:0)./src.Rate);

    % Add points to animated line
    addpoints(h, datenum(t), data)

    % Update axes
    % ax.XLim = datenum([t-seconds(15) t]); % this line is useless, why would you have a 15s window when your data acquisition is only 5s long?
    datetick('x','keeplimits')
    drawnow

end

我目前无法尝试,所以它可能无法完全正常工作。

【讨论】:

  • 我认为这条线不起作用dq.ScansAvailableFcn = {@plotDataAvailable, h, ax}; % pass also the handle to the line and to the axes,我已经尝试过其他的东西,比如dq.ScansAvailableFcn = @plotDataAvailable(src,evt,h,ax);dq.ScansAvailableFcn = @(src,evt,h,ax) plotDataAvailable(src,evt,h,ax);dq.ScansAvailableFcn = @(h,ax) plotDataAvailable(h,ax);dq.ScansAvailableFcn = @(src, evt) plotDataAvailable(h,ax);dq.ScansAvailableFcn = @(src, evt) plotDataAvailable(src,evt,h,ax);但似乎没有工作,我真的不知道这行代码是如何工作的
  • 那行是 100% 正确的。此外,“它不起作用”不是有效的评论,请解释如何它不起作用。
  • 它说“将 ScansAvailableFcn 指定为标量函数句柄。”当我这样写dq.ScansAvailableFcn = @(src,evt,h,ax) plotDataAvailable(src,evt,h,ax); 时,它也不起作用,并且会出现 1000 行错误。
  • 我认为那条线不是唯一的问题。有空可以试试吗?
  • 另外,data = read(dq,n) 正在返回一个矩阵,我不知道为什么
【解决方案2】:

所以我想我终于明白了,因为我得到了我想要的情节,x 轴实时移动。但是,我仍然收到一条错误消息,提示“无法识别的表变量名称'Dev1_ai0'”事件,但我检查了这是我想要的行的名称。不管怎样,这就是我的代码现在的样子。

clear
close all

time = 0;
data = 0;

% Set up the plot
figure(1)
plotGraph = plot(time,data,'-r' ); 
title('DAQ data log','FontSize',15);
xlabel ('Elapsed Time (s)','FontSize',10)
ylabel('Voltage (V)','FontSize',10);
h = animatedline;
ax = gca;
ax.YGrid = 'on';
ax.XGrid = 'on';

% Set up the data acquisition
dq = daq("ni");
ch1 = addinput(dq, "Dev1", "ai0", "Voltage");
dq.Rate = 1000;

% Start the data acquisition
start(dq, "Duration", seconds(10))
n = ceil(dq.Rate/10);


while ishandle(plotGraph)
    data = read(dq, n);
    voltage = data.Dev1_ai0;
    
    t = datetime('now');
    
    for i = 1:100
    % Add points to animated line
        if isvalid(h)
        addpoints(h, datenum(t), voltage(i))
        end
    end

    % Update axes
    ax.XLim = datenum([t-seconds(15) t]);
    datetick('x','keeplimits')
    drawnow

end

disp('Plot Closed')

【讨论】:

    猜你喜欢
    • 2016-09-24
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    相关资源
    最近更新 更多