Create Tunable Calibration Parameter in the Generated Code

A calibration parameter is a value stored in global memory that an algorithm reads for use in calculations but does not write to. Calibration parameters are tunable because you can change the stored value during algorithm execution. You create calibration parameters so that you can:

  • Determine an optimal parameter value by tuning the parameter and monitoring signal values during execution.

  • Efficiently adapt an algorithm to different execution conditions by overwriting the parameter value stored in memory. For example, you can use the same control algorithm for multiple vehicles of different masses by storing different parameter values in each vehicle’s engine control unit.

In Simulink®, create a Simulink.Parameter object to represent a calibration parameter. You use the parameter object to set block parameter values, such as the Gain parameter of a Gain block. To control the representation of the parameter object in the generated code, you apply a storage class to the object.

To make block parameters accessible in the generated code by default, for example for rapid prototyping, set Default parameter behavior (see Default parameter behavior) to Tunable. For more information, see Preserve Variables in Generated Code.

Represent Block Parameter as Tunable Global Variable

This example shows how to create tunable parameter data by representing block parameters as global variables in the generated code.

Configure Block Parameter by Using Parameter Object

Open the example model rtwdemo_paraminline and configure it to show the generated names of blocks.

load_system('rtwdemo_paraminline')
set_param('rtwdemo_paraminline','HideAutomaticNames','off')
open_system('rtwdemo_paraminline')

On the Modeling tab, click Model Data Editor.

In the Model Data Editor, inspect the Parameters tab.

In the model, click the G1 Gain block. The Model Data Editor highlights the row that corresponds to the Gain parameter of the block.

In the Model Data Editor Value column, change the gain value from 2 to myGainParam.

Next to myGainParam, click the action button (with three vertical dots) and select Create.

In the Create New Data block dialog box, set Value to Simulink.Parameter(2). Click Create. A Simulink.Parameter object myGainParam stores the parameter value, 2, in the base workspace.

In the myGainParam dialog box, set Storage class to ExportedGlobal and click OK. This storage class causes the parameter object to appear in the generated code as a tunable global variable.

Alternatively, to create the parameter object and configure the model, use these commands at the command prompt:

set_param('rtwdemo_paraminline/G1','Gain','myGainParam')
myGainParam = Simulink.Parameter(2);
myGainParam.CoderInfo.StorageClass = 'ExportedGlobal';

Use the Model Data Editor to create a parameter object, myOtherGain, for the G2 Gain block. Apply the storage class ExportedGlobal.

Alternatively, use these commands at the command prompt:

set_param('rtwdemo_paraminline/G2','Gain','myOtherGain')
myOtherGain = Simulink.Parameter(-2);
myOtherGain.CoderInfo.StorageClass = 'ExportedGlobal';

Generate and Inspect Code

Generate code from the model.

rtwbuild('rtwdemo_paraminline')
### Starting build procedure for: rtwdemo_paraminline
### Successful completion of build procedure for: rtwdemo_paraminline

The generated file rtwdemo_paraminline.h contains extern declarations of the global variables myGainParam and myOtherGain. You can include (#include) this header file so that your code can read and write the value of the variable during execution.

file = fullfile('rtwdemo_paraminline_grt_rtw','rtwdemo_paraminline.h');
rtwdemodbtype(file,...
    'extern real_T myGainParam;','Referenced by: ''<Root>/G2''',1,1)
extern real_T myGainParam;             /* Variable: myGainParam
                                        * Referenced by: '<Root>/G1'
                                        */
extern real_T myOtherGain;             /* Variable: myOtherGain
                                        * Referenced by: '<Root>/G2'

The file rtwdemo_paraminline.c allocates memory for and initializes myGainParam and myOtherGain.

file = fullfile('rtwdemo_paraminline_grt_rtw','rtwdemo_paraminline.c');
rtwdemodbtype(file,...
    '/* Exported block parameters */','Referenced by: ''<Root>/G2''',1,1)
/* Exported block parameters */
real_T myGainParam = 2.0;              /* Variable: myGainParam
                                        * Referenced by: '<Root>/G1'
                                        */
real_T myOtherGain = -2.0;             /* Variable: myOtherGain
                                        * Referenced by: '<Root>/G2'

The generated code algorithm in the model step function uses myGainParam and myOtherGain for calculations.

rtwdemodbtype(file,...
    '/* Model step function */','/* Model initialize function */',1,0)
/* Model step function */
void rtwdemo_paraminline_step(void)
{
  /* Outport: '<Root>/Out1' incorporates:
   *  Gain: '<Root>/G1'
   *  Gain: '<Root>/G2'
   *  Inport: '<Root>/In1'
   *  Sum: '<Root>/Sum'
   */
  rtwdemo_paraminline_Y.Out1 = myGainParam * rtwdemo_paraminline_U.In1 +
    myOtherGain * -75.0;
}

Apply Storage Class When Block Parameter Refers to Numeric MATLAB Variable

If you use a numeric variable to set the value of a block parameter, you cannot apply a storage class to the variable. As a workaround, you can convert the variable to a parameter object, and then apply a storage class to the object. To convert the variable to a parameter object, choose one of these techniques:

  • On the Model Data Editor Parameters tab, with Change view set to Code, find the row that corresponds to the variable. In the Storage Class column, from the drop-down list, select Convert to parameter object. The Model Data Editor converts the variable to a parameter object. Then, use the Storage Class column to apply a storage class to the object.

    You can also use this technique in the Model Explorer.

  • Use the Data Object Wizard (see Create Data Objects for a Model Using Data Object Wizard (Simulink)). In the Wizard, select the Parameters check box. The Wizard converts variables to objects. Then, apply storage classes to the objects, for example, by using the Model Data Editor or the Model Explorer.

Create Storage Class That Represents Calibration Parameters (Embedded Coder)

This example shows how to create a storage class that yields a calibration parameter in the generated code. The storage class causes each parameter object (Simulink.Parameter) to appear as a global variable with special decorations such as keywords and pragmas.

In the generated code, the calibration parameters must appear as global variables defined in a file named calPrms.c and declared in calPrms.h. The variable definitions must look like these definitions:

#pragma SEC(CALPRM)

const volatile float param1 = 3.0F;
const volatile float param2 = 5.0F;
const volatile float param3 = 7.0F;

#pragma SEC()

The variables use the keywords const and volatile. The pragma #pragma SEC(CALPRM) controls the placement of the variables in memory. To implement the pragma, variable definitions must appear in a contiguous block of code.

Also, the generated code must include an ASAP2 (a2l) description of each parameter.

Create Package for Storing Storage Class and Memory Section Definitions

Now, create a package in your current folder by copying the example package +SimulinkDemos. The package stores the definitions of Parameter and Signal classes that you later use to apply the storage class to data elements in models. Later, the package also stores the definitions of the storage class and an associated memory section.

  1. Set your current MATLAB® folder to a writable location.

  2. Copy the +SimulinkDemos package folder into your current folder. Name the copy +myPackage.

    copyfile(fullfile(matlabroot,...
        'toolbox','simulink','simdemos','dataclasses','+SimulinkDemos'),...
        '+myPackage','f')

  3. Navigate inside the +myPackage folder to the file Signal.m to edit the definition of the Signal class.

  4. Uncomment the methods section that defines the method setupCoderInfo. In the call to the function useLocalCustomStorageClasses, replace 'packageName' with 'myPackage'. When you finish, the section looks like this:

      methods
        function setupCoderInfo(h)
          % Use custom storage classes from this package
          useLocalCustomStorageClasses(h, 'myPackage');
        end
      end % methods

  5. Save and close the file.

  6. Navigate inside the +myPackage folder to the file Parameter.m to edit the definition of the Parameter class. Uncomment the methods section that defines the method setupCoderInfo and replace 'packageName' with 'myPackage'.

  7. Save and close the file.

Create Storage Class and Memory Section

  1. Set your current folder to the folder that contains the package folder +myPackage.

  2. Open the Custom Storage Class Designer.

    cscdesigner('myPackage')
  3. In the Custom Storage Class Designer, on the Memory Sections tab, click New.

  4. For the new memory section, set properties according to the table.

    PropertyValue
    NameCalMem
    Statements SurroundGroup of variables
    Pre Statement#pragma SEC(CALPRM)
    Post Statement#pragma SEC()
    Is constSelect
    Is volatileSelect

  5. Click Apply.

  6. On the Custom Storage Class tab, click New.

  7. For the new storage class, set properties according to the table.

    PropertyValue
    NameCalParam
    For signalsClear
    Data scopeExported
    Header FilecalPrms.h
    Definition FilecalPrms.c
    Memory SectionCalMem

  8. Click OK. In response to the message about saving changes, click Yes.

Set Default Parameter Object to myPackage.Parameter

To make applying the storage class easier, use the Model Explorer to change the default parameter object from Simulink.Parameter to myPackage.Parameter.

  1. At the command prompt, open the Model Explorer.

    daexplr

  2. In the Model Explorer Model Hierarchy pane, select Base Workspace.

  3. In the Model Explorer toolbar, click the arrow next to the Add Simulink Parameter button. In the drop-down list, select Customize class lists.

  4. In the Customize class lists dialog box, under Parameter classes, select the check box next to myPackage.Parameter. Click OK.

  5. In the Model Explorer toolbar, click the arrow next to the Add Simulink Parameter button. In the drop-down list, select myPackage Parameter.

    A myPackage.Parameter object appears in the base workspace. You can delete this object.

Now, when you use tools such as the Model Data Editor to create parameter objects, Simulink creates myPackage.Parameter objects instead of Simulink.Parameter objects.

Apply Storage Class

In the example model rtwdemo_roll, the BasicRollMode subsystem represents a PID controller. Configure the P, I, and D parameters as calibration parameters.

  1. Open the model.

    rtwdemo_roll

  2. In the model, navigate into the BasicRollMode subsystem.

  3. In the Apps gallery, click Embedded Coder.

  4. Underneath the block diagram, open the Model Data Editor by selecting the Model Data Editor tab.

  5. In the Model Data Editor, select the Parameters tab and update the block diagram.

    Now, the data table contains rows that correspond to workspace variables used by the Gain blocks (which represent the P, I, and D parameters of the controller).

  6. In the Model Data Editor, next to the Filter contents box, activate the Filter using selection button.

  7. In the model, select the three Gain blocks.

  8. In the Filter contents box, enter model workspace.

    The variables that the Gain blocks use are in the model workspace.

  9. In the data table, select the three rows and, in the Storage Class column for a row, select Convert to parameter object.

    The Model Data Editor converts the workspace variables to myPackage.Parameter objects. Now, you can apply a storage class to the objects.

  10. In the Storage Class column for a row, select CalParam.

Configure Generation of ASAP2 Interface

Configure the model to generate a2l files. Select Configuration Parameters > Code Generation > Interface > ASAP2 interface.

Generate and Inspect Code

  1. Generate code from the model.

  2. In the code generation report, inspect the calPrms.c file. The file defines the calibration parameters.

    /* Exported data definition */
    #pragma SEC(CALPRM)
    
    /* Definition for custom storage class: CalParam */
    const volatile real32_T dispGain = 0.75F;
    const volatile real32_T intGain = 0.5F;
    const volatile real32_T rateGain = 2.0F;
    
    #pragma SEC()

    The file calPrms.h declares the parameters.

  3. Inspect the interface file rtwdemo_roll.a2l. The file contains information about each parameter, for example, for dispGain.

    /begin CHARACTERISTIC
      /* Name                   */      dispGain  
      /* Long Identifier        */      ""
      /* Type                   */      VALUE 
      /* ECU Address            */      0x0000 /* @ECU_Address@dispGain@ */ 
      /* Record Layout          */      Scalar_FLOAT32_IEEE 
      /* Maximum Difference     */      0 
      /* Conversion Method      */      rtwdemo_roll_CM_single 
      /* Lower Limit            */      -3.4E+38 
      /* Upper Limit            */      3.4E+38
    /end CHARACTERISTIC

Initialize Parameter Value From System Constant or Other Macro (Embedded Coder)

You can generate code that initializes a tunable parameter with a value calculated from some system constants (macros). For example, you can generate this code, which initializes a tunable parameter totalVol with a value calculated from macros numVessels and vesInitVol:

#define numVessels 16
#define vesInitVol 18.2

double totalVol = numVessels * vesInitVol;

This initialization technique preserves the mathematical relationship between the tunable parameter and the system constants, which can make the generated code more readable and easier to maintain. To generate this code:

  1. Create parameter objects that represent the system constants.

    numVessels = Simulink.Parameter(16);
    vesInitVol = Simulink.Parameter(18.2);

  2. Configure the objects to use the storage class Define, which yields a macro in the generated code.

    numVessels.CoderInfo.StorageClass = 'Custom';
    numVessels.CoderInfo.CustomStorageClass = 'Define';
    
    vesInitVol.CoderInfo.StorageClass = 'Custom';
    vesInitVol.CoderInfo.CustomStorageClass = 'Define';

  3. Create another parameter object that represents the tunable parameter. Configure the object to use the storage class ExportedGlobal, which yields a global variable in the generated code.

    totalVol = Simulink.Parameter;
    totalVol.CoderInfo.StorageClass = 'ExportedGlobal';

  4. Set the value of totalVol by using the expression numVessels * vesInitVol. To specify that the generated code preserve the expression, use the slexpr function.

    totalVol.Value = slexpr('numVessels * vesInitVol');

  5. Use totalVol to set block parameter values in your model. The code that you generate from the model initializes the tunable parameter with a value based on the system constants.

For more information and limitations about using an expression to set the value of a Simulink.Parameter object, see Set Variable Value by Using a Mathematical Expression (Simulink).

Code Generation Impact of Storage Location for Parameter Objects

You can create a parameter object in the base workspace, a model workspace, or a data dictionary. However, when you end your MATLAB session, variables in the base workspace are deleted. To determine where to store parameter objects and other variables that a model uses, see Determine Where to Store Variables and Objects for Simulink Models (Simulink).

The location of a parameter object can impact the file placement of the corresponding data definition in the generated code.

  • If you place a parameter object in the base workspace or a data dictionary, the code generator assumes that the corresponding parameter data (for example, a global variable) belongs to the system from which you generate code, not to a specific component in the system. For example, if a model in a model reference hierarchy uses a parameter object with a storage class other than Auto, the data definition appears in the code generated for the top model in the hierarchy, not in the code generated for the model that uses the object.

    However, if you have Embedded Coder®, some storage classes enable you to specify the name of the model that owns a piece of data. When you specify an owner model, the code generated for that model defines the data. For more information about data ownership, see Control Placement of Global Data Definitions and Declarations in Generated Files (Embedded Coder).

  • If you place a parameter object in a model workspace, the code generator assumes that the model owns the data. If you generate code from a reference hierarchy that includes the containing model, the data definition appears in the code generated for the containing model.

    For more information about data ownership, see Control Placement of Global Data Definitions and Declarations in Generated Files (Embedded Coder).

  • If you apply a storage class other than Auto to a parameter object, the object appears in the generated code as a global symbol. Therefore, in a model reference hierarchy, two such objects in different model workspaces or dictionaries cannot have the same name. The name of each object must be unique throughout the model hierarchy.

    However, if you have Embedded Coder, you can use the storage class FileScope to prevent name clashes between parameter objects in different model workspaces. See Apply Built-In and Customized Storage Classes to Data Elements (Embedded Coder).

If you store an AUTOSAR.Parameter object in a model workspace, the code generator ignores the storage class that you specify for the object.

Configure Accessibility of Signal Data

When you tune the value of a parameter during algorithm execution, you monitor or capture output signal values to analyze the results of the tuning. To represent signals in the generated code as accessible data, you can use techniques such as test points and storage classes. See Preserve Variables in Generated Code.

Programmatic Interfaces for Tuning Parameters

You can configure the generated code to include:

Set Tunable Parameter Minimum and Maximum Values

It is a best practice to specify minimum and maximum values for tunable parameters.

You can specify these minimum and maximum values:

  • In the block dialog box that uses the parameter object. Use this technique to store the minimum and maximum information in the model.

  • By using the properties of a Simulink.Parameter object that you use to set the parameter value. Use this technique to store the minimum and maximum information outside the model.

For more information, see Specify Minimum and Maximum Values for Block Parameters (Simulink).

Considerations for Other Modeling Goals

GoalConsiderations and More Information
Apply storage type qualifiers const and volatile

If you have Embedded Coder, to generate the storage type qualifiers, see Protect Global Data with const and volatile Type Qualifiers (Embedded Coder).

Prevent name clashes between parameters in different components by applying the keyword static

If you have Embedded Coder, use the storage class FileScope or a similar storage class that you create. See Choose Storage Class for Controlling Data Representation in Generated Code (Embedded Coder).

Generate ASAP2 (a2l) description

You can generate an a2l file that uses the ASAP2 standard to describe your calibration parameters. For more information, see Define ASAP2 Information for Parameters and Signals.

Generate AUTOSAR XML (ARXML) description

If you have Embedded Coder, you can generate an ARXML file that describes calibration parameters used by models that you configure for the AUTOSAR standard. See Model AUTOSAR Calibration Parameters and Lookup Tables (AUTOSAR Blockset).

Store lookup table data for calibration

To store lookup table data for calibration according to the ASAP2 or AUTOSAR standards (for example, STD_AXIS, COM_AXIS, or CURVE), you can use Simulink.LookupTable and Simulink.Breakpoint objects in lookup table blocks.

However, some limitations apply. See Simulink.LookupTable. To work around the limitations of Simulink.LookupTable and Simulink.Breakpoint objects, use Simulink.Parameter objects instead.

For more information, see Define ASAP2 Information for Parameters and Signals and Configure Lookup Tables for AUTOSAR Measurement and Calibration (AUTOSAR Blockset).

Use pragmas to store parameter data in specific memory locations

If you have an Embedded Coder license, to generate code that includes custom pragmas, use storage classes and memory sections. See Control Data and Function Placement in Memory by Inserting Pragmas (Embedded Coder).

See Also

| |

Related Topics