Using parallel computing to communicate with device

10 ビュー (過去 30 日間)
John Whalen
John Whalen 2025 年 6 月 21 日
コメント済み: Edric Ellis 2025 年 6 月 26 日
Could use some help on this one. I have a scale (and more devices to come later) that I'd like to read often and periodically to get a near live reading of the weight of an object. I'm looking to offload the constant reading of the scale to another worker on the pool (and later a few more devices on other workers). Below I have simplified the code to try and debug but have hit a wall.
I first create an instance of the scale class. I connect to the scale via bluetooth (this works fine / I've communicated with the scale numerous times without parallel computing). Setup for parallel processing, setup a timer to call a function in another worker but where things go awry is that the scale class and all of its contents does not go to the other worker. I've tried to pass this in as an argument to the function and as a constant in the parallel pool to no avail.
I would imagine I'm not the only one who wants to rapidly and constantly status instruments / devices for status and needs to offload this to a free worker. Any help would greatly be appreciated
function parallel_const_pull_func()
% Establish Communication with Scale
Scale = ScaleClass;
Scale.com = bluetooth("SCALE");
% Setup Pool
Scale_Const = parallel.pool.Constant(Scale);
pool = parpool;
% Setup Parallel Function
F = parfeval(backgroundPool,@UpdateWeight,1,Scale);
% Setup Timer
scale_timer = timer('TimerFcn',{@(~,~)F,'Scale'}, ...
'ExecutionMode','fixedSpacing','Period',1,'BusyMode','drop','Name','Scale Timer','TasksToExecute',10);
% Start Background Task
start(scale_timer);
% Mindless Foreground Task
pause(1);
for idx = 1:100, fprintf("Number: %d - ",idx); pause(0.1); end
y = fetchOutputs(F);
disp(y);
% Clean Up
stop(scale_timer);
delete(scale_timer);
delete(pool);
end
function weight = UpdateWeight(scale)
device = Scale_Const;
writeline(device.com,"W?"); % Get Weight
weight = strtrim(readline(device.com));
disp(weight);
end

回答 (2 件)

Walter Roberson
Walter Roberson 2025 年 6 月 21 日
F = parfeval(backgroundPool,@UpdateWeight,1,Scale);
F is returned as a future object.
% Setup Timer
scale_timer = timer('TimerFcn',{@(~,~)F,'Scale'}, ...
'ExecutionMode','fixedSpacing','Period',1,'BusyMode','drop','Name','Scale Timer','TasksToExecute',10);
Your anonymous function created in the TimerFcn evaluates the future, and does nothing with the future.
Setup for parallel processing, setup a timer to call a function in another worker
It is not possible to call a function that lives in another worker.
for idx = 1:100, fprintf("Number: %d - ",idx); pause(0.1); end
With the idx iterating with a delay of about 0.1, each 10 idx iterations would correspond to one firing of the timer.
weight = strtrim(readline(device.com));
Each call to UpdateWeight (if somehow it were to get called) would return a single line from the scale.
y = fetchOutputs(F);
You clearly expect the fetchOutputs to collect all 10 outputs of UpdateWeight() calls. But it doesn't work that way. The parfeval() execution ends as soon as the @UpdateWeight returns once -- so there would be only a single accumulated line of output.
  1 件のコメント
Walter Roberson
Walter Roberson 2025 年 6 月 21 日
If you must execute the communication on a different worker, then set up the worker to be called exactly once, after having created a Dataqueue https://www.mathworks.com/help/parallel-computing/parallel.pool.dataqueue.html . Use afterEach() in the main thread to collect each element sent to the dataqueue. Set up the worker to loop repeatedly fetching data from the scale and writing the result to the dataqueue; then if you are not at the final iteration, pause()

サインインしてコメントする。


Edric Ellis
Edric Ellis 2025 年 6 月 25 日
Firstly, I wonder if you should be using the function-handle constructor to make the parallel.pool.Constant, like this:
Scale_Const = parallel.pool.Constant(@buildScale);
% with the following helper function:
function out = buildScale()
out = ScaleClass();
out.com = bluetooth("SCALE");
end
This stops MATLAB having to copy the ScaleClass instance to the worker, and instead builds it directly there. This can often help with things like connections to remote resources. Similar to @Walter Roberson's suggestion in the comment, I would then proceed like this using a DataQueue to receive the periodic results.
q = parallel.pool.DataQueue(); % receives periodic results
ae_fut = afterEach(q, @(result) disp(result)); % or whatever with the results
read_fut = parfeval(backgroundPool, @readScaleLoop, 0, q, Scale_Const);
% do more stuff on the client
% Then, when you've had enough, simply cancel "read_fut"
cancel(read_fut);
% with the following:
function readScaleLoop(q, Scale_Const)
while true
device = Scale_Const.Value; % must get the "Value" field out of the parallel.pool.Constant
writeline(device.com,"W?"); % Get Weight
weight = strtrim(readline(device.com));
send(q, weight); % send the result back to the client
pause(1);
end
end
  2 件のコメント
Walter Roberson
Walter Roberson 2025 年 6 月 25 日
Scale_Const = parallel.pool.Constant(@buildScale);
There is the disadvange that parallel.pool.Constant executes the given function handle on each worker. That would try to make the bluetooth connection on each worker individually, which is likely to cause problems.
You kind of want to be able to create the object on only a single worker, and then later specify the same worker is to do the looping. Unfortunately, the methods of selecting a particular worker to do work on, are pretty ugly.
You would need to do something like parfeval() copying in a DataQueue, and then parfevalOnAll code that checks to see whether the DataQueue exists and if not exits, and loops doing real work on the one remaining worker.
Edric Ellis
Edric Ellis 2025 年 6 月 26 日
Good point about the object being created in places where it isn't needed. If continuing down the path of a long-running parfeval running something like readScaleLoop, I would modify that to simply build the object directly in the body of that function, i.e.
function readScaleLoop(q)
device = bluetooth("SCALE");
while true
writeline(device, "W?");
% etc.
end
end

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeParallel Computing Fundamentals についてさらに検索

製品


リリース

R2025a

Community Treasure Hunt

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

Start Hunting!

Translated by