Prepare Sensor and Controller Models in a Distributed Monitoring System for Code Generation
This example shows how to take a Simulink® model containing a reusable algorithm and prepare that model to generate code that is deployable on a target hardware platform where the algorithm is implemented in a component as part of a system. The algorithms are contained in the controller and sensor models from the tire pressure monitoring system described in Wireless Tire Pressure Monitoring System with Fault Logging. The algorithms themselves do not depend on the hardware platform, but the inputs and outputs at the component interfaces are platform-dependent. The example shows how to integrate custom code to handle these aspects of the operation of the components:
Receiving data from the physical environment
Communication between components
Sending signals to other systems
Interacting with non-volatile memory (NVM)
NVM is used to store the unique device IDs of the sensors in the system and to maintain the fault log between power cycles. By using NVM, the same code can be burnt into the CPU on multiple devices during manufacturing, and the unique IDs can be subsequently flashed into NVM.
Run this command to create and open a working copy of the project files for this example:
Sensor Wrapper Model
To generate code for the sensor units, the sensor model
sensorCoreAlgorithm is placed inside a wrapper model that is used as the top-level model for code generation. The local device ID parameter of the sensor model is a dummy value. The wrapper model contains an Initialize Function block that reads the local device ID for the sensor from NVM on power-up and writes it to the sensor model device ID parameter using a Parameter Writer block. Reading from NVM is performed by a MATLAB Function block, which calls custom code for this purpose.
Similarly, MATLAB Function blocks that call custom code are used to retrieve tire pressure measurement data from the sensor and to send the data to the controller. The measurement data are fed as input to the sensor model. A Message Receive block receives the messages that are output from the sensor model and extracts the payload, which is passed to a MATLAB Function block for transmission to the controller via wireless communication, middleware, or a combination of both.
SensorTargetSpecificCodeExternalDependency.m defines the MATLAB class
SensorTargetSpecificCodeExternalDependency as a subclass of the
coder.ExternalDependency (MATLAB Coder) class. The
coder.ExternalDependency class is a base class that is useful for interfacing with external C/C++ code from MATLAB code. See Develop Interface for External C/C++ Code (MATLAB Coder). The
classdef defines public methods to read from NVM, read pressure data, and transmit data. The MATLAB Function blocks in the sensor wrapper model call these methods to perform these functions. These methods in turn call custom C code functions using
coder.ceval (MATLAB Coder). These custom code functions are defined in
sensor_hand_code_source.c. For the purpose of this example, these files contain stub functions, which allow the model to compile and to generate code that implements the desired algorithm using generic driver calls. To generate and deploy code on a particular hardware target, replace the stubs with the corresponding target-specific code.
Controller Wrapper Model
To generate code for the controller units, the controller model
controllerCoreAlgorithm is placed inside a wrapper model that is used as the top-level model for code generation. The sensor device ID list parameter of the controller model is a dummy value. The wrapper model contains an Initialize Function block that reads the sensor device ID list for the system from NVM on power-up and writes it to the sensor device ID list parameter using a Parameter Writer block. The Initialize Function block also reads the previously saved contents of the fault log from NVM and loads them into RAM by using a Data Store Write block to write them to the data store that is used for the fault log while the system is operating.
The wrapper model contains a Terminate Function block that executes on power-down. The Terminate Function block reads the updated contents of the fault log using a Data Store Read block and writes these contents to NVM. In this way, the fault log contents are maintained between power cycles.
Reading from and writing to NVM are performed by MATLAB Function blocks, which call custom code for this purpose. Interacting with NVM only on startup and shutdown and using RAM for memory needs during operation minimizes wear and tear on NVM.
The controller wrapper model contains a MATLAB Function block that calls custom code to receive message communications from the sensors. At one outport, the block outputs a function call signal each time a message is received and outputs the message payload at the other outport. These outputs are used to drive a function-call subsystem, which uses a Message Send block to send a message containing the payload each time it receives a function-call signal.
This message is sent to the controller model message input port through a Queue block that represents a LIFO, overwriting-type queue. The function-call subsystem and the Queue block implement an internal queue in the code that is generated for deployment to the controller hardware.
The logical output signal of the controller block is fed into a MATLAB Function block in order to enable a warning lamp and again calls custom code for this purpose.
ControllerTargetSpecificCodeExternalDependency.m defines the MATLAB class
ControllerTargetSpecificCodeExternalDependency as a subclass of the
coder.ExternalDependency class. The
classdef defines public methods to read from and write to NVM, receive message communications, and enable a warning lamp. The MATLAB Function blocks in the controller wrapper model call these methods to perform these functions. These methods in turn call custom C code functions using
coder.ceval. These custom code functions are defined in
controller_hand_code_source.c. For the purpose of this example, these files contain stub functions, which allow the model to compile and to generate code that implements the desired algorithm using generic driver calls. To generate and deploy code on a particular hardware target, replace the stubs with the corresponding target-specific code.