0

After problems I had here, I need some help to write a function with MATLAB Function block. I saw in following links that some people solved it with that block or s-function: http://www.mathworks.co.uk/matlabcentral/newsreader/view_thread/317910

http://www.physicsforums.com/showthread.php?t=595813

http://www.mathworks.de/matlabcentral/newsreader/view_thread/250266

So I tried with this:

function y = fcn(u)
coder.extrinsic('only3')
coder.extrinsic('serial', 'fopen','fread')
coder.extrinsic('set')

persistent s a 
y = (zeros(2,1));
  s = serial('COM12');

set(s,'Terminator','', 'InputBufferSize', 1024);
a = char('000');        % a-initialization for mxArray problems

a = only3(get(s,'status'));   %to check if port is already opened calling custom function 
if strncmp(a,'clo',3)==true
    fopen(s)
else
    fclose(s)
end

   y = fread(s,[2 1],'uint8'); % I have to read some data from serial. This command works fine in the matlab command window.

Where only3 is a function that I created. It takes first 3 char from a string, and I need it to compare only three char of the 'status' answer:

function let = only3(string)

let = string(1:3);

I did it to know if communication is already opened. But simulink returns me an error as window:

Call to MATLAB function aborted: Open failed: Port: COM12 is not available. No ports are available.

I think it tries to open the port after port opening in the first iteration.

EDIT: I change my code with this:

function y = fcn(u)

coder.extrinsic('only3')
coder.extrinsic('strncmp') %like Phil say
coder.extrinsic('serial', 'fopen','fread')
coder.extrinsic('get')
persistent s a b
y = (zeros(2,1));

%%Part taken from Phil suggestion:

 if isempty(s)
   % only do this the first time
    s = serial('COM12','Terminator','', 'InputBufferSize', 1024);
    a = '000';
    b = false; %without this returns mxArray error.
end 


a = only3(get(s,'status'));
b = strncmp(a,'clo',3);
if b == true
    fopen(s)
else
    fclose(s)
end


y = fread(s,[2 1],'uint8'); 

It returns as error:

Unsuccessful read: OBJ must be connected to the hardware with FOPEN. Block MATLAB Function (#24) While executing: State During Action 

hightlighting y expression.

UPDATE EDIT: I solved it with following code:

function y = fcn(u)
coder.extrinsic('only3')
coder.extrinsic('strncmp')
coder.extrinsic('serial', 'fopen','fread')
coder.extrinsic('get')
persistent s a b
y = uint8(zeros(2,1));  %signal is an uint8

 if isempty(s)
   % only do this the first time
    s = serial('COM12','Terminator','', 'InputBufferSize', 1024);
    a = '000';
    b = false;
    a = only3(get(s,'status'));
b = strncmp(a,'clo',3);

    switch double(b)
    case 1
        fopen(s);
    otherwise
        fclose(s);
    end
end

   y = uint8(fread(s,[2 1],'uint8')); 

But, as I commented below, every time that I stop simulation I have to restart Matlab because it does not close communication. I say this because if I re-try to start simulation it returns "my first error":

Call to MATLAB function aborted: Open failed: Port: COM12 is not available. No ports are available.

I do not know why. There would be something that runs fclose(s) every simulation stopping like mdlTerminate function in M-code Level-1 S-functions. Some suggestion ?

Community
  • 1
  • 1
cyberdyne
  • 426
  • 3
  • 5
  • 23

2 Answers2

1

Your initialization of the persistent variables is wrong. Presumably what you really want is

persistent s a
if isempty(s)
   % only do this the first time
   s = serial('COM12');
   a = '000';
end
Phil Goddard
  • 10,571
  • 1
  • 16
  • 28
  • After this can I continue with rest of the code or have I to change something else? – cyberdyne Feb 23 '14 at 00:24
  • You no longer want the s =... and a = ... lines, and you most likely need to define strncmp as extrinsic, but the easiest thing to do is try it and see if it works. If it does great. If it doesn't then tell us the next error message. – Phil Goddard Feb 23 '14 at 04:04
  • Ok, thanks. I changed my code and I am writing it above. – cyberdyne Feb 23 '14 at 11:45
  • I solved it but every time I have to restart matlab because it does not close communication. I am sharing code above. – cyberdyne Feb 23 '14 at 12:49
  • 1
    One of the problems with the MATLAB Fcn Block is that you don't have as fine control over execution as with an S-Function -- in this case no control over what happens at termination. Given that all of your code is extrinsic, I'd just convert it to an S-Function, then you can use mdlTerminate. Alternatively, before starting the simulation you should be able to 'clear functions' at the MATLAB command line, which will clear the persistent variables, putting them out of scope and hence closing the connection. – Phil Goddard Feb 23 '14 at 16:26
  • Ok, thanks. An information: MATLAB Fcn has compiled a MEX file. Can I use it in a S-function block? Would it increase performance or will it be the same? – cyberdyne Feb 24 '14 at 11:54
  • 1
    A MATLAB Fcn block is already a C-mex S-Function, so trying to incorporate it into another S-Function doesn't make sense. In your use-case, since almost everything in the function is defined as extrinsic, effectively this is what's happening: Simulink calls the S-Function; the S-function calls back into MATLAB to execute the extrinsic functions (note they do not get converted to C-code); the results are passed back to the S-Function; which then passed the results back to Simulink. It is not hard to create cases like this where it is faster to just use an m-code S-function. – Phil Goddard Feb 24 '14 at 15:28
  • I asked this because SERIAL class does not supported by Simulink Coder , so I wonder if incorporating MEX into a S-Function block I solve it. – cyberdyne Feb 24 '14 at 16:25
  • 1
    Anything that requires MATLAB to execute - in this case serial - by definition, requires MATLAB to execute. There is no way around that except to find a C library that does the same thing and use it instead. – Phil Goddard Feb 24 '14 at 17:01
0

if your port is not closed, you can use the instrfind command to get the array of intruments, then you can use fclose to close the comunication.

I.e.

q=instrfind();

%%select the index port that you want to close.

fclose(q(x)); where x is the index

And if you need to clear all the instruments, use delete(q);

Best regards.

Unheilig
  • 16,196
  • 193
  • 68
  • 98
Ralf
  • 1