Ignoring Simulink blocks when generating code

29 views (last 30 days)
Jeffryes
Jeffryes on 10 Jul 2015
Edited: Jeffryes on 10 Jul 2015
I am trying to make stand alone blocks for a toolbox and have bumped into an issue getting them to work with the Simulink Coder.
Essentially, blocks have to output generated data to a file to be used at a later date. I got this to work by using a MATLAB function call and then using a combination of fopen and fprintf.
function fcn(u,FVar_M)
%#codegen
FileName = char(FVar_M);
FID = fopen(FileName,'w');
L = length(u);
for i = 1:L
u(i) = min(99999,u(i));
fprintf(FID,'%f\n',u(i));
end
fclose(FID);
This works to generate code unless I call my block from a model block (which I want to do). In this case I get some errors:
'coder.internal.fileManagerHelper' requires the use of EMLRT and can only be used with MEX and S-Function targets.
Function 'fileManager.m' (#34.1824.1835), line 45, column 52: "varargin{3}" Component: MATLAB Function | Category: Coder error
and
Function call failed.
Function 'fileManager.m' (#35.3243.3292), line 98, column 21: "coder.internal.fileManager('open',filename,cp,af)"
The functionality won't really be used when building code, so I got the bright idea of trying to disable the block when it wouldn't be required. I put the below code into the initialization for the mask, however i get an error saying you can't comment out blocks in a call back function.
if Set_M == 0
set_param(strcat(gcb,'/myblock','Commented','on');
else
set_param(strcat(gcb,'/myblock'),'Commented','off');
end
Any ideas on how I can:
A) fix my issue with the code gen when my block is within a model block? and/or
B) how to disable certain portions of a block when using code gen (note, i would like to know this second part regardless if the first part is figured out. I want to add some functionality into the blocks that is not appropriate for code gen).
Thanks, -Jeff

Answers (1)

Ryan Livingston
Ryan Livingston on 10 Jul 2015
Edited: Ryan Livingston on 10 Jul 2015
This is a bug in MATLAB Coder when using file I/O with model reference (i.e. a model block) and either accelerator or rapid accelerator mode. It has been reported to our development teams.
From my experiments, simulating in normal mode should not be an issue. Does that work for you?
One way to disable parts of a MATLAB Function block is to use coder.target to conditionally include certain code:
if coder.target('Sfun')
simulationCode();
end
or:
if coder.target('Rtw')
standaloneAndRapidAccelCode();
end
For disabling Simulink blocks in general you could consider Conditional subsystems. These allow enabling and disabling parts of a model dynamically.
  1 Comment
Jeffryes
Jeffryes on 10 Jul 2015
Edited: Jeffryes on 10 Jul 2015
Ryan,
Thanks for getting back. I have not heard of coder.target before it seems promising, I will have to play around with it to see if i can get it to work.
As for this problem, you are correct Normal mode was fine it was only an issue when running rapid accel. I managed to get a work around by creating the function in C code then creating an S-function. I will still look forward to them fixing this because MATLAB function blocks are easier to use.
For completeness I have attached the C-code below:
#define S_FUNCTION_NAME DataOutput
#define S_FUNCTION_LEVEL 2
#include "stdio.h"
#include "stdlib.h"
#include "simstruc.h"
#include <math.h>
#define FN_p(S) ssGetSFcnParam(S,0)
#define NPARAMS 1
static void mdlInitializeSizes(SimStruct *S)
{
int i;
ssSetNumSFcnParams(S, NPARAMS); /* Number of expected parameters */
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
/* Return if number of expected != number of actual parameters */
return;
}
for (i = 0; i < NPARAMS; i++)
ssSetSFcnParamTunable(S, i, 0);
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
ssSetInputPortRequiredContiguous(S, 0, true);
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetNumSampleTimes(S, 1);
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
ssSetModelReferenceSampleTimeDefaultInheritance(S);
}
#define MDL_START
#if defined(MDL_START)
static void mdlStart(SimStruct *S)
{
}
#endif
static void mdlOutputs(SimStruct *S, int_T tid)
{
/*---------Define Inputs--------*/
const real_T *VecIn = ssGetInputPortRealSignal(S, 0);
/* ------- get strings -------------- */
double Val;
char * FileNm;
FILE * fp;
int Width, i;
int_T buflen;
int_T status;
/* Get File Name from dialog parameter (string) */
buflen = mxGetN(FN_p(S))*sizeof(mxChar)+1;
FileNm = mxMalloc(buflen);
status = mxGetString(FN_p(S), FileNm, buflen);
/* Save Data to file*/
Width = VecIn[0];
fp = fopen(FileNm,"w");
for (i = 1; i <= Width; i++) {
Val = max(min(VecIn[i],99999),-99999);
fprintf(fp,"%f\n",Val);
}
fclose(fp);
}
static void mdlTerminate(SimStruct *S)
{
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
/*==================*/

Sign in to comment.

Categories

Find more on Simulink Coder in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!