Main Content

Perform XCP Operations on Deployed Simulink Model

This example shows how to use the XCP protocol capability to perform basic XCP operation from a Simulink® model deployed to a Windows® executable. The example performs XCP operations on TCP protocol, including modifying the characteristic parameters of the model using direct memory access and reading measurement parameters of the model using direct memory access and dynamic DAQ list.

XCP is a high-level protocol used for accessing and modifying internal parameters and variables of a model, algorithm, or ECU. For more information, refer to the ASAM standard.

Algorithm Overview

The algorithm used in this example is a Simulink model built and deployed as an XCP server. The model has already been compiled and is available to run in the file XCPServerSineWaveGenerator.exe. Additionally, the A2L-file XCPServerSineWaveGenerator.a2l is provided as an output of that build process. The model contains three measurements and two characteristics accessible via XCP. Because the model is already deployed, Simulink is not required to run this example. The following image illustrates the model.

For details about how to build a Simulink model, including an XCP server and generating an A2L-file, see Export ASAP2 File for Data Measurement and Calibration (Simulink Coder).

Run the XCP Server Model

To communicate with the XCP server, the deployed model must be run. By using the system function, you can execute the XCPServerSineWaveGenerator.exe from inside MATLAB®. The function requires constructing an argument list pointing to the executable. A separate command window opens and shows running outputs from the server. The input pwd gets the present working directory.

sysCommand = ['"', fullfile(pwd, 'XCPServerSineWaveGenerator.exe'),'"', ' &'];
system(sysCommand);

Open the A2L-File

Use the xcpA2L function to open the A2L-file that describes the server model.

a2lInfo = xcpA2L("XCPServerSineWaveGenerator.a2l");

TCP is the transport protocol used to communicate with the XCP server. Details for the TCP connection, such as the IP address and port number, are contained in the TransportLayerTCPInfo property.

a2lInfo.TransportLayerTCPInfo
ans = 
  XCPonIP with properties:
          CommonParameters: [1×1 xcp.a2l.CommonParameters]
    TransportLayerInstance: ''
                      Port: 17725
                   Address: 2.1307e+09
             AddressString: '127.0.0.1'

Create an XCP Channel

To create an active XCP connection to the server, use the xcpChannel function. The function requires a reference to the server A2L-file and the type of transport protocol (TCP only in this example) to use for messaging with the server.

xcpCh = xcpChannel(a2lInfo, "TCP")
xcpCh = 
  Channel with properties:

              ServerName: 'ModuleName'
             A2LFileName: 'XCPServerSineWaveGenerator.a2l'
          TransportLayer: 'TCP'
    TransportLayerDevice: [1×1 struct]
              SeedKeyDLL: []

Connect to the Server

To make communication with the server active, use the connect function.

connect(xcpCh)

Read XCP Measurements with Direct Acquisition

This section demonstrates reading measurement parameters of the model using function readMeasurement for direct memory access to the model server.

Directly Acquire Measurement Data

The readMeasurement function acquires the current value for a given measurement from the server.

readMeasurement(xcpCh, "Sine") 
ans = 0
readMeasurement(xcpCh, "SineAfterGain")
ans = -1.9021
readMeasurement(xcpCh, "SineAfterTable")
ans = -0.9511

Read XCP Measurements with Dynamic DAQ Lists

Apart from direct memory access to aquire the data, the other way to read measurement data is using dynamic DAQ lists. This section demonstrates reading measurement parameters of the model using dynamic DAQ lists.

Create and View a Measurement List

Use the createMeasurementList function to create a dynamic DAQ list.

createMeasurementList(xcpCh, "DAQ", "100 ms", ["Sine", "SineAfterGain", "SineAfterTable"]) 

Acquire Data form XCP server

Start the configured dynamic DAQ list using the startMeasurement function. After running for a few seconds, stop measurements using the stopMeasurement function.

startMeasurement(xcpCh)
pause(3);
stopMeasurement(xcpCh)

Retrieve the Sine Measurement Data

To retrieve the acquired data from the XCP channel for the Sine measurement, use the readDAQ function.

dataSine = readDAQ(xcpCh, "Sine");
plot(dataSine, "o-")
title("Sine Measurement Data")
xlabel("Data Point")
ylabel("Data Value")

Retrieve the SineAfterGain Measurement Data

To retrieve the acquired data from the XCP channel for the SineAfterGain measurement, use the readDAQ function.

dataSineAfterGain = readDAQ(xcpCh, "SineAfterGain");
plot(dataSineAfterGain, "o-")
title("SineAfterGain Measurement Data")
xlabel("Data Point")
ylabel("Data Value")

Retrieve the SineAfterTable Measurement Data

To retrieve the acquired data from the XCP channel for the SineAfterTable measurement, use the readDAQ function.

dataSineAfterTable = readDAQ(xcpCh, "SineAfterTable");
plot(dataSineAfterTable, "o-")
title("SineAfterTable Measurement Data")
xlabel("Data Point")
ylabel("Data Value")

Free the Measurement List

Free the measurement lists using the freeMeasurementLists function.

freeMeasurementLists(xcpCh);

Calibrate XCP Characteristics

This section demonstrates calibrating measurement parameters of the model using direct memory access. Note that two parameters are used in this section, Gain is the multiplier and ydata specifies the output data points of the 1-D look-up table.

Inspect Preloaded Characteristic Values

Read the current value of the characteristic Gain using readCharacteristic function.

initialGain = readCharacteristic(xcpCh, "Gain")
initialGain = 2

Read the current 1-D look-up table characteristic using readAxis and readCharacteristic, then plot the mapping. This table effectively maps any positive input value to zero output.

inputBreakpoints = readAxis(xcpCh, "xdata")
inputBreakpoints = 1×7

   -1.0000   -0.5000   -0.2000         0    0.2000    0.5000    1.0000

outputPoints = readCharacteristic(xcpCh, "ydata")
outputPoints = 1×7

   -1.0000   -0.5000   -0.2000         0         0         0         0

plot(inputBreakpoints, outputPoints);
title("Initial 1-D Look-up Table Map");
xlabel("Input Value");
ylabel("Output Value");

Create a Measurement List

This example explores the value of the measurement Sine, unmodified and modified by the two characteristics. To visualize the continuously changing value of Sine pre- and post-calibration, acquire measurement data values using a DAQ list. Use the createMeasurementList function to create a DAQ list containing all Sine-based measurements available from the server.

createMeasurementList(xcpCh, "DAQ", "100 ms", ["Sine", "SineAfterGain", "SineAfterTable"])

Obtain Measurements Before Calibration

Use the startMeasurement function and stopMeasurement function to run the DAQ list for a short period of time.

startMeasurement(xcpCh);
pause(3);
stopMeasurement(xcpCh);

To retrieve the data acquired by the DAQ list for all the Sine-based measurements, use the readDAQ function. The number of retrieved samples during 3 seconds at 100 ms event is expected to be 30, but because the XCP server runs on Windows, which is not a real-time operating system, the actual number of retrieved samples might be less than 30, depending on how occupied the operating system is.

sine = readDAQ(xcpCh, "Sine");
sineAfterGain = readDAQ(xcpCh, "SineAfterGain");
sineAfterTable = readDAQ(xcpCh, "SineAfterTable");

Inspect Measurements Before Calibration

Plot the SineAfterGain measurement against the base Sine measurement. The value after Gain is boosted by a factor of 2, based on the original measurement, because the preloaded value of the characteristic Gain is 2, as shown previously.

plot(sine, "o-"); hold on;
plot(sineAfterGain, "*-"); hold off;
title("Before Calibration: Sine Signal vs Sine Signal after Gain");
legend("Original", "After Gain");
xlabel("Data Point");
ylabel("Data Value");

Plot the SineAfterTable measurement against the base Sine measurement. Any positive value of the original measurement is mapped to zero according to the preloaded 1-D look-up table, therefore the modified signal looks truncated and does not have any positive values.

plot(sine, "o-"); hold on;
plot(sineAfterTable, "*-"); hold off;
title("Before Calibration: Sine Signal vs Sine Signal after Table");
legend("Original", "After Table");
xlabel("Data Point");
ylabel("Data Value");

Calibrate the Gain and 1-D Look-up Table

Write a new value to the charateristic Gain using writeCharacteristic, and perform a read to verify the change using readCharacteristic.

writeCharacteristic(xcpCh, "Gain", 0.5);
newGain = readCharacteristic(xcpCh, "Gain")
newGain = 0.5000

Write new data points to the output of the 1-D look-up table using writeCharacteristic.

writeCharacteristic(xcpCh, "ydata", [0 0 0 0 0.2 0.5 1]);

Read the new 1-D look-up table data using readAxis and readCharacteristic, then plot the mapping. Now the table effectively maps any negative input value to zero output.

inputBreakpoints = readAxis(xcpCh, "xdata")
inputBreakpoints = 1×7

   -1.0000   -0.5000   -0.2000         0    0.2000    0.5000    1.0000

newOutputPoints = readCharacteristic(xcpCh, "ydata")
newOutputPoints = 1×7

         0         0         0         0    0.2000    0.5000    1.0000

plot(inputBreakpoints, newOutputPoints);
title("New 1-D Look-up Table Map");
xlabel("Input Value");
ylabel("Output Value");

Obtain Measurements After Calibration

Use the startMeasurement function and stopMeasurement function to run the DAQ list for a short period of time.

startMeasurement(xcpCh);
pause(3);
stopMeasurement(xcpCh);

To retrieve the data acquired by the DAQ list for all the Sine-based measurements, use the readDAQ function.

sine = readDAQ(xcpCh, "Sine");
sineAfterGain = readDAQ(xcpCh, "SineAfterGain");
sineAfterTable = readDAQ(xcpCh, "SineAfterTable");

Inspect Measurements After Calibration

Plot the SineAfterGain measurement against the base Sine measurement. Now the value after Gain is decreased by a factor of 2, based on the original measurement, because the value of the characteristic Gain is set to 0.5 after calibration.

plot(sine, "o-"); hold on;
plot(sineAfterGain, "*-"); hold off;
title("After Calibration: Sine Signal vs Sine Signal after Gain");
legend("Original", "After Gain");
xlabel("Data Point");
ylabel("Data Value");

Plot the SineAfterTable measurement against the base Sine measurement. Any negative value of the original measurement is mapped to zero according to the new 1-D look-up table, therefore the modified signal looks truncated differently and does not have any negative values.

plot(sine, "o-"); hold on;
plot(sineAfterTable, "*-"); hold off;
title("After Calibration: Sine Signal vs Sine Signal after Table");
legend("Original", "After Table");
xlabel("Data Point");
ylabel("Data Value");

Disconnect from the Server

To make communication with the server inactive, use the disconnect function.

disconnect(xcpCh)

Clean Up

clear a2lInfo