Force Simulink Embedded Coder to do a simple cast when converting float to uint16?

I've got a problem with Embedded Coder trying to be too helpful and it's breaking my code.
I want to simply cast a floating point to a uint16 (using the convert block).
Embedded Coder generates this monstruosity:
rtb_DataTypeConversion[0] = (uint16_T)(int32_T)fmod((int32_T)floor(fmax(0.0, fmin(65535.0, PWMGen_TestCode_B.Add_b))), 65536.0);
Which for some reason, when I run on my target (Aurix TC299), just returns 0 all the time (it doesn't like fmod...) I've also tried every option and blocks around, adding saturation, floor etc, it still wants to fmod which breaks my code.
I've hand modified my code to do:
rtb_DataTypeConversion[0] = (uint16_T)(PWMGen_TestCode_B.Add_b);
Which is a simple cast to uint16, and it works! It's as simple as that.
How can I force Simulink/Embedded coder to only generate a simple cast? I don't want to have to hand modify my code everytime, this kind of defeats the point, plus it takes ages...
Thanks for your help.
edit: Solution thanks to Les Backman

2 commentaires

That's it! Oh my god thank you so much. Spent almost two days on this... I looked for it, but it was hidden in the advanced parameters thing.

Connectez-vous pour commenter.

Réponses (1)

Why don't you use a MATLAB Function block and write this line inside it? For example:
y=uint16(x);
This line should go inside MATLAB Function instead using Data Type Conversion block.

5 commentaires

Thank you very much for the suggestion.
That's a great idea, but it doesn't quite work as Embedded Coder is trying to be helpful again.
Here's what it generates:
tmp = rt_roundd_snf(PWMGen_TestCode_B.Add_b);
if (tmp < 65536.0) {
if (tmp >= 0.0) {
rtb_y[0] = (uint16_T)tmp;
} else {
rtb_y[0] = 0U;
}
} else {
rtb_y[0] = MAX_uint16_T;
}
and that function is:
real_T rt_roundd_snf(real_T u)
{
real_T y;
if (fabs(u) < 4.503599627370496E+15) {
if (u >= 0.5) {
y = floor(u + 0.5);
} else if (u > -0.5) {
y = u * 0.0;
} else {
y = ceil(u - 0.5);
}
} else {
y = u;
}
return y;
}
So it's almost there. If it weren't calling that rounding function it would be okay with me.
I think the issue is that it's calling fmod and floor, where it should be calling fmodf and floorf for single precision floats. But this also takes a lot of CPU time, and I just want the cast!
Can you share your model? It will help me to understand the situation better.
I can't really, there's some proprietary libraries in there.
But here's basically what the code is doing. The only part that messes up is that convert block at the end.
I could make the whole calculation in fixed point, but that also kinds of defeats the pont of having an FPU in the CPU.
I just want Embedded Coder to generate a simple cast to uint16 at the end, but it's generating code with fmod and floor which somehow doesn't work. I understand why it does, it's to be safe and make sure there's no overflow etc, but I want to override that and do a simple cast.
One question:
-Is the ton/toff ratio smaller than 1? If it so, for example, if it is 0.6, then it might be rounded to 0, which is what you are seeing. Can you also share the mask for Data Type Conversion block?
I've checked with my debugger, the tOn/tOff times are all calculated correctly, they are in number of GTM counts (internal CPU timer, so they'll always be greater than 1).
Example with my modified code that works: On the right side watch window are the result of the math calculation. On the left side are the results of the data conversion.
When I let Embedded Coder do it's thing, the table rtb_DataTypeConversion is all zeroes.
Here is the data convert mask (I've tried pretty much all the different options, it still does the same).

Connectez-vous pour commenter.

Catégories

Produits

Version

R2019a

Community Treasure Hunt

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

Start Hunting!

Translated by