Matlab: simulate command window input by a script - matlab

I need a way to execute a script in matlab from within another script. The tricky part is, that the first script is a while loop, which polls every 60 seconds for a new job. If a job is found (created by me), the main.m file should be called. Now, the problem is that I want to be able to modify main.m and all other functions while the while loop is already running. The loop looks something like this:
while run
- pause 60 seconds
- get jobs form text file on network drive
- run main(jobID)
- save result on network drive
end
I thought the eval command would do the trick. But it doesn't. I think Matlab compiles all functions that could be called during runtime as soon as I start my while loop. From then on I cant change anything without restarting the while loop. (I can change it but Matlab ignores all changes).
Is there a way around this problem? I thought there was a method of executing commands inside the command window, just as if a user had typed it. But I cant remember.

Amro's solution with rehash works perfectly. Matlab detects changes in m-files even when it's already running a script!

I think you may be able to do what you want with a timer object.
First create a main.m function to define and initialize your timer:
function main
% Create timer that calls the sub-function checkmfiles every 60 seconds
t = timer('TimerFcn', #checkmfiles, 'Period', 60, 'ExecutionMode', 'fixedRate');
start(t);
function checkmfiles(obj,events)
% Just a dummy function, you'll need to expand it to fit your needs
if exist(f1) == 2
disp('''f1.m'' found.');
eval('f1');
else
disp('No file found.');
end
The example above assumes that f1.m doesn't exist initially. You can run main.m and then create an arbitrary f1.m (example assume that the function takes no inputs) afterwards that will be run by the timer callback. This method has the added benefit that it doesn't tie up your Matlab session while the timer runs.

Related

Wait for Simulink model execution

I wrote a script file in MATLAB that executes two functions as shown below:
function TempFunction()
fcn1();
fcn2();
end
After fcn1() is executed, I want the program to wait for execution of a model in Simulink, and then execute fcn2().
How can I do that?
One way to do this would be to use a Model Callback - set up a 'StopFcn' to trigger the next thing you want to run.
Alternatively, you could go into a loop polling the 'SimulationStatus' - see this page in the doc. .
you can call simulink models as functions from MATLAB as sim('Model_Name')
Read more about the options in the docs: https://uk.mathworks.com/help/simulink/ug/using-the-sim-command.html
and the sim function: https://uk.mathworks.com/help/simulink/slref/sim.html

How to call function every Nth seconds in IEC61131-3 structured text (TwinCAT3)?

What I want to do in the code?
I want to create a function block that is made up out of 4 methods: start, stop, run, calculate. Start method will call a run method that has an while loop that periodically calls calculate method. The while loop inside the run method will end only if the stop method is called.
What I have tried already:
When I call the object.start() I want it to start a cycle that will go as long as I don't call the stop method.
timer(IN := triggerTimer, PT := T#0.1S);
trigger(CLK := timer.Q);
workingFlag := TRUE;
run();
The cycle will be in the run method. Cycle will consist of a while loop conditioned via workingFlag variable. When workingFlag is True the the while loop will constantly trigger a timer structure which will every 0.1S call the calculate method.
WHILE workingFlag = TRUE DO
triggerTimer := TRUE; //Start timer
IF trigger.Q THEN //If timer expired execute code below ...
calculate();
triggerTimer := FALSE; //Reset the timer
END_IF;
END_WHILE
Finally the stop method will just set the workingFlag to False and theoretically it would end the cycle in run method.
workingFlag := FALSE;
What is the problem?
After I call the object.start() my whole PC crashes. Therefor ... I think something is horribly wrong with my code (:
What I want to achieve with this?
The object will be a PID controller. And I want in the main program just call the start method when I want it to regulate and stop when I need it to shut down.
To this day I was calling manually the calculate method inside my main program with the timer that you can find in the run method above.
My problem with this approach was that when I had more PID's (or another functions I needed to call periodically) the code got messy really quick.
Therefor I wanted to create a function block that would have local timers and would be managing the periodical calling by itself.
So please any suggestions how to approach this problem?
Jouke already told you that WHILE is the reason. Here is your code example refactored. This is how it should be done if you want 100 milliseconds impulse work.
timer(IN := TRUE, PT := T#100MS);
IF timer.Q THEN
calculate();
timer(IN := FALSE); // reset timer
END_IF;
But remember that your main PLC cycle should not be longer than 100ms.
The object will be a PID controller. And I want in the main program just call the start method when I want it to regulate and stop when I need it to shut down.
Every PID function block has Enable input parameter. You can use that to start and stop PID.
Just set you Start variable to PID function block input, that is it.
It crashes because you instruct the PLC to run the while loop forever. The PLC software already runs cyclically (according to your PLCtask). It would be easier to put your code that is inside the while loop into a method (or in the body of the function block) that you call every cycle.
A PLC starts the code from top to bottom. Then 10ms (or other cycletime) later, it executes the same code again from top to bottom. So it's essentially a big while loop already. When running a while loop like in your example, the code enters the while loop, but never exits. Then a watchdog somewhere times out and TwinCAT crashes.

How to clear persistent variables in sub-functions

I have a script that calls a function, which is written in separate file and contains sub-functions that are inner to main function only. In one of my sub-functions, I have persistent variable that I would like to clear every time I run the main script. How can I do so? In addition, I have breakpoints through my code, and I would prefer to keep them while I clear the persistent variable - how that can be done?
MainScript.m script:
clear variables;
for iterNum=1:5
dataOut = MyMainFunction(iterNum);
end
disp(dataOut);
MyMainFunction code:
function dataOut = MyMainFunction(iterNum)
if (iterNum==1)
clear MySubFunction;
end
dataOut = MySubFunction();
end
function dataOut = MySubFunction()
persistent idx;
if isempty(idx)
idx=1;
end
dataOut=idx;
idx=idx+1;
end
I would like to clear "idx" persistent variable every time that I run MainScript.m, but of course to keep that variable as long as the script is running.
Thanks, John
The easiest way I see is to call clear followed the function name:
clear MySubFunction
instead of
clear variables;
This should clear all the persistent variables in that particular function. This will probably have the side effect of removing the stored JIT'd copy of it, causing it to be reparsed the next time it is invoked.
You can use munlock if you previously mlock'ed your function.
OR
You can define a special set of parameters in your function that are designed to solely clear the persistent variable, and you call the function with this syntax at the beginning of your main file.
Unfortunately, the other answer is partially incorrect - it is NOT possible to clear persistent variables in a sub-function using clear MySubFunction.
To quote an answer by a MathWorks staff member,
Only top level or main functions (with the same name as the file) may be cleared. To clear any local or nested function the main function must be cleared and that can't be done while the main function (or any other function in the file) is running.
and
Only whole m files can be cleared from memory. The entire file is managed as a unit so sub functions can't be cleared without clearing the main function.
As such, your options are to
separate the sub-function into its own m-file, or
clear the entire MyMainFunction from within MainScript.m, or
follow Ratbert's second suggestion, i.e. instead of using clear, give MySubFunction an additional argument that tells it to reset the persistent variables by itself

Let Matlab continue without waiting for a result

I have the following question: How do I tell Matlab that it should not wait for the results of a function? Is there a way other than threads?
My problem: I have a function A that is called by a Timer every few seconds. If a specific event is met, another function B is called inside function A. Function B opens a Batch File.
I want function A to go on without waiting for function B to end. Is there a way to easily do it?
I'm sorry if this question was already asked, but I couldn't find a satisfying answer. Please also excuse my bad english.
I would like to thank everyone who answers for their help.
In your function B, just call the batch file with a & at the end of the line.
For example:
!mybatch.bat &
This will run the file mybatch.bat in background mode and will return execution to Matlab immediately after the call.
or if you prefer the complete form:
[status, result] = system('mybatch.bat &')
But in this case it is a bit useless, since the system call mybatch in the background, the result variable is always empty and status is always 0 (whether a file mybatch.bat was found and executed or not)
edit: That is the quick trick in case it is only the batch file execution which is slowing down your program.
If you have more matlab instructions in function B and you really need function A to go on without waiting, you will have to set up a listener object with function B as a callback. Then in your function A, trigger the event (which will activate the listener and call function B).

Calling function to run when idle in matlab

Is it possible in matlab to call a function when the program I'm running is idle? I don't want this to be a parallel process. Also, I would prefer a solution where I could pause and resume the function when the main program has to run again. Kind of like an interrupt in embedded systems, in my case the main program is the interrupt.
how would I do this?
you could use a timer object to start / stop the second function. see the matlab documentation. See also this mathworks blog entry.