Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problem with Embedded Matlab Function in Simulink

1,271 views
Skip to first unread message

Cahit

unread,
Sep 5, 2006, 11:16:09 AM9/5/06
to
Hi all,

In Matlab 7.1 version, im trying to work with embedded Matlab
function block in my Simulink model in order to break double value
into 8 sets of uint8.

For that 'typecast' function is ideal but model always gives me
mistakes. In Embedded Mat.Func i just write,

function y = fcn(u)

y=typecast(u,'uint8')

I also set up in model explorer window that u is double value and
the size will be inherited from the attached block and y has the size
1x8 array stating [1 8] and the type of it uint8. What is wrong?

Perhaps Embedded function doesn't support the typecast function, if
yes how can i achieve this? Anyone who has dealt with embedded
function already, your help will be highly appreciated. Thank you.

Cahit

Idin Motedayen-Aval

unread,
Sep 5, 2006, 2:26:01 PM9/5/06
to
Cahit wrote:
> Hi all,
>
> In Matlab 7.1 version, im trying to work with embedded Matlab
> function block in my Simulink model in order to break double value
> into 8 sets of uint8.
>
> For that 'typecast' function is ideal but model always gives me
> mistakes. In Embedded Mat.Func i just write,
>
> function y = fcn(u)
>
> y=typecast(u,'uint8')
>


Give this a try:
function y = fcn(u)

y = uint8(zeros(8,1));
y = typecast(u,'uint8');

This seems to work ok for me (I just pre-allocated the array; EML
doesn't like calls that look like they could be dynamically sizing the
array).

Idin Motedayen-Aval
The MathWorks

Michael Hosea

unread,
Sep 6, 2006, 4:08:18 PM9/6/06
to
Right, you can get it to work if you set the type and size of y explicitly
in the manner that Idin suggested. The main issue here is that TYPECAST
isn't yet supported as an Embedded MATLAB library function, and so it is a
call out from Simulink to MATLAB. Such function calls return mxArrays,
which carry along with them severe restrictions within Embedded MATLAB.
However, with Idin's solution Embedded MATLAB is told that the output of the
TYPECAST function will be an mxArray that should be convertible into an
array of 8 uint8s, and so after the call to MATLAB it carries out this
conversion, and everything works nicely.

The only problem is that you can't use RTW to generate standalone C code for
a model that relies on calling MATLAB.

One thing to note is that I do get the warning (I think this begins with the
2006b release)

Function 'typecast' implicitly resolved in the MATLAB workspace.
This feature is deprecated.
Please declare this function extrinsic using eml.extrinsic('typecast'), or
call it using feval.

If you get this warning, the easiest way to quiet it is simply to add the
line

eml.extrinsic('typecast')

The reason we are making this change from handling the situation
automatically, calling out to MATLAB when necessary, to asking the user to
handle it explicitly, using feval or declaring certain functions as
"extrinsic", is that new Embedded MATLAB library functions can sometimes
only support a subset of their full-up MATLAB counterparts. Consquently, a
new release of Simulink might break a user model relying on
automatically-resolved calls to MATLAB functions simply because new Embedded
MATLAB library functions were added.
--
Mike

"Idin Motedayen-Aval" <imot...@mathworks.com> wrote in message
news:edkffp$6ns$1...@fred.mathworks.com...

Cahit

unread,
Sep 7, 2006, 9:44:29 AM9/7/06
to

Hello Mike,

Thanks a lot for your detailed reply and information. As I said
before im working on serial interface between an external device
(Dspace Control Box) and Comp.
What you told me about Typecast function and Embedded Matlab Func.
worked nicely in Simulink but unfortunately that Typecast function is
not supported by my external device library and embedded func.
including Typecast did not work out in my main interface Model.
Therefore, i decided to do what Typecast does in ordinary way using
'sprintf','reshape' and 'hex2dec'functions respectively as follows in
my embedded function in model :

function y = fcn(u)
y=hex2dec(reshape(sprintf('%bx',u), 2, 8)')

In model, u is a double constant block, then comes embedded f. block
and then data type conversion block of uint8 (as external device
input only accepts uint8).I expect 'y' 8x1 size double array in
emb.func.

Independent from my external device i just tried a simple model in
simulink to check it in block order like,

constant u block-->embedded funct-->data type conversion
uint8--->display

In this model, i also set up some parameters in Model Explorer
Window of Embedded function such as Size [8 1],Data Type Mode of u
and y as double etc.

But i am still receiving this error message :

Error : Inferred type (ml) for data 'y' (#135) does not match
specified type (double)

Warning: Function resolved in the MATLAB workspace and will only be
called during simulation.

Function 'Embedded MATLAB Function' (#131.23.64), line 2, column 3:
"hex2dec(reshape(sprintf('%bx',u), 2, 8)')"

I dont understand the type of 'ml'. I would be very pleased if you
could help with this matter, it will be a good step to finish it for
me to go further.

I really appreciate your suggestions.

Kind Regards,
Cahit

Michael Hosea

unread,
Sep 8, 2006, 2:14:52 PM9/8/06
to
Ah, yes. Since neither HEX2DEC nor SPRINTF are supported in Embedded MATLAB
for code generation, you're in the same situation there (or worse). I can
imagine going about this using the LOG2 function, which will give you a
mantissa abs(m) <= 0.5 and an integer exponent, but it will still require a
lot of computation and attention to detail to accomplish something that is
trivial straight C, either by simply casting the address of a double to the
address of an array of unsigned chars, or perhaps by something a little less
"under the table" like

union { double d; unsigned char u[8] } d2u;
d2u.d = x;

In the future we may have custom C code integration into Embedded MATLAB,
but for now I would suggest that you follow the path of integrating custom C
code into an S function for RTW in order to split a double up into an array
of bytes. I'm told that the Legacy Code Tool for Simulink in 2006b will
help you write an S-function, but to be honest with you, I'm out of my depth
when it comes to doing things like that in Simulink, so now would be a good
time for one of my Simulink and RTW savvy colleagues to step in.

For my part, I'll enter this as an enhancement request for TYPECAST in
Embedded MATLAB.
--
Mike

"Cahit" <cahit_...@yahoo.com> wrote in message
news:ef3f...@webcrossing.raydaftYaTP...
[snip]

Cahit

unread,
Sep 14, 2006, 6:58:07 AM9/14/06
to

Hi Mike,

Thank you for your last reply. Since then, i decided to switch to
write an ordinary C S-Function to split a double into 8 sets of uint8
values!
But i still get wrong values and do not know why namely e.g double
value is pi, i should get this matrix

[24 45 68 84 251 33 9 64]

but i get 8 times only the first value 24!

if you do not mind, here is my C S-Function Code: mdlinitialize and
mdloutput functions.

static void mdlInitializeSizes(SimStruct *S)

{
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}

if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDataType(S, 0, SS_DOUBLE);
ssSetInputPortDirectFeedThrough(S, 0, 1);

if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 8);
ssSetOutputPortDataType(S, 0, SS_UINT8);

ssSetNumSampleTimes(S, 1);
ssSetOptions(S,0);
}

static void mdlOutputs(SimStruct *S, int_T tid)

{
int_T i;
int_T width = ssGetOutputPortWidth(S,0);
InputPtrsType uPtrs = ssGetInputPortSignalPtrs(S,0);
uint8_T *y = (uint8_T *)ssGetOutputPortSignal(S,0);

InputUInt8PtrsType pU0 = (InputUInt8PtrsType)uPtrs;

for(i=0; i<width; i++)
{
y[i] = *pU0[i];
}
}

I would be very pleased if you could refer to this problem and what
i should change to get the desired matrix.I really appreciate your
suggestions, thank you!

Regards,
Cahit

Michael Hosea

unread,
Sep 14, 2006, 1:58:20 PM9/14/06
to
Try this replacement:

static void mdlOutputs(SimStruct *S, int_T tid)

{

const real_T *u0 = (const real_T*) ssGetInputPortSignal(S,0);

uint8_T *y0 = (uint8_T *)ssGetOutputPortRealSignal(S,0);

memcpy(y0,u0,sizeof(real_T));


}

If that works, then use it as a starting point for converting an array of
doubles (just replace sizeof(real_T) with the output port width, I think).

I basically just did this with the S-function Builder block. The "outputs"
tab has just the memcpy line of code, and the input and output signals are
defined appropriately. S-function Builder puts the memcpy wrapper function,
but it's just a straight call with arguments u0 and y0.

--

Mike


"Cahit" <cahit_...@yahoo.com> wrote in message
news:ef3f...@webcrossing.raydaftYaTP...

Cahit

unread,
Sep 15, 2006, 12:56:17 PM9/15/06
to

Hi Mike,

Thank you for your reply, i tried what you told me. It has been
nicely compiled but still does not give expected results. As an
alternative, i tried it with union as follows :

typedef union
{ uint8_T uvalue[8];
real_T d;
} UnionNum;

Initialization func. is the same.

static void mdlOutputs(SimStruct *S, int_T tid)
{
int_T i;
int_T width = ssGetOutputPortWidth(S,0);

InputPtrsType uPtrs = ssGetInputPortSignalPtrs(S,0);
uint8_T *y = (uint8_T *)ssGetOutputPortSignal(S,0);

UnionNum num;
num.d = *uPtrs[0] ;
for(i=0; i<width; i++)
{
y[i] = num.uvalue[i];
}
}

I think, that should have worked but gave me this error :

Error : have illegal types 'double' and 'void'

Such a strange error! Why does it have problem with double? I still
do not find out the solution and wanted to share with you. As a
result, i would really appreciate your suggestions i.e. improvement.
Thanks a lot in advance.

Regards,
Cahit

Michael Hosea

unread,
Sep 15, 2006, 3:54:08 PM9/15/06
to
I'm not sure where your error lies. I just drop an S-function Builder block
into a model, open the block, give the S-function a name in the edit box,
change the output data property to be 8 rows and its type to be uint8 (the
input data type is correct by default, I think). Then I add one line of
code in the edit box on the output tab (overwriting a comment snippet that
gets preloaded there) which says

memcpy(y0,u0,8);

Then I hit the BUILD button on the S-Function Builder dialog box. It
generates the S-function and gives the desired results. I'm not comfortable
enough with S-functions to help you debug your S-function, so I recommend
the S-function Builder instead.

0 new messages