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

6 vues (au cours des 30 derniers jours)
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 commentaires
Leo Uhre Jakobsen
Leo Uhre Jakobsen le 25 Avr 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 le 22 Déc 2022
Modifié(e) : Alvaro le 22 Déc 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.

Connectez-vous pour commenter.

Réponses (0)

Community Treasure Hunt

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

Start Hunting!

Translated by