Matlab Data Acquisition Toolbox test data - matlab

I'm using Matlab's Data Acquisition Toolbox for interfacing with a National Instruments ADC. Unfortunately, I only have access to the hardware in my lab for limited parts of the day, but I'd like to be able to develop and test my code when I don't have access. Does anyone know of a way that I can collect some sample data, then feed it into the DAQ toolbox from a file instead of from the actual hardware? It needs to be input over time, same as it would with the NI hardware.
Current code:
s = daq.createSession('ni');
s.addAnalogInputChannel('Dev1',0,'Voltage');
s.Rate = 250;
s.DurationInSeconds = 30;
lh = s.addlistener('DataAvailable', #(src,event)myfunction(src,event));
s.NotifyWhenDataAvailableExceeds = 1000;
s.startBackground();
s.wait();
delete(lh);

Related

PLot Realtime data using MATLAB

I am trying to plot real-time data from a sensor that has a frequency of 25 Hz. I read data from the sensor using TCPIP protocol, parse it and then plot the data. However, the plotting part is not very fast and starts to lag after some time. So for e.g. if I move the sensor, I see the response 5 seconds later. I used Serial Plotter in Arduino (which has much less specifications than my laptop) but it is able to plot real-time data without any delays / problems.
My code looks a bit like the following
IMUData = nan(1500,6);
InterfaceObject = tcpip('my_ip_address',50001);
InterfaceObject.BytesAvailableFcn ={#PlotSensorData};
And the PlotSensorData function looks like
function PlotSensorData(~,~)
RecievedData = fscanf(InterfaceObject,'%s');
Identifier = RecievedData(6); % 6th byte is the sensor identifier
DataStartIdx = 28; % For each sensor, data start position is common
if Identifier == 'I'
DataEndIdx = DataEndPosition(RecievedData, 1);
SlicedData = RecievedData(DataStartIdx:DataEndIdx);
ParsedData = textscan(SlicedData,'%f', 'Delimiter',',');
% Append new data to IMUData matrices
prevval = IMUData;
val = [prevval(2:end,:); ParsedData{1}'];
IMUData = val;
set(PlotHandle{1},'ydata',val(:,3));
set(TopAxes,'ylim',[-15 15]);
drawnow limitrate;
end
end
Also, instead using plot, I have already tried animatedLine. It seems faster initially as it plots very fast, but after sometime, it starts to lag as well and the lag is more than 10 Sec.
So my questions are
What can be done to speed up the real-time data in MATLAB.
Also, I have already tried plotting the data after a certain number of samples (say 10, 20) are received instead of plotting after every received sample, but the results are still lagging and the GUI hangs as well. Is there any other strategy that I can use? In Python I used Multi-threading, but can I use it here as well? Or is there a better approach to handle this data rate?
I understand that Arduino is only running one script but the computer has a lot of overhead, but how is Arduino able to plot the data so fast while MATLAB just hangs up?
Thanks
Reading Data Asynchronously instead of continuously solved my problem.

Digital Output Using NI BNC-2110 connect to NI USB-6255

I currently have NI BNC-2110 connect to the NI USB-6255 which is then connected to my computer.
My goal is to generate a digital output through the NI BNC-2110 and then read the output on an analog input on the same NI BNC-2110. (The purpose of this is to make sure that I know how to properly output a digital signal and can input an analog signal, and I figured this would just check both things simultaneously.)
The setup works when generating a digital signal and reading an analog when I use the software NI MAX, my problem is when I try and do the same thing in Matlab.
Here is my current code in Matlab:
d = daq.getDevices
s = daq.createSession('ni');
addAnalogInputChannel(s,'dev1', 'ai0', 'Voltage');
s.Rate = 8000;
q = daq.createSession('ni');
addDigitalChannel(q,'dev1','Port2/Line0:0','OutputOnly');
for p = 1:1:100
outputSingleScan(q,1)
pause(0.1)
data = s.inputSingleScan;
data
outputSingleScan(q,0)
pause(0.1)
data = s.inputSingleScan;
data
end
My current results are an analog input of ~0 Volts, and what I expect is a square wave from my analog input.
Any help on this would be much appreciated.
I am expecting something with a syntax in Matlab with port to be the problem, but not to sure.

How can I reuse the same neural network to recreate the same results I had while training/creating the network?

I just trained a neural network, and I would like to test it with a new data set that were not included in the training so as to check its performance on new data. This is my code:
net = patternnet(30);
net = train(net,x,t);
save (net);
y = net(x);
perf = perform(net,t,y)
classes = vec2ind(y);
where x and t are my input and target, respectively. I understand that save net and load net; can be used, but my questions are as follows:
At what point in my code should I use save net?
Using save net;, which location on the system is the trained network saved?
When I exit and open MATLAB again, how can I load the trained network and supply new data that I want to test it with?
Please Note: I have discovered that each time I run my code, it gives a different output which I do not want once I have an acceptable result. I want to be able to save the trained neural network such that when I run the code over and over again with the training data set, it gives the same output.
If you just call save net, all your current variables from the workspace will be saved as net.mat. You want to save only your trained network, so you need to use save('path_to_file', 'variable'). For example:
save('C:\Temp\trained_net.mat','net');
In this case the network will be saved under the given file name.
The next time you want to use the saved pre-trained network you just need to call load('path_to_file'). If you don't reinitialize or train this network again, the performance will be the same as before, because all weights and bias values will be the same.
You can see used weights and bias values by checking variables like net.IW{i,j} (input weights), net.LW{i,j} (layer weights) and net.b{i} (bias). As long as they stay the same, the network's performance stay the same.
Train and save
[x,t] = iris_dataset;
net = patternnet;
net = configure(net,x,t);
net = train(net,x,t);
save('C:\Temp\trained_net.mat','net');
y = net(x);
perf = perform(net,t,y);
display(['performance: ', num2str(perf)]);
It returns performance: 0.11748 in my case. The values will be different after each new training.
Load and use
clear;
[x,t] = iris_dataset;
load('C:\Temp\trained_net.mat');
y = net(x);
perf = perform(net,t,y);
display(['performance: ', num2str(perf)]);
It returns performance: 0.11748. The values will be the same when using the network on the same data set. Here we used the training set again.
If you get an absolutely new data set, the performance will be different, but it will always be the same for this particular data set.
clear;
[x,t] = iris_dataset;
%simulate a new data set of size 50
data_set = [x; t];
data_set = data_set(:,randperm(size(data_set,2)));
x = data_set(1:4, 1:50);
t = data_set(5:7, 1:50);
load('C:\Temp\trained_net.mat');
y = net(x);
perf = perform(net,t,y);
display(['performance: ', num2str(perf)]);
It returns performance: 0.12666 in my case.

Matlab session-based interface: rapidly update analog output

I would like to control a piezo driven z-stage (for microscopy) through a simple analog output (0-10V) by using a NI DAQ board and the Matlab session-based interface. This works so far but I need to dynamically update the z-postion very rapidly (best under 20 ms). However queuing and executing an updated voltage value takes over 150 ms right now. Is there any way to optimize this? Thanks!
Here is my code:
%% initialize DAQ, specify output channels and refreshrate
devices = daq.getDevices
s = daq.createSession('ni');
s.addAnalogOutputChannel('Dev1', 'ao0', 'Voltage');
s.Rate = 1000; %1ms refreshrate
%define output data (I only define one data point as DAQ board keeps that voltage until changed)
zVol = 4.8; % range of stage is 100 um => 10um/V
%Queue output data
s.queueOutputData(zVol);
%output signal
s.startBackground();

Can you synchronize the data acquisition toolbox and the image acquisition toolbox of Matlab?

I'd like to simultaneously get data from a camera (i.e. an image) and an analog voltage using matlab. For the camera I use the imaq toolbox, for reading the voltage I use the daq toolbox (reading NI-USB device), with a following code:
clear all
% Prepare camera
vid = videoinput('gentl', 1, 'Mono8');
src = getselectedsource(vid);
vid.FramesPerTrigger = 1;
vid.TriggerRepeat = Inf;
triggerconfig(vid, 'hardware', 'DeviceSpecific', 'DeviceSpecific');
src.FrameStartTriggerMode = 'On';
src.FrameStartTriggerActivation = 'RisingEdge';
% prepare DAQ
s=daq.createSession('ni');
s.addAnalogInputChannel('Dev1','ai1','Voltage');
fid = fopen('log.txt','w');
lh = s.addlistener('DataAvailable',#(src,event)SaveData(fid,event));
s.IsContinuous = true;
% Take data
s.startBackground();
start(vid)
N=10;
for ii=1:N
im(:,:,ii)=getsnapshot(vid);
end
% end code
delete(lh );
fclose('all');
stop(vid)
delete(vid)
where the function SaveData is:
function SaveData(fid,event)
time = event.TimeStamps;
data = event.Data;
fprintf(fid, '%f,%f\n ', [time data]);
end
I do get images and a log.txt file with the daq trace (time and data), but how can I use the external triggering (that trigger the camera) or some other clock to synchronize the two?
For this example, the daq reads the camera triggering TTL signal (# 50 Hz), so I want to assign each TTL pulse to an image.
Addendum:
I've been searching and have found a few discussions (like this one) on the subject, and read the examples that are found in the Mathworks website, but haven't found an answer. The documentation shows how to Start a Multi-Trigger Acquisition on an External Event, but the acquisition discussed is only relevant for the DAQ based input, not a camera based input (it is also working in the foreground).
This will not entirely solve your problem, but it might be good enough. Since the synchronization signal you are after in at 50 Hz, you can use clock in order to create time stamps for both types of your data (camera image and analog voltage). Since the function clock takes practically no time (i.e. below 1e-7 sec), you can try edit to your SaveData function accordingly:
fprintf(fid, '%f,%f\n ', [clock time data]);
And in the for loop add:
timestamp(i,:)=clock;
Can you use the sync to trigger the AD board? From the USB-6009 manual...
Using PFI 0 as a Digital Trigger--
When an analog input task is defined, you can configure PFI 0 as a digital trigger input. When the digital trigger is enabled, the AI task waits for a rising or falling edge on PFI 0 before starting the acquisition. To use AI Start Trigger (ai/StartTrigger) with a digital source, specify PFI 0 as the source and select a rising or falling edge.
My experience suggests that delay between trigger and AQ is very short
I'm sorry I use Python or C for this, so I can't give you MatLab code, but you want to look at functions like.
/* Select trigger source */
Select_Signal(deviceNumber, ND_IN_START_TRIGGER, ND_PFI_0, ND_HIGH_TO_LOW);
/* specify that a start trigger is to be used */
DAQ_Config(deviceNumber, startTrig, extConv); // set startTrig = 1
/* start the acquisition */
DAQ_Start(deviceNumber, …)
If you want to take this route you could get more ideas from:
http://www.ni.com/white-paper/4326/en
Hope this helps,
Carl
This is yet no complete solution, but some thoughts that might be useful.
I do get images and a log.txt file with the daq trace (time and data), but how can I use the external triggering (that trigger the camera) or some other clock to synchronize the two?
Can you think of a way to calibrate your setup? I.e. modify your experiment and create a distinct event in both your image stream and voltage measurements, which can be used for synchronization? Just like this ...