Main Content

Log CAN Bus Data on Raspberry Pi

This example shows how to use Simulink® Support Package for Raspberry Pi® Hardware to monitor a controller area network (CAN) bus, perform basic CAN conversions, and log CAN data in a measurable data format (MDF) file. This example also showcases the interoperability between a model deployed in Simulink and a Python program running simultaneously on Raspberry Pi hardware.

The automotive industry extensively uses CAN due to its robustness, real-time capabilities, and ability to efficiently transfer data. This example uses the latest MDF4 format to store the CAN data. This format enables you to analyze and interpret the data offline without any constraints of real-time processing. The format enables efficient data compression and provides support for more complex data structures.

Simulink Models and Supported Files

Implementing this example requires you to successfully deploy these Simulink models and run a Python script on your Raspberry Pi board.

Example Workflow

This diagram explains the relationship and dependencies between the components and processes used in the example such as the Raspberry Pi board, CAN bus, interprocess communication, and MDF logging.

Use Simulink to create and deploy a model on the Raspberry Pi hardware to receive CAN data. Run a Python script on the Raspberry Pi hardware to log the received CAN data in the MDF format. Transfer the MDF file from Raspberry Pi to Simulink for further analysis. Because the various components in the system interact in real time, you can record the the relevant data in an MDF file for future analysis or troubleshooting purposes.

Installing Third-Party Libraries and Packages

When installing Simulink Support Package for Raspberry Pi Hardware, make sure to set up these third-party libraries and packages that are included in the interprocess communication bundle.

  • nng

  • ninja_build

For more information, see Modularize Installation of Third-Party Packages and Libraries for Raspberry Pi Hardware.

Hardware Requirements

You need these components to set up CAN bus communication using Raspberry Pi:

Hardware Connections

Connect both the CANH lines between the CAN shield and CAN bus. Similarly, connect both the CANL lines between the CAN shield and CAN bus.

Configuring CAN Modules

For this example, use these pointers while configuring the CAN modules:

  • This example uses physical CAN hardware to ensure accurate communication and data logging. For setting up a virtual CAN interface, see Setup Virtual CAN Interface.

  • This example uses dual-shield CAN modules, can0 and can1, where can1 is used for transmission of CAN data and can0 is used for reception of CAN data.

  • For configuring CAN modules other than MCP2515, refer to the vendor datasheet or manual.

  • To initiate CAN communication on your Raspberry Pi, make sure to enable SPI communication on your board. After you enable SPI communication, individually configure the can0 and can1 modules by adjusting the oscillator frequency and specifying the interrupt pins. For more information, see Enable and Configure Raspberry Pi for SPI and CAN Communication Using MCP2515 CAN Controller.

  • The loopback connection of the CANH and CANL lines creates a direct communication between the CAN shield and the CAN bus.

  • After you configure the CAN modules, make sure to reboot your Raspberry Pi board for the changes to apply.

Configure raspberrypi_CAN_traffic_generator Simulink Model

Use the raspberrypi_CAN_traffic_generator Simulink Model to transmit CAN messages over the MCP2515 CAN controller bus connected to your Raspberry Pi board.

Open the raspberrypi_CAN_traffic_generator Simulink model.

This model uses two CAN Transmit blocks, with the CAN Transmit 1 block using data of message ID 100 and the CAN Transmit 2 block using 103. Input raw data to the two CAN Transmit blocks as a two-element vector. The can1 module transmits CAN data.

Configure these parameters in the Block Parameters dialog box of the CAN Transmit 1 block.

  1. Set CAN interface to can1.

  2. Set Data is input as to Raw data.

  3. Set Timeout in seconds to 1.

  4. Set Message ID to 100.

  5. Set Message length to 2.

For more information, see CAN Transmit block

Configure these parameters in the Block Parameters dialog box of the CAN Transmit 2 block.

  1. Set CAN interface to can1.

  2. Set Data is input as to Raw data.

  3. Set Timeout in seconds to 1.

  4. Set Message ID to 103.

  5. Set Message length to 1.

For more information, see CAN Transmit block

The sample time of Counter 1 is 0.5 seconds while that of Counter 2 is 0.1 seconds. Based on these values, the CAN Transmit 1 block transmits 2 counter values per second and CAN Transmit 2 block transmits 10 counter values per second. You can observe these value while logging the CAN data in MATLAB®. For more information on the Counter block, see Counter Limited.

Configure these parameters in the Configuration Parameters dialog box > Target hardware resources > CAN parameters of the raspberrypi_CAN_traffic_generator Simulink Model.

  1. Select Configure CAN interface.

  2. Set Number of CAN interfaces to 1.

  3. Set CAN interface to can1.

  4. Set CAN interface type to Real.

  5. Set CAN Bus Speed (kBits/s) to 500.

  6. Set Transmit queue buffer size to 65536.

For more information on configuring CAN modules, see CAN.

Configure raspberrypi_CAN_MDF_logging Simulink Model

Use the raspberrypi_CAN_MDF_logging Simulink model to receive the CAN raw data on message IDs 100 and 103 and log the data in an MDF file. Observe that the Simulink model utilizes a single CAN Receive block to listen to all messages on the bus in the CAN Msg mode. This behavior is due to the broadcasting nature of the CAN bus and the ability to filter and process messages based on their identifiers.

Open the raspberrypi_CAN_MDF_logging Simulink model.

The model uses the can0 module to receive CAN data. The model also uses the CAN Unpack blocks from the Vehicle Network Toolbox™ to unpack the CAN messages from the CAN bus. The CAN Unpack 1 block unpacks individual signals from CAN message IDs 100 and 101, while the CAN Unpack 2 block unpacks signals from CAN message ID 103. For this example, retrieve data, timestamp, and status signals from the CAN Unpack blocks in the model. For more information, see CAN Unpack (Vehicle Network Toolbox).

Configure these parameters in the Block Parameters dialog box of the CAN Receive block.

  1. Set CAN interface to can0.

  2. Set Data to be output as to CAN Msg.

  3. Set Sample time to 0.05. Make sure that the receiver sampling time is lower than the transmitter sampling time in the CAN Transmit blocks for the raspberrypi_CAN_traffic_generator Simulink model.

Configure these parameters in the Block Parameters dialog box of the CAN Unpack 1 block.

  1. Set Data to output as to raw data.

  2. Set CAN Identifier to 100. Make sure you set the same CAN message ID as you configure in the Message ID parameter of the CAN Transmit blocks in the raspberrypi_CAN_traffic_generator Simulink model.

  3. Set Length (bytes) to 2. Make sure you set the same CAN message length as you configure in the Message length parameter of the CAN Transmit block in the raspberrypi_CAN_traffic_generator Simulink model.

  4. To view timestamp and status output ports, select Output timestamp and Output status.

For more information, see CAN Unpack (Vehicle Network Toolbox).

Configure these parameters in the Block Parameters dialog box of the CAN Unpack 2 block.

  1. Set Data to output as to raw data.

  2. Set CAN Identifier to 103.

  3. Set Length (bytes) to 1.

  4. To view timestamp and status output ports, select Output timestamp and Output status.

For more information, see CAN Unpack (Vehicle Network Toolbox).

Use the Status port output from the CAN Unpack (Vehicle Network Toolbox) blocks to trigger the Log CAN ID 100 and Log CAN ID 103 subsystems. The subsystems are triggered only when the Status port output is 1, which means that the block receives a new CAN message from the CAN bus. The subsystems also receive data and timestamp outputs from the CAN Unpack blocks for further processing.

Use the NNG Send blocks, one for each CAN message ID, to broadcast CAN data to all applications subscribing to the same uniform resource locator (URL). Configure the NNG Send blocks to filter messages by CAN message IDs.

In the block parameters dialog box of the NNG Send block in the Log CAN ID 100 subsystem, set IPC name to canid100.

In the block parameters dialog box of the NNG Send block in the Log CAN ID 103 subsystem, set IPC name to canid103.

Configure these parameters in the Configuration Parameters dialog box > Target hardware resources > CAN parameters of the raspberrypi_CAN_MDF_logging Simulink Model.

  1. Select Configure CAN interface.

  2. Set Number of CAN interfaces to 1.

  3. Set CAN interface to can0.

  4. Set CAN interface type to Real.

  5. Set CAN Bus Speed (kBits/s) to 500.

  6. Set Transmit queue buffer size to 65536.

For more information on configuring CAN modules, see CAN.

Run and Deploy Simulink Models on Raspberry Pi

Follow these steps to deploy the raspberrypi_CAN_traffic_generator.slx and raspberrypi_CAN_MDF_logging.slx Simulink models on your Raspberry Pi. To initiate CAN communication, deploy the raspberrypi_CAN_traffic_generator.slx model on your Raspberry Pi first.

  1. Open the raspberrypi_CAN_traffic_generator.slx model.

  2. On the Hardware tab of the model, in the Deploy section, click Build, Deploy & Start.

  3. Open the raspberrypi_CAN_MDF_logging model.

  4. On the Hardware tab of the model, in the Run on Hardware section, click Monitor & Tune.

Use the Simulation Data Inspector application to visualize the Counter Limited and Counter Limited CAN data that the CAN Unpack (Vehicle Network Toolbox) blocks output on the Data port in the raspberrypi_CAN_MDF_logging model.

Log CAN Data into MDF File

Use the raspberrypi_can_bus_logger.py Python script to log data into an MDF file on the Raspberry Pi hardware. You can locate this file in the current directory of the example folder. The script sets up a multi-threaded environment to listen for CAN messages on IPC channels and logs it into an MDF4 file format. It uses the ASAM MDF library to handle the data format and ensures thread safety with locks during data updates. In the raspberrypi_can_bus_logger.py Python script, make sure to capture these points and take care to match them with specific parameters in the blocks of the Simulink models.

Run raspberrypi_can_bus_logger.py Python Script on Raspberry Pi Terminal

When you install the support package, MATLAB creates the virtual environment required to run a Python script on your Raspberry Pi hardware by installing the core bundle third-party libraries and packages.

In the MATLAB Command Window, execute these command to open the Raspberry Pi terminal.

r=raspberrypi('<Raspberry Pi IP address>','<Raspberry Pi username>','<Raspberry Pi password>');
r.openShell

Transfer the raspberrypi_can_bus_logger.py file from the host computer to the Raspberry Pi. Simulink places this Python script in the current folder of the Raspberry Pi.

r.putFile('raspberrypi_can_bus_logger.py')

In the Raspberry Pi terminal, execute this command to activate a Python virtual environment of Linux®.

source /opt/mw_venv/bin/activate

Install the NNG and asammdf libraries on the Raspberry Pi.

pip3 install pynng
pip3 install asammdf

Execute the raspberrypi_can_bus_logger.py script on the Raspberry Pi to capture CAN specifications for CAN messages.

python3 raspberrypi_can_bus_logger.py

Let this command run on your Raspberry Pi for some time. You will receive these messages when the command is runs on your Raspberry Pi.

Starting thread for CAN Msg ID: 100
Starting thread for CAN Msg ID: 103

This script keeps running for infinity on your Raspberry Pi. Press Ctrl+C to kill the Python script. This process generates the MF4 file in the current folder of your Raspberry Pi. You can view this message on the Raspberry Pi terminal.

Preparing to save data to can_bus_data.mf4
Saved. All done!

In the MATLAB Command Window, execute this command to transfer the can_bus_data.mf4 file from the Raspberry Pi to your host computer. Observe the file in the current working directory on your MATLAB session.

r.getFile('can_bus_data.mf4')

Get channel metadata from MDF file. This function returns a table of information about all channels in the can_bus_data.mf4 MDF file.

canLoggedDataInfo = mdfChannelInfo("can_bus_data.mf4")

Read all available data from the can_bus_data.mf4 MDF file and assign the output to the cell array data.

canLoggedData = mdfRead('can_bus_data.mf4')

Access the first element of the canLoggedData variable.

canLoggedData{1}

You can utilize the support package, along with Python and interprocess communication capabilities, to efficiently analyze and process CAN data offline according to your requirements.

Other Things to Try

Instead of using the raspberrypi_CAN_traffic_generator.slx model to generate CAN data, you can use any other source to generate CAN data. In this case, deploy only the raspberrypi_CAN_MDF_logging.slx model on your Raspberry Pi and adjust the code in the Python script accordingly.

See Also