Saving data of command window from callback function
Mostra commenti meno recenti
Hi guys,
I am using a callback function which reads a characteristic of a bluetooth module to achieve high sampling frequency. But since I am now using callback function I am not able to store the data as I wish. I can display it and see it in the command window but I want it as variables in the workspace. How can I achieve that?
Right know I just see my values in the command window and am not able to store it in workspace.
%% Setup connection
bt = ble("RN4871-BT_C719");
c = characteristic(bt,"59C88760-5364-11E7-B114-B2F933D5FE66","0F300FD5-78CD-4449-8865-A84136B8A286");
%% read values
tic;
c.DataAvailableFcn = @displayCharacteristicData;
%%
unsubscribe(c);
%% callback function
function displayCharacteristicData(src,~)
data = read(src,'oldest');
disp(data);
toc;
end
When I tried this I got the error message that there it could not find the variable "i"
%% Setup connection
bt = ble("RN4871-BT_C719");
c = characteristic(bt,"59C88760-5364-11E7-B114-B2F933D5FE66","0F300FD5-78CD-4449-8865-A84136B8A286");
%%
s = 1000;
i = 1;
t = zeros(1,s);
v1 = zeros(1,s);
v2 = zeros(1,s);
tic;
c.DataAvailableFcn = @displayCharacteristicData;
%%
unsubscribe(c);
%%
function displayCharacteristicData(src,~)
data = read(src,'oldest');
v1(i)=data(1);
v2(i)=data(2);
t(i)=toc;
i=i+1;
end
1 Commento
Mathieu NOE
il 22 Gen 2021
hello
is there any reason why data cannot be output of your function ?
function data = displayCharacteristicData(src,~)
Risposte (1)
Jan
il 22 Gen 2021
function data = displayCharacteristicData(src,~, Flush)
persistent Store
if isempty(Store)
Store = struct('v1', [], 'v2', [], 't', []);
end
if nargin == 3
data = Store;
Store = [];
end
data = read(src,'oldest');
i = numel(Store.v1) + 1;
Store.v1(i) = data(1);
Store.v2(i) = data(2);
Store.t(i) = toc;
end
Now the data are collected persistently inside the callback and flushed, of you call the callback with 3 inputs.
Note that this let the Struct grow iteratively, which consumes a lot of ressources. A smarter method would be to increase the size in steps and crop them finally:
function data = displayCharacteristicData(src,~, Flush)
persistent Store
if isempty(Store)
Store = struct('v1', zeros(1, 1000), 'v2', zeros(1, 1000), 't', zeros(1, 1000), 'count', 0);
end
if nargin == 3
data = Store;
Store = [];
end
data = read(src,'oldest');
count = Store.count + 1;
if count > numel(Store.v1)
Store.v1(count + 1000) = 0;
Store.v2(count + 1000) = 0;
Store.vt(count + 1000) = 0;
end
Store.v1(count) = data(1);
Store.v2(count) = data(2);
Store.t(count) = toc;
Store.count = count;
end
I'd use clock instead of tic/toc.
6 Commenti
Sakin Sivakurunathar
il 22 Gen 2021
Jan
il 23 Gen 2021
Then define a further function as so called wrapper:
function displayCharacteristicData_CB(src, event)
displayCharacteristicData(src, event);
end
Now the callback has its function with 2 inputs, while the data collection is done inside your function, which can flush the data on demand.
Joris Lambrecht
il 5 Feb 2021
I don't understand this either.
With timer and serial callbacks you can add input arguments to the callback function. In this simple example the Line object is passed to the timercallback to change the data plotted
t = timer;
t.BusyMode = 'drop';
t.ExecutionMode = 'fixedRate';
t.TasksToExecute = 10;
t.Period = 1;
p = plot(0:10, 0:10);
axis([0 10 0 100])
t.TimerFcn = {@myTimerCallback, p};
%%
start(t)
%%
function myTimerCallback(obj, evt, p)
p.YData = p.YData+1;
end
In AppDesigner, I can also use
%app.p is a property defined elsewhere in the app
t.TimerFcn = @app.myTimerCallback;
%%
function myTimerCallback(app, obj, event)
app.p.YData = app.p.YData+1;
end
I figured for the ble notification callback, c.DataAvailableFcn should be able to replace t.TimerFcn above but I get the same error as @Sakin Sivakurunathar:
Invalid value for DataAvailableFcn. Specify [] or a function handle that accepts two inputs.
I can accomplish getting the Line Object into the callback by using a global variable but that is something I try to avoid.
@Jan, in your wrapper example, both the wrapped and wrapper function have the same inputs so how does this actually help getting outside data into the callback without using a global variable. I would like to implement the ble notification callback in AppDesigner, so I need to be able to pass the app argument in order for the callback to be able to update UI elements within the app from the callback.
David Schönfisch
il 17 Feb 2021
I had the same problem when using the BLE subscrition callback with AppDesigner.
Here's how I solved it:
% Definition of the function to callback
function displayCharacteristicData(app, src)
Data = read(src,'oldest');
disp(Data)
end
% Passing of the callback function elsewhere in the app
app.c.DataAvailableFcn = @(obj,event)app.displayCharacteristicData(obj);
Joris Lambrecht
il 17 Feb 2021
Sakin Sivakurunathar
il 21 Feb 2021
Categorie
Scopri di più su App Building in Centro assistenza e File Exchange
Prodotti
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!