How to use MATLAB to control an endless python script on Raspberry Pi using a TCP connection?

6 visualizzazioni (ultimi 30 giorni)
I have a Raspberry Pi model 2 B running Raspbian 11 (bullseye) on which my python script is regulating the voltage of a power supply, therefore running in a while loop for as long as the experiments last. I want to initialize this "instrument" from a MATLAB script and be able to send messages to the Raspberry Pi throughout the experiment. So far, I have the MATLAB Support Package for Raspberry Pi Hardware and the Instrument Control Toolbox installed. I use
r = raspi('ip_RPi','username','password');
to connect to the Pi, and then I start a tcp server with
t = tcpserver('ip_Computer',4000);
The python script connects to the server using socket.socket(). Now, I want to start the script on the Raspberry Pi using the 'system' function:
system(r,['export DISPLAY=:0' ' ; ' '~/.venv/Controller/bin/python3 ~/Controller/main.py &']);
The Raspberry Pi has a display and main.py starts a gui, therefore I export 'DISPLAY=:0' to show the gui on the Raspberry Pi screen. When ssh'ing into the Pi and running the script from terminal everything works.
The issue I'm having is that the '&' symbol in the system-call does not result in the MATLAB script to continue, instead it is busy until the script is no longer running. But since the script is not supposed to stop, I never reach the part of my MATLAB script where I read and write to the client using functions like:
function setT(tcp,T)
L = strcat('t ',string(T));
write(tcp,L);
end
I have looked into the batch function from the Parallel Computing Toolbox in order to run something like:
j = batch('init2',0,{r,['export DISPLAY=:0' ' ; ' '~/.venv/Controller/bin/python3 ~/Controller/main.py &']});
with the init2.m script:
function init2(r,command)
system(r,command);
end
I get this error message, however:
> j
j =
Job
Properties:
ID: 31
Type: independent
Username: leouh
State: finished
SubmitDateTime: 25-Apr-2022 13:50:25
StartDateTime: 25-Apr-2022 13:50:38
Running Duration: 0 days 0h 0m 4s
NumThreads: 1
AutoAttachFiles: true
Auto Attached Files: List files
AttachedFiles: {}
AutoAddClientPath: true
AdditionalPaths: 27 paths
Associated Tasks:
Number Pending: 0
Number Running: 0
Number Finished: 1
Task ID of Errors: [1]
Task ID of Warnings: [1]
Task with properties:
ID: 1
State: finished
Function: @parallel.internal.cluster.executeFunction
Parent: Job 31
StartDateTime: 25-Apr-2022 13:50:38
Running Duration: 0 days 0h 0m 3s
Error: Undefined function 'execute' for input arguments of type 'double'.
Error Stack: init2 (line 3)
Warnings: List warnings
>> diary(j)
--- Start Diary ---
Warning: The following error was caught while executing 'onCleanup' class destructor:
Undefined function 'dataIntegrate' for input arguments of type 'string'.
Error in raspi.internal.DataUtilityHelper/dataIntegrateAll
Error in raspi>@()dataIntegrateAll(obj,obj.RaspiImpl.DataUtility,true) (line 1220)
c = onCleanup(@() dataIntegrateAll(obj, obj.RaspiImpl.DataUtility, true));
Error in onCleanup/delete (line 80)
obj.task();
Error in raspi/processInternal (line 1218)
try
Error in raspi/system (line 193)
output = processInternal(obj, false, false, varargin{:});
Error in init2 (line 3)
system(r,command);
Error in parallel.internal.cluster.executeFunction (line 31)
feval(fcn, fcnArgsIn{:});
Error in parallel.internal.evaluator.evaluateWithNoErrors (line 16)
feval(fcn, args{:});
Error in parallel.internal.evaluator.CJSStreamingEvaluator/evaluate (line 41)
[out, errOut] = parallel.internal.evaluator.evaluateWithNoErrors( fcn, nOut, args );
Error in dctEvaluateTask>iEvaluateTask/nEvaluateTask (line 377)
[output, errOutput, cellTextOutput{end+1}] = evaluator.evaluate(fcn, nOut, args);
Error in dctEvaluateTask>iEvaluateTask (line 175)
nEvaluateTask();
Error in dctEvaluateTask (line 81)
[resultsFcn, taskPostFcn, taskEvaluatedOK, isAsyncTask] = iEvaluateTask(job, task, runprop);
Error in distcomp_evaluate_filetask_core>iDoTask (line 154)
dctEvaluateTask(postFcns, finishFcn);
Error in distcomp_evaluate_filetask_core (line 52)
iDoTask(handlers, postFcns);
> In raspi/processInternal (line 1218)
In raspi/system (line 193)
In init2 (line 3)
In parallel.internal.cluster.executeFunction (line 31)
In parallel.internal.evaluator.evaluateWithNoErrors (line 16)
In parallel.internal.evaluator/CJSStreamingEvaluator/evaluate (line 41)
In dctEvaluateTask>iEvaluateTask/nEvaluateTask (line 377)
In dctEvaluateTask>iEvaluateTask (line 175)
In dctEvaluateTask (line 81)
In distcomp_evaluate_filetask_core>iDoTask (line 154)
In distcomp_evaluate_filetask_core (line 52)
--- End Diary ---
>>
I have tried to print the module 'r' in the init2.m script:
function init2(r,command)
r
system(r,command);
end
And I get the following output:
>> diary(j)
--- Start Diary ---
r =
raspi with properties:
DeviceAddress: ''
Port:
BoardName: ''
AvailableLEDs: {}
AvailableDigitalPins: []
AvailableSPIChannels: {}
AvailableI2CBuses: {}
AvailableWebcams: {}
I2CBusSpeed:
Supported peripherals
along with the same error message as before. It seems to me that the raspi module is not properly passed to the function. The function correctly runs if I just do
init2(r,['export DISPLAY=:0' ' ; ' '~/.venv/Controller/bin/python3 ~/Controller/main.py &'])
but then I still have the issue that MATLAB is busy until main.py is no longer running.
Do you have any suggestions on what I can do to make either the system() with '&' or the batch() work? Or other possible solutions to the issue that MATLAB is busy until the python script has finished?
Thank you in advance!
  2 Commenti
Leo Uhre Jakobsen
Leo Uhre Jakobsen il 25 Apr 2022
Here is the main.py script:
% python packages
import threading
% our scripts
import ui
import loop
import globals
globals.initialize_variables()
% create threads
ui_thread = ui.ui()
main_loop_thread = loop.loop()
% start threads
ui_thread.start()
main_loop_thread.start()
exit()
I have used % instead of # here for the syntax to be correct with the code input syntax
Alvaro
Alvaro il 22 Dic 2022
Modificato: Alvaro il 22 Dic 2022
Based on Walter's answer, your use of & should allow your call to return while the processing continues on your Raspberry Pi.
Have you tried printing a message or doing some other check on your Raspberry Pi while executing that script in the background?
Alternatively, the asker in that question does not use the & when calling batch. This should send the calling process to a MATLAB worker in the background of your client but not your Pi.

Accedi per commentare.

Risposte (0)

Community Treasure Hunt

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

Start Hunting!

Translated by