Main Content

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 InlineBlockParameters and configure it to show the generated names of blocks.

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

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 model workspace.

In the myGainParam dialog box, on the Code Generation tab, click Configure in Coder App.

In the Code Mappings editor, set Storage Class of myGainParam to ExportedGlobal. 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('InlineBlockParameters/G1','Gain','myGainParam')
mws = get_param('InlineBlockParameters', 'modelworkspace');
mws.assignin('myGainParam',Simulink.Parameter(2));
cm = coder.mapping.utils.create('InlineBlockParameters');
setModelParameter(cm,'myGainParam','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('InlineBlockParameters/G2','Gain','myOtherGain')
mws.assignin('myOtherGain',Simulink.Parameter(-2));
setModelParameter(cm,'myOtherGain','StorageClass','ExportedGlobal');

Generate and Inspect Code

Generate code from the model.

slbuild('InlineBlockParameters')
### Starting build procedure for: InlineBlockParameters
### Successful completion of build procedure for: InlineBlockParameters

Build Summary

Top model targets:

Model                  Build Reason                                         Status                        Build Duration
========================================================================================================================
InlineBlockParameters  Information cache folder or artifacts were missing.  Code generated and compiled.  0h 0m 17.262s 

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 19.391s

The generated file InlineBlockParameters.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('InlineBlockParameters_grt_rtw','InlineBlockParameters.h');
coder.example.extractLines(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 InlineBlockParameters.c allocates memory for and initializes myGainParam and myOtherGain.

file = fullfile('InlineBlockParameters_grt_rtw','InlineBlockParameters.c');
coder.example.extractLines(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.

coder.example.extractLines(file,...
    '/* Model step function */','/* Model initialize function */',1,0)
/* Model step function */
void InlineBlockParameters_step(void)
{
  /* Outport: '<Root>/Out1' incorporates:
   *  Gain: '<Root>/G1'
   *  Gain: '<Root>/G2'
   *  Inport: '<Root>/In1'
   *  Sum: '<Root>/Sum'
   */
  InlineBlockParameters_Y.Out1 = myGainParam * InlineBlockParameters_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). 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

Create a package in your current folder. Add definitions of a new storage class and an associated memory section to the package. Then, apply the storage class to data objects in models.

  1. Open the example containing the package MATLAB® namespace folder +myPackage. The package stores definitions of Parameter and Signal classes.

    openExample('ecoder/ExploreExampleModelCustomStorageClassesExample')

  2. Navigate inside the namespace folder +myPackage to the file Signal.m.

  3. Open Signal.m and uncomment the methods section that defines method setupCoderInfo. In the call to the function useLocalCustomStorageClasses, replace 'packageName' with 'myPackage'.

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

  4. Save and close the file.

  5. Open the file Parameter.m and make the same changes that you made in the file Signal.m.

  6. Save and close the file.

Create Storage Class and Memory Section

  1. Set your current folder to the folder that contains the package namespace 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 to the values listed in this 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 to the values listed in this 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 RollAxisAutopilot, the BasicRollMode subsystem represents a PID controller. Configure the P, I, and D parameters as calibration parameters.

  1. Open the model.

    openExample('RollAxisAutopilot');

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

  3. Open the Embedded Coder app.

  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.

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 RollAxisAutopilot.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      */      RollAxisAutopilot_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.

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.

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 Organize Parameter Data into a Structure by Using Struct Storage Class (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:

  • A C application programming interface (API) for tuning parameters independent of external mode. The generated code includes extra code so that you can write your own code to access parameter values. See Write External Code to Access Generated C API Code.

  • A Target Language Compiler API for tuning parameters independently of external mode. See Parameter Functions.

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.

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 Generate ASAP2 and CDF Calibration Files.

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 Lookup Tables and Configure Lookup Tables for AUTOSAR Calibration and Measurement (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