MATLAB Answers

Is it possible to control two Arduino boards in parallel using parfor?

3 views (last 30 days)
junchul kim
junchul kim on 10 May 2021
Edited: Edric Ellis on 12 May 2021
Hi,
I am trying to control two Arduino boards in parallel (not serially) with one matlab script. I was hoping to achieve this by creating two Arduino objects and running the parallel for-loop, but when I try the script below, I get the following error:
"Error using writeDigitalPin(a, "D13", 1). Dot indexing is not supported for variables of this type."
I suspect that the parfor automatically creates and uses dot indexing, which may not be compatible with Arduino object.
Any help will be much appreciated.
Thanks.
a = arduino('/dev/tty.usbmodem141301','UNO');
b = arduino('/dev/tty.usbmodem141401','UNO');
ProtocolList = {@protocol1, @protocol2};
BoardList = {a,b};
Datalist = cell(1,2);
% use of parfor
parfor k = 1:2
Datalist{k}=ProtocolList{k}(BoardList{k});
end
function out = protocol1(a)
data = {};
t0 = clock;
tic
while toc < 3
writeDigitalPin(a, "D13", 1); % turn on LED
pause(1)
writeDigitalPin(a, "D13", 0);
pause(1)
data = vertcat(data,{round(etime(clock,t0) * 1000)})
end
out = data;
end
function out = protocol2(a)
data = {};
tic
t0 = clock;
while toc < 3
writeDigitalPin(a, "D13", 1); % turn on LED
pause(1)
writeDigitalPin(a, "D13", 0);
pause(1)
data = vertcat(data,{round(etime(clock,t0) * 1000)})
end
out = data;
end

Answers (2)

Walter Roberson
Walter Roberson on 11 May 2021
The arduino object data is not being copied to the workers.
Use parfevalOnAll to run an initialization on each worker that creates an arduino object and stores a reference to it .
However, when devices are being run in parallel, it is most common that one needs data from both of them, or needs data from one to influence what is done with the other. In such a case you should be considering using spmd instead of parfor, so that you can communicate between workers using labSend() and labReceive()
  2 Comments
Walter Roberson
Walter Roberson on 11 May 2021
https://www.mathworks.com/matlabcentral/answers/30294-identifying-lab-id-within-a-parfor#answer_38822
shows how to identify a worker. You can use that to index the filenamesof the ports to figure out which one to open. Then parfevalOnAll passing in the handle of a function that will do the open and store the object.

Sign in to comment.


Edric Ellis
Edric Ellis on 11 May 2021
Edited: Edric Ellis on 12 May 2021
As @Walter Robersonpoints out, you need to create the arduino objects directly on the workers. Rather than using parfevalOnAll though, I'd recommend using parallel.pool.Constant which is designed exactly for this sort of thing. In this case, things are slightly awkward because each worker needs a slightly different argument when building the arduino object, so we defer to a simple function that switches on the task ID from getCurrentTask. You can use a Constant to both initialize and access the data, like this:
parpool('local',2);
arduinoPorts = {'/dev/tty.usbmodem141301', '/dev/tty.usbmodem141401'};
% The following line runs the function separately on each worker
% and stores the result so that it can be accessed using 'board.Value' on a
% worker. Note that we pass in all the arduinoPorts, and the function
% buildArduinoForWorker selects the right one to use.
board = parallel.pool.Constant(@() buildArduinoForWorker(arduinoPorts));
% Next, use parfor (or you could use spmd, or even parfeval)
parfor k = 1:2
% Get the underlying 'arduino' object on this worker
thisBoard = board.Value;
% Do whatever with that
Datalist{k}=ProtocolList{k}(thisBoard);
end
%%%
function board = buildArduinoForWorker(arduinoPorts)
t = getCurrentTask();
id = t.ID;
board = arduino(arduinoPorts{id}, 'UNO');
end
  2 Comments
Edric Ellis
Edric Ellis on 12 May 2021
Argh doh, quite right, I didn't spot that. Thanks for pointing that out. There are a couple of ways around that. I still prefer to use parallel.pool.Constant for this sort of thing though - you just need to write a tiny function to build the right arduino based on the task index (unfortunately this approach is not compatible with parpool("threads")). I'll update my answer...

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!