Issues setting exact sampling rates when using the data acquisition toolbox in MATLAB’s app designer
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 = ”;
endHi 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 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 data acquisition, toolbox, graph, callback, appdesigner, app designer MATLAB Answers — New Questions