Hello, I have 2 Simulink models, one is a PI controller, and one is a spring-mass-damper system. I converted them into 2 different C++ files with Generic Real-Time Target. Now I want to connect both of them but I don't know how. I tried to create one new project in Codeblocks and include all .cpp and .h files but the results are different from simulation. Does anyone have experience on this?
MATLAB: How to connect 2 generated code from 2 different Simulink models
csimulinkcoder
Related Solutions
The ability to generate a file that contains source files, compiler options, and link options is not available in Real-Time Workshop.
For releases prior to Real-Time Workshop v.v (R2007a), there are 2 methods to port generated code. Both require a lot of manual copying and extracting information from the makefile. Either the MATLAB file hierachy must be maintained and the generated makefile can be used with minor modifications, or the files must be copied, and some information form the makefile must be extracted. Both methods are summarized below.
%%%METHOD 1: Maintaining the MATLAB hierarchy
Note: "Host PC" refers to the PC running MATLAB, while "Target PC" refers to
the PC that the code will be compiled on (without MATLAB installed)
1) Generate code for the model on the Host PC
2) Copy the entire build dir (usually called model_ert_rtw) to the Target PC For example (rtwdemo_counter is the model):
Host PC: C:\myproject\rtwdemo_counter_ert_rtw
Target PC: C:\my_target_port\rtwdemo_counter_ert_rtw
3) Copy the entire slprj dir to the Target PC:
Host PC: C:\myproject\slprj\...
Target PC: C:\my_target_port\slprj\...
4) Open the generated makefile (the .mk file) and look for the definition of
MATLAB_INCLUDES. There will be several directories listed similar to these:
$(MATLAB_ROOT)\rtw\c\ert
$(MATLAB_ROOT)\extern\include
$(MATLAB_ROOT)\simulink\include
...
All of these directories must be copied from the Host PC to the Target PC, maintaining the relative path hierarchy. On the Target PC, a directory should be created for these directories. For example create this directory on the Target PC:
C:\my_target_port\MATLAB_files
assuming MATLAB is installed on the Host PC here:
C:\Program Files\MATLAB71
Then the directories listed in the makefile should be copied:
Host PC: C:\Program Files\MATLAB71\rtw\c\ert
Target PC: C:\my_target_port\MATLAB_files\rtw\c\ert
Host PC: C:\Program Files\MATLAB71\extern\include
Target PC: C:\my_target_port\MATLAB_files\extern\include
Host PC: C:\Program Files\MATLAB71\simulink\include
Target PC: C:\my_target_port\MATLAB_files\simulink\include
...
5) Step 4 must be repeated for build rules that contain $(MATLAB_ROOT) in them. For example, if this rule appears (this is from an MSVC build):
{$(MATLAB_ROOT)\rtw\c\ert}.c.obj
Then the source files in that directory should be copied
6) Copy vctools.mk from the Host PC to the Target PC:
Host PC: C:\Program Files\MATLAB71\rtw\c\tools\vctools.mk
Target PC: C:\my_target_port\MATLAB_files\rtw\c\tools\vctools.mk
7) In the makefile (.mk file) on the Target PC, change the definition of MATLAB_ROOT and ALT_MATLAB_ROOT MATLAB_BIN and ALT_MATLABBIN to the location on the Target PC:
Host PC:
MATLAB_ROOT = C:\Program Files\MATLAB71
ALT_MATLAB_ROOT = C:\PROGRA~1\MATLAB71
MATLAB_BIN = C:\Program Files\MATLAB71\bin\win32
ALT_MATLAB_BIN = C:\PROGRA~1\MATLAB71\bin\win32
Target PC:
MATLAB_ROOT = C:\my_target_port\MATLAB_files
ALT_MATLAB_ROOT = C:\my_target_port\MATLAB_files
MATLAB_BIN = C:\my_target_port\MATLAB_files\bin\win32
ALT_MATLAB_BIN = C:\my_target_port\MATLAB_files\bin\win32
8) In the additional includes area of the makefile, the start dir and build dir should be updated to the location on the Target PC (example with rtwdemo_counter model shown here):
Host PC:
MATLAB_INCLUDES = $(MATLAB_INCLUDES);c:\myproject
MATLAB_INCLUDES =
$(MATLAB_INCLUDES);c:\myproject\rtwdemo_counter_ert_rtw
Target PC:
MATLAB_INCLUDES = $(MATLAB_INCLUDES);c:\my_target_port\
MATLAB_INCLUDES =
$(MATLAB_INCLUDES);c:my_target_port\rtwdemo_counter_ert_rtw
9) On the Target PC the environment must be set up for MSVC. TMSVC ususally
installs a batch file called vcvars32.bat (or similar). run this on the Target PC.
10) In the generated BAT file(the model .bat file), copy the line that starts with
'nmake -f...' into a DOS cmd shell that is in the Target PC build directory
(c:\my_target_port).
%%%METHOD 2: Copying the sources to the Target PC
Note: in this method all files can be coipied to the same directory
1) Generate code for the model on the Host PC
2) Copy the entire build dir (usually called model_ert_rtw) to the Target PC For example (rtwdemo_counter is the model):
Host PC: C:\myproject\rtwdemo_counter_ert_rtw
Target PC: C:\my_target_port\
3) Copy the entire slprj dir to the Target PC:
Host PC: C:\myproject\slprj\...
Target PC: C:\my_target_port\
Steps 4 and 5 are the same as for Method 1, except all files can go into the
same target dir.
4) In the generated makefile (the model .mak file) the defines must be extracted:
First look for the definition of CPP_REQ_DEFINEs. It should look similar to this:
CPP_REQ_DEFINES = -DMODEL=$(MODEL) -DNUMST=$(NUMST) -DNCSTATES=$(NCSTATES) \
-DMAT_FILE=$(MAT_FILE) -DINTEGER_CODE=$(INTEGER_CODE) \
-DONESTEPFCN=$(ONESTEPFCN) -DTERMFCN=$(TERMFCN) \
-DHAVESTDIO -DMULTI_INSTANCE_CODE=$(MULTI_INSTANCE_CODE) \
-DADD_MDL_NAME_TO_GLOBALS=$(ADD_MDL_NAME_TO_GLOBALS)
For each make var that looks similar to "$(...)" the value most be searched for in the makefile. Most, if not all of them will be near the beginning of the makefile and look similar to this:
...
NUMST = 1
NCSTATES = 0
BUILDARGS = GENERATE_REPORT=1
MULTITASKING = 0
INTEGER_CODE = 1
MAT_FILE = 0
ONESTEPFCN = 1
TERMFCN = 0
...
These must be expanded and put into a temporary text buffer. So the final defines will look similar to this:
/DMODEL=rtwdemo_counter /DNUMST=1 /DNCSTATES=0 /DMAT_FILE=0 /DINTEGER_CODE=1
/DONESTEPFCN=1 /DTERMFCN=0 /DHAVESTDIO /DMULTI_INSTANCE_CODE=0
/DADD_MDL_NAME_TO_GLOBALS=0
Additionally, if External mode is used, then the "-D" definitions in the
external mode section of the makefile must be copied as well.
5) The defines obtained in step 4 must either be put on the compile line (if a custom makefile is being created), or they must be imported into the IDE.
Please see the following points:
- Through a suitable hook - like postCodeGen - you can programmatically construct a master script to call the individual makefiles / bat scripts. https://www.mathworks.com/help/releases/R2017b/rtw/ug/customizing-post-code-generation-build-processing.html
- You can access the list of referenced models by querying 'buildInfo.ModelRefs'. BuildInfo is one of the auto-generated artifacts in the form of a MAT file, which you can load and access its data.
- Here's some pseudocode that will compose paths of Model Reference libraries (and rtwsharedlib)
% Extract referenced model info
mdls = args.buildInfo.ModelRefs;% Find the path of the directory code generation was started from
startDir = args.buildInfo.Settings.LocalAnchorDir;% Initialize empty cell for path info
paths = cell(size(mdls));% Additional Code for the Relative Directory
% Determine your current working directory
currentDir = pwd;% Remove the starting directory from the current directory, this will leave
% only the path from the starting directory to the current folder.
pathFromAnchor = currentDir(2+length(startDir):end);% Extract all the folders between the starting directory and the current
% directory
folders = strsplit(pathFromAnchor,'\');% Create the relative path to the start directory based on the number of
% folders between the start and current directories.
relativePath = repmat('../',1,length(folders));% If there are model references loop over them and construct the path for
% each reference
if ~isempty(mdls) for i = 1:length(mdls) libname = mdls(i).Name; fullpath = replace(mdls(i).Path,'$(START_DIR)\', relativePath); paths{i} = [fullpath,'\',libname]; endend
So, to conclude, using the above script as reference, you should be able to compose a script to build the generate code.
Alternatively, you can use the 'PackNGo' feature to obtain the list of files. You would need to use 'packType = hierarchical' and then add the makefiles to the buildInfo before calling PackNGo. Read this for more info: https://www.mathworks.com/help/releases/R2017b/rtw/ref/packngo.html
Also, for your information, starting R2020b, a new API has been introduced i.e. 'codebuild' which can successfully generate a CMakeLists.txt for the complete application. This is exactly you are looking for. But this only exists starting R2020b. https://www.mathworks.com/help/releases/R2020b/rtw/ref/codebuild.html
Related Question
- Do I get the errors about duplicate files with the packNgo function in Real-Time Workshop 5.1 (R2008a)
- Do I get Linker errors while building a Simulink model to dll file
- How to prevent the rt_main.c or ert_main.c file from being included in the packNGo package when using ert.tlc
- Unable to find ‘solver_zc.h’ header file in generated code from Embedded Coder
- How to use PackNGo without naming dependencies on the current directory
Best Answer