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!