Issues setting exact sampling rates when using the data acquisition toolbox in MATLAB's app designer

7 views (last 30 days)
Hi all,
I have been having issues setting my sampling rate/ DAQ.Rate to the values 2048 and 120. I am using a start function that is set for x amount of seconds. This then triggers the scansavailablecallback and within this callback it will readout about 1 tenth of the values to be graphed out over time. When setting the DAQ's Rate to 2048 is collects in sample batches of 205, this leaves the sample batch for 0.9s to 1.0s missing 2 samples and does not end up triggering final 0.1s of the callback. I am not too sure why it does this and am wondering if using the scansavailable callback is part of the issue. I have tried to change the DAQ rate for the 0.9-1.0s time to then activate the callback again but this does not seem to work. A similiar issue happens for 120 where it's sample batch seems to be 13 which I am quite confused by. Any ideas or guidance on how to go about solving these issues would be greatly appreciated.
This is the callback function
function scansAvailable_Callback(app, src, ~)
% Callback function executed on DAQ object ScansAvailable event
% runs after the start button pushed event is complete
if ~isvalid(app)
return
end
disp (app.numscan)
% Read data from the DAQ object
% Read data from the DAQ object
[app.data, timestamps] = read(src,app.DAQ.ScansAvailableFcnCount, 'OutputFormat','Matrix');
test = [timestamps,app.data];
assignin("base","test",test)
% Calibration
if app.calibrate == true
% sends data to function to be calibrated appropriately
app.calibratedData = calibrateData(app,app.data, app.sl, app.int);
else
% if calibration is not turned off, just take the voltage values
for jj = app.SelectedChannels
app.calibratedData(:,jj) = (app.data(:,jj));
end
end
% checking too put the app back into configuration @ the end of the
% Store continuous acquisition data in FIFO data buffers
buffersize = round(app.DAQ.Rate * app.TimewindowEditField.Value) + 1;
app.TimestampsFIFOBuffer = storeDataInFIFO(app, app.TimestampsFIFOBuffer, buffersize, timestamps);
app.DataFIFOBufferch1 = storeDataInFIFO(app, app.DataFIFOBufferch1, buffersize, app.calibratedData(:,app.SelectedChannels));
% Plotting (Update the plot every N data points received
updatePlotInterval = 1; % Adjust this value based on your preference
if mod(src.ScansAvailableFcnCount, updatePlotInterval) == 0
% runs function that is responsible for plotting a singular
% graph
updateLivePlot(app);
end
% for data that goes to the workspace and
for ii = 1:(round(app.RateEdit.Value/10))
% keep count of the sample#/time
app.fws_x = app.fws_x + 1;
% initialize data to be written into the workspace
app.fwsdata(app.fws_x,(app.SelectedChannels)) = app.calibratedData(ii,app.SelectedChannels);
end
disp(app.fws_x)
if app.ContinuousSwitch.Value == "Off"
lengthcheck = (app.TrialLengthsEditField.Value* app.RateEdit.Value);
disp(lengthcheck)
if app.fws_x >= lengthcheck
if app.LogRequested
try
% Change the data to a timetable
WSData = array2timetable(app.fwsdata(1:app.TrialLengthsEditField.Value*app.DAQ.Rate,app.SelectedChannels),'SampleRate',app.RateEdit.Value);
varname = table2array(app.UITable.Data(:,1));
% renames the variable names to match the channel names
for i = app.SelectedChannels
WSData = renamevars(WSData,i,varname(i));
end
% write into base workspace with the name stated in the UI
assignin('base', app.VariableNameEditField.Value, WSData);
assignin("base","variable_name",app.VariableNameEditField.Value)
catch exception
uialert(app.LiveDataAcquisitionUIFigure,exception.message,'You cannot start the variable name with a number')
end
end
setAppViewState(app, 'configuration');
end
end
app.numscan = app.numscan + 1;
end
And the following is what initiates the callback
function StartButtonPushed(app, event)
% so the app can go back into "configuration state"
app.fws_x = 0;
app.fwsdata = 0;
app.wstimestamps= 0;
% clearing the graphs just helps with mainly tab 2 when the
% user is switching where a channels goes (between the 2
% graphs)
cla(app.LiveAxes)
if numel(app.SelectedChannels) == 0
warndlg('Please select Channels to record','No Channels to Record from Selected')
else
% dur = isinteger(app.DAQ.Rate/10);
% Disable DAQ device, channel properties, and start acquisition UI components
setAppViewState(app, 'acquisition');
% Reset FIFO buffer data
app.calibratedData = [];
app.DataFIFOBufferch1 = [];
app.TimestampsFIFOBuffer = [];
% Checks to see if the app is set to continuous or has a the
% User selected to use a recording window instead
if app.continuous == true
% preallocate for the data that is to be written for
% the workspace
app.fwsdata = zeros(400000,numel(app.numchan));
try
% starts data collection
start(app.DAQ,'continuous');
catch exception
% In case of error show it and revert the change
uialert(app.LiveDataAcquisitionUIFigure, exception.message, 'Start error, you may have selected channels too quick!');
setAppViewState(app, 'configuration');
end
else
% preallocate for the data that is to be written for
% the workspace based on the trial length and the
% sample rate
app.fwsdata = zeros((app.RateEdit.Value*app.TrialLengthsEditField.Value),numel(app.numchan));
try
start(app.DAQ,"Duration",app.TrialLengthsEditField.Value)
catch exception
% In case of error show it and revert the change
uialert(app.LiveDataAcquisitionUIFigure, exception.message, 'Start error');
setAppViewState(app, 'configuration');
end
end
% Clear Log status text
app.LogStatusText.Text = '';
end
  1 Comment
Connor
Connor on 28 May 2024
I ended up removing some things I had commented out but, Additionally I know that messing with the format of the reading in of the values could affect things aswell. I am also wondering if I change the callback/function of the ScansAvailable to a non-conditional callback, this might also work.

Sign in to comment.

Answers (1)

Ayush
Ayush on 17 Jun 2024
Hey Connor,
I understand that you are facing an issue with handling the final batch of data in your MATLAB application, particularly when the batch size doesn't align perfectly with the end of your data acquisition period. This can result in the last portion of data being missed or not processed as expected when using callback functions with a DAQ session. The challenge lies in ensuring that all data, including the final batch which may not fill up to the 'ScansAvailableFcnCount', is accurately captured and processed.
To address this, you can adjust your callback function to track the number of samples that have been processed and compare this against the expected total number of samples. This approach allows you to identify when you are processing the final batch of data and implement logic to handle this batch appropriately, regardless of its size. Here's how you can modify your callback function:
  1. Calculate the Expected Total Samples: Use the sampling rate and the duration of the acquisition to determine the total number of samples you expect to collect.
  2. Track Processed Samples: Maintain a count of how many samples have been processed so far during the data acquisition process.
  3. Handle the Final Batch: When you detect that the processed samples are about to reach the expected total, implement specific logic to handle this final batch, ensuring that no data is missed.
function scansAvailable_Callback(app, src, ~)
% Callback function executed on DAQ object ScansAvailable event
if ~isvalid(app)
return
end
% Calculate the expected number of samples based on rate and duration
expectedTotalSamples = app.DAQ.Rate * app.TrialLengthsEditField.Value;
% Read available data from the DAQ object
[app.data, timestamps] = read(src, src.ScansAvailableFcnCount, 'OutputFormat','Matrix');
test = [timestamps, app.data];
assignin("base", "test", test);
% Update the count of processed samples
app.numscan = app.numscan + src.ScansAvailableFcnCount;
% Check if this is potentially the last batch
if app.numscan >= expectedTotalSamples
% Logic to handle the final batch of data
disp('Final batch processed');
end
% Additional logic for processing data and stopping the acquisition if needed
end
For more detailed information on handling data acquisition in MATLAB, including working with callback functions and DAQ sessions,refer to the following MathWorks documentation link : https://in.mathworks.com/help/daq/
Hope this helps!
Regards

Categories

Find more on Data Acquisition Toolbox in Help Center and File Exchange

Products


Release

R2024a

Community Treasure Hunt

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

Start Hunting!