Take Discrete DAQ sample while doing Continuous Sampling

7 views (last 30 days)
Hello,
I am doing a background sampling of a DAQ USB6003 in Matlab. What I need to do is periodically pull the latest data point from the background sampling. However, when I try to do this using the "read" function during the background sessions, I get the error:
Error using roboAnterograde_speedStop (line 159)
NI Error -50103:
The specified resource is reserved. The operation could not be completed as specified.
Task Name: _unnamedTask<3FF>
Status Code: -50103
I also tried creating a second DAQ object with only the channel added that I need to continously check during the background sesions and it also doesn't work.
So, does anyone have a good way to pull the latest data points during the background sampling without stopping the sampling?
Hopefully this makes sense.
Thank you

Answers (3)

akshatsood
akshatsood on 17 Sep 2024
Edited: akshatsood on 17 Sep 2024
I see that you are performing a background sampling of a DAQ USB6003 in MATLAB and you need to periodically pull the latest data point from the background sampling.
The error you are encountering, "NI Error -50103", indicates that the resource is reserved, meaning that the DAQ device is already in use by another task. This is a common issue when attempting to access the same DAQ device from multiple tasks simultaneously.
Here are a few strategies you can try to resolve this issue and periodically access the latest data points:
Use a Listener to Access Data - MATLAB allows you to set up a listener that can be triggered whenever new data is available. This approach avoids directly accessing the DAQ device while it is in use.
s = daq.createSession('ni'); % Create a DAQ session
addAnalogInputChannel(s, 'Dev1', 'ai0', 'Voltage');
s.Rate = 1000; % 1000 Hz
s.DurationInSeconds = 10;
% Add a listener for DataAvailable event
lh = addlistener(s, 'DataAvailable', @(src, event) processData(event));
function processData(event)
latestData = event.Data(end, :); % Get the latest data point
disp(latestData);
end
s.startBackground();
Use a Circular Buffer - Implement a circular buffer to store the latest data points and access them as needed. This approach can be combined with the listener method.
bufferSize = 1000;
circularBuffer = zeros(bufferSize, 1);
bufferIndex = 1;
function processData(event)
global circularBuffer bufferIndex bufferSize;
data = event.Data;
numDataPoints = size(data, 1);
for i = 1:numDataPoints
circularBuffer(bufferIndex) = data(i);
bufferIndex = mod(bufferIndex, bufferSize) + 1;
end
% Access the latest data point
latestData = circularBuffer(mod(bufferIndex - 2, bufferSize) + 1);
disp(latestData);
end
Please refer to the following MATLAB Answer for better understanding
I hope this helps.

Holden
Holden on 18 Sep 2024
Thanks for the info.
It seems like I should be able to get away with a simpler solution such as just calling the "read" function during the background acquisition. They do that in the example code on the documentation. In my code below, I first start the continuous acquisition, and then the underlined code lines have to do with the discrete calls. What is very odd is that by the end of the while loop, the variable 'cnt' which increases for every iteration of the while loop is at ~300, whereas the variable 'spot' only is at around 80. They should be the same number by the end. Is it because the discrete "read" command is slow and cannot keep up with the while loop perhaps?
% Start Continuous Data Sampling
start(d2,"Continuous"); % start analog channels
disp('Start');
sampling = true; % boolean that sampling is running
cnt = 1; % initialize for logging Zaber position
timerStart= tic; % start of timer for when position is logged
% Initialize for Movement
begin = 1;
moving = true;
% On the fly data
dataHold = [];
timestampsHold = [];
spot = 1;
% Forward Peck
while (moving == true)
posTime(cnt) = toc(timerStart);
pos(cnt) = axis.getPosition(Units.LENGTH_MILLIMETRES);
if (begin == 1) % if on first iteration, perform movement
axis.moveRelative(travelDistance, Units.LENGTH_MILLIMETRES, false, travelSpeed, Units.VELOCITY_MILLIMETRES_PER_SECOND);
end
check = axis.isBusy(); % check if device is moving
if (check == false)
moving = false; % end sampling
end
cnt = cnt + 1; % increase count
begin = begin + 1;
[dataTemp, timestampsTemp] = read(d2,1,OutputFormat="Matrix");
dataHold(spot) = dataTemp(2);
timestampsHold(spot) = timestampsTemp;
spot = spot + 1;
end
speedHold = dataHold(1,:)/5 * 220000; % convert to rpm
% Retrive Continuous Data
scanData = read(d2,"all"); % read data

Holden
Holden on 18 Sep 2024
For instance in the documentation for continuous background sampling, it states
start(d,"Continuous") starts the background operation running continuously. If there is data already available from the preload function, output generation begins immediately along with acquisition on any input channels. Otherwise, acquisition begins when you execute write. The operation continues until you call stop. As output scan data is generated or input scan data is acquired, you might need to call write or read while the DataAcquisition is still running.
This seems to indicate that you should be able to read data while it is still scanning. Is it just not working for me because I am trying to call read too quickly perhaps?
  2 Comments
akshatsood
akshatsood on 23 Sep 2024
It sounds like the issue might indeed be related to the speed at which the "read" function is called. If the discrete "read" command is slower than the loop, it could cause the discrepancy between "cnt" and "spot". You might want to try adding a brief pause in the loop or optimizing the read process to ensure it can keep up with the loop iterations.
Holden
Holden on 23 Sep 2024
Hello,
It turns out adding a 10 [ms] pause after the read command did solve the issue, thank you!

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!