Saving data of command window from callback function
古いコメントを表示
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 件のコメント
Mathieu NOE
2021 年 1 月 22 日
hello
is there any reason why data cannot be output of your function ?
function data = displayCharacteristicData(src,~)
回答 (1 件)
Jan
2021 年 1 月 22 日
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 件のコメント
Sakin Sivakurunathar
2021 年 1 月 22 日
Jan
2021 年 1 月 23 日
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
2021 年 2 月 5 日
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
2021 年 2 月 17 日
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
2021 年 2 月 17 日
Sakin Sivakurunathar
2021 年 2 月 21 日
カテゴリ
ヘルプ センター および File Exchange で App Building についてさらに検索
製品
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!