Teresa
Teresa

Reputation: 1

Real time NI-DAQ data plot in Matlab

I'm trying to get a real time plot of data I'm acquiring with a NI USB-6008. I tried doing the same with arduino and got a plot exactly as I wanted (see here https://i.sstatic.net/08kzU.jpg), and the x-axis would move in real-time, but I couldn't define the sampling rate. With NI I was able to define the sampling rate I wanted but I can't display the data in a continuous, real-time plot, I can only see 1 sec at a time and I need to be able to have access to all the data acquired since I want to measure a real-time EEG. I'm a new matlab user, so please consider no previous knowledge.

This is the code I've got so far:

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

This was my previous arduino code that showed me the plot I needed (with the wrong sampling rate):

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

I've tried using this while loop on my NI data but it doesn't work.

I would really appreciate your help.

Upvotes: 0

Views: 1428

Answers (2)

Teresa
Teresa

Reputation: 1

So I think I finally got it, because I got the plot like I wanted, with the x-axis moving with real-time. However I still get an error saying "Unrecognized table variable name 'Dev1_ai0'" event tho I checked that's the name of the row that I want. Anyways, this is what my code looks now.

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')

Upvotes: 0

Matteo V
Matteo V

Reputation: 1163

You've got the order of the operations wrong. What your code is doing at the moment is:

  1. initialize the data acquisition
  2. read the data from the hardware while trying to add data to lines that don't exist
  3. initialize the animated lines.

Furthermore, in your addpoints call you're trying to plot t, which is a scalar, and data, which is an array.

What you should do instead is:

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

I can't try this at the moment, so it might not work exactly.

Upvotes: 0

Related Questions