Main Content

Generate FMU from C/C++ Code Using S-Function Builder

This topic shows how to generate an Functional Mockup Unit (FMU) that is compatible with FMI 3.0 standards from your C/C++ code using the S-Function Builder. Use S-Function Builder to integrate your existing C/C++ code into Simulink®. You can then generate an FMU from the S-Function Builder block.

This workflow requires the FMU Builder for Simulink support package.

Open Model That Integrates C/C++ Code to Export as FMU

In this model, we integrate a C++ class that defines a first-order low pass filter into Simulink using an S-Function Builder.

The filter is defined by the following equation,

$H(s) = \left( \frac{\omega_{cutoff}}{s + \omega_{cutoff}} \right)$,

where:

$\omega_{cutoff}$ is the cutoff frequency

The filter can be represented in time domain using Tustin Bilinear transform as,

$$y_{k} = \left( \frac{1 - \alpha}{1 + \alpha} \right)y_{k-1} + \left(\frac{\alpha}{1 + \alpha} \right) \left[ u_{k} + u_{k-1}\right]$$

$$\alpha = \left( \frac{\omega_{cutoff}T_{s}}{2} \right)$$

where:

$y_{k}$ and $y_{k-1}$ are the filter outputs at the current and previous time steps

$u_{k}$ and $u_{k-1}$ are the filter inputs at the current and previous time steps

$T_{s}$ is the sample time

Integrate C/C++ Code and Build S-Function

Define the first-order lowpass filter using C++ code.

class FirstOrderLowPassFilter
{
   private:
      double cutoffFrequency;
      double sampleTime; 
      double previousOutput;
      double previousInput; 

   public: 

    FirstOrderLowPassFilter(double cutoffFrequency, double sampleTime);
      
    double computeFilterOutput(double input); 

};
Define the methods.
#include "FirstOrderLowPassFilter.hpp"

FirstOrderLowPassFilter::FirstOrderLowPassFilter(double cutoffFreq, double SampleTime)
{
    cutoffFrequency = cutoffFreq;
    sampleTime = SampleTime;
    previousInput = 0.0;
    previousOutput = 0.0; 
}


double FirstOrderLowPassFilter::computeFilterOutput(double input)
{
    double alpha = (3.14*cutoffFrequency*sampleTime);

    double output = ((1-alpha)/(1+alpha))*previousOutput + ((alpha)/(1+alpha))*(input + previousInput); 

    previousOutput = output;
    previousInput = input; 

    return output; 
}  
The model uses the S-Function Builder block to integrate this code into Simulink and implement the low pass filter. The source and header files are specified in the Libraries table of the S-Function Builder editor.

S-Function Builder libraries table with source code specified

The S-Function Builder code uses one PWork is used to store a pointer to the instantiated filter object. The S-Function Builder is configured to have one input and one output port. The input port receives the noisy signal. The output port is configured with a bus data type. The bus output signal gives the filtered and unfiltered signal. The sample time and cutoff frequency are set as parameters with units for the S-Function Builder.

S-Function Builder editor implementation for the low pass filter

Click Build to generate the S-function.

Generate FMU from S-Function Builder

Use the Simulink.SFunctionBuilder.generateFMU function to generate FMU for the S-Function Builder block. For example, the following command generates a co-simulation FMU compatible with FMI 3.0 standards and adds a description for it.

blockHandle = getSimulinkBlockHandle('FirstOrderLowPassFilterSFunctionBuilder/S-Function Builder');
Simulink.SFunctionBuilder.generateFMU(blockHandle,'FMUType','CS','Description','First Order Low Pass Filter');
The generated FMU has the same port, parameter, and unit configuration as specified in the S-Function Builder editor.

View and specify the parameters SampleTime and CutoffFrequency in the Parameters tab of the FMU Import block dialog.

FMU Import block dialog with parameters

View the bus output configuration in the Output tab of the FMU Import block dialog.

FMU Import block dialog with output configuration

See Also

|