Learning MATLAB/Simulink and Arduino — Device Integration with Custom S-Function Blocks

| 11 min read
Author: shuichi-takatsu shuichi-takatsuの画像
Information

To reach a broader audience, this article has been translated from Japanese.
You can find the original version here.

#

Arduino supports a wide range of devices, but there are many sensors and displays not directly supported by Simulink.
This is where custom blocks using S-Function come in handy.
In this article, using the OLED Display SSD1306 as an example, we will introduce the steps to create a custom S-Function block for Simulink and run it on Arduino.


Preparation of the Development Environment

#
  • Software
    • MATLAB (Version: R2025a)
    • Simulink (Version: 25.1)
  • Add-Ons (for Simulink)
    • Simulink Support Package for Arduino Hardware (Version: 25.1.0)
  • Hardware
    • Arduino Uno (or compatible board)
    • USB cable (for communication between PC and Arduino)
    • HC-SR04 (ultrasonic distance sensor)
    • OLED SSD1306 (I2C-connected display)

Detailed Steps for Environment Setup:

#

1. Installing MATLAB/Simulink and Basic Packages

For instructions on installing MATLAB, Simulink, and the Arduino Support Package, refer to the previous article.

2. Installing the Rensselaer Arduino Support Package Library

  • Launch MATLAB → from the menu select Add-OnsGet Hardware Support Packages (the Add-On Explorer will open)

  • In the search box, type "Arduino" and select Rensselaer Arduino Support Package Library (RASPLib)

  • Click Install to add the package

  • After installation, the "Rensselaer Arduino Support Package Library" blocks will be added to the Simulink library


    Inside, there is a block for the ultrasonic distance sensor HC-SR04. We will use this block to operate the HC-SR04.


Circuit Connections

#

HC-SR04

#
  • VCC → Arduino 5V
  • GND → Arduino GND
  • Trig → Arduino Digital Pin 7 (example)
  • Echo → Arduino Digital Pin 8 (example)

OLED SSD1306 (I2C)

#
  • VCC → Arduino 3.3V or 5V
  • GND → Arduino GND
  • SCL → Arduino A5 (for Uno)
  • SDA → Arduino A4 (for Uno)

Creating the S-Function Block for SSD1306

#

The HC-SR04 is supported by RASPLib, but since we couldn't find a dedicated block for the SSD1306, we will create one ourselves using an S-Function block.

The key point here is that features not directly supported by Simulink can be supplemented by calling Arduino libraries. Arduino libraries are collections of device-control functions written in C/C++, and can be invoked from a Simulink model via an S-Function. This allows even devices not supported by Simulink to be operated by leveraging the extensive Arduino library ecosystem.

Selecting an Arduino OLED SSD1306 Library

#

Well-known Arduino OLED libraries include:

However, since these may not fit into the Uno's flash memory, we will use the more lightweight U8g2_Arduino. U8g2 is feature-rich, but considering the Uno's memory constraints, we will use only the U8x8 text mode in this example.

Creating the Project

#

The S-Function Builder can be used on its own, but when dealing with multiple S-Functions, it's convenient to use the Simulink Project feature.

  1. Creating a New Project
    • In MATLAB, select "New → Project → Blank Project"
    • The chosen folder becomes the "Project Folder"

This approach makes it easier to organize multiple devices and enhances reusability.

Creating the Library

#
  1. Creating a New Simulink Library

    • Launch MATLAB and open the Simulink Library Browser using the simulink command
    • From the menu, select "New → Library" to create an empty library file
    • You will add your custom blocks here
  2. Placing the S-Function Builder Block

    • Place an "S-Function Builder" block in the new library
    • The generated .cpp and .tlc files will be managed in sync with the library
  3. Preparing External Libraries

    • Prepare so that Arduino headers like Wire.h and U8x8lib.h can be included
    • Place U8g2_Arduino in, for example, C:\ProgramData\MATLAB\thirdpartylibs\U8g2_Arduino
    • Also verify the Support Package path according to your environment

Creating the Block with S-Function Builder

#

In this example, we will simplify the specifications and design for operation with minimal memory. The specification is to display a single line of ASCII text (up to 16 characters) on an SSD1306 128×64 (I²C) using U8g2's U8x8 text mode.

Project Name: sfun_ssd1306_u8x8_display_block
S-Function Name: sfun_ssd1306_u8x8_display
Language: C++

  • Source code:
/* Includes_BEGIN */
#ifndef MATLAB_MEX_FILE
  #include <Arduino.h>
  #include <Wire.h>
  #include <U8x8lib.h>
  // SSD1306 128x64 via hardware I2C, no reset pin (UNO: SCL=A5, SDA=A4)
  static U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset = */ U8X8_PIN_NONE);
  static bool isDisplayInitialized_u8x8 = false;
#endif
/* Includes_END */

/* Externs_BEGIN */
/* extern double func(double a); */
/* Externs_END */

void sfun_ssd1306_u8x8_display_Start_wrapper(void)
{
/* Start_BEGIN */
#if !defined(MATLAB_MEX_FILE)
  if (!isDisplayInitialized_u8x8) {
    u8x8.begin();
    u8x8.setPowerSave(0);
    // Font (lightweight ASCII font)
    u8x8.setFont(u8x8_font_chroma48medium8_r);
    // Optionally specify the I2C address (common 0x3C in 8-bit representation)
    // u8x8.setI2CAddress(0x3C << 1);  // Try only if nothing is displayed
    u8x8.clearDisplay();
    isDisplayInitialized_u8x8 = true;
  }
#endif
/* Start_END */
}

void sfun_ssd1306_u8x8_display_Outputs_wrapper(const uint8_T *u)
{
/* Output_BEGIN */
#if !defined(MATLAB_MEX_FILE)
  if (!isDisplayInitialized_u8x8) return;

  // Adjust based on input vector length
  const uint8_t MAX_STR = 16;

  char buf[MAX_STR + 1];
  uint8_t i = 0;
  for (; i < MAX_STR; ++i) {
    uint8_t b = u[i];
    buf[i] = (char)b;
    if (b == 0) break;
  }
  buf[(i < MAX_STR) ? i : MAX_STR] = '\0';

  // Display ASCII string on the first line (row=0)
  u8x8.clearLine(0);
  u8x8.drawString(0, 0, buf);
#endif
/* Output_END */
}

void sfun_ssd1306_u8x8_display_Terminate_wrapper(void)
{
/* Terminate_BEGIN */
#if !defined(MATLAB_MEX_FILE)
// nothing
#endif
/* Terminate_END */
}
  • Ports and parameters:

  • External Code:
    Clone the required U8g2_Arduino via Git at:
    C:\ProgramData\MATLAB\thirdpartylibs\U8g2_Arduino
    The Arduino Support Package path was as follows (this depends on your MATLAB installation, so please verify the Support Package path in your environment):
    C:\ProgramData\MATLAB\SupportPackages\R2025a\aCLI\data\packages\arduino

Build and Library Registration

#

When you build the S-Function, the following files are generated:

  • .cpp (main source)
  • _wrapper.cpp (wrapper code)
  • .tlc (Target Language Compiler file)
  • .mexw64 (Windows binary)
### Output folder is 'C:\Users\<UserName>\Documents\MATLAB\sfun_ssd1306_u8x8_display_block'
### 'sfun_ssd1306_u8x8_display.cpp' was successfully created
### 'sfun_ssd1306_u8x8_display_wrapper.cpp' was successfully created
### 'sfun_ssd1306_u8x8_display.tlc' was successfully created
### S-Function 'sfun_ssd1306_u8x8_display.mexw64' was successfully created

Additionally, to register with the Library Browser, prepare the following files:

  • slblocks.m (required)
  • setup.m (recommended)
  • INSTALL.m (optional) Useful when distributing the project.

slblocks.m

function blkStruct = slblocks
% This function is defined to display the specified library
% in the Simulink Library Browser.

    % --- Library registration information ---
    % Set Browser.Library to the library file name (without extension).
    Browser.Library = 'ssd1306_u8x8_display_lib';

    % Set Browser.Name to the name you want to display in the library browser.
    Browser.Name = 'Arduino SSD1306 U8x8 display library';

    % --- Combine into the structure ---
    blkStruct.Browser = Browser;

end

setup.m

function setup
addpath(fileparts(mfilename('fullpath')));   % #ok<MCAP> Add current folder to PATH
try
    lb = LibraryBrowser.LibraryBrowser2;
    refresh(lb);
catch
    sl_refresh_customizations;
end
% Dependency check (e.g., Arduino support)
% assert(exist('arduino','file')~=0, 'Install MATLAB Support Package for Arduino');
end

INSTALL.m

%% Add library to path
addpath(pwd);
savepath;

%% Refresh library browser
lb = LibraryBrowser.LibraryBrowser2;
refresh(lb);

Register the path in the path settings.

When registration succeeds, your custom SSD1306 block is added to the Simulink library.


#

Creating a New Model

#
  1. Launch Simulink and create a new "Blank Model"

  2. From the block library, place the following:

    • HC-SR04 block (RASPLib)
    • SSD1306 display S-Function block (custom)
    • String processing blocks (constant string, number-to-string conversion, string concatenation, string-to-ASCII conversion)
    • Display block (for debugging)

Parameter Settings

#

Set "Hardware Settings" → "Hardware Execution" as follows:

  • Hardware Execution

Uploading to Arduino and Execution

#

We will upload the program to the Arduino and enable automatic execution.

  1. In Simulink, run "Build, Deploy & Start"

  2. Compile → Transfer to Arduino
    When the transfer is successful, the following log is output:

The distance to the object measured by the ultrasonic distance sensor is now displayed on the OLED.

(The numbers are a bit hard to read, but an obstacle is placed at about 7 cm.)


Results and Discussion

#
  • The distance obtained by the HC-SR04 can be instantly displayed on the OLED, allowing integration of sensor and display via Simulink.
  • Due to the Uno's memory constraints, using U8g2's full-buffer mode is difficult, but the U8x8 mode is lightweight and practical.
  • With this setup, sensor input → string conversion → display output can be constructed intuitively.
  • Going forward, by parameterizing features such as variable row/column display positions, font switching, and I²C address specification, the block can be developed into a more versatile component.

Conclusion

#
  • HC-SR04 can be easily used in Simulink by leveraging RASPLib.

  • SSD1306 display functionality can be extended by creating a custom S-Function.

  • It is practical to use the U8g2 library in U8x8 mode to accommodate memory constraints.

  • By combining the Project feature with slblocks/setup/INSTALL, managing and distributing the library becomes easy.

  • This effort demonstrates an example of integrating multiple devices using Arduino.

  • In the future, this approach can be applied to other sensors and actuators, enriching the library and further expanding the scope of model-based development.


豆蔵では共に高め合う仲間を募集しています!

recruit

具体的な採用情報はこちらからご覧いただけます。