Learning MATLAB/Simulink and Arduino — Device Integration with Custom S-Function Blocks
Back to Top
To reach a broader audience, this article has been translated from Japanese.
You can find the original version here.
Introduction: Creating Custom S-Function Blocks with Simulink and Arduino
#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-Ons → Get 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.
- Creating a New Project
This approach makes it easier to organize multiple devices and enhances reusability.
Creating the Library
#-
Creating a New Simulink Library
-
Placing the S-Function Builder Block
-
Preparing External Libraries
- Prepare so that Arduino headers like
Wire.h
andU8x8lib.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
- Prepare so that Arduino headers like
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 */
}
-
External Code:
Clone the requiredU8g2_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 the Main Simulink Model
#Creating a New Model
#-
From the block library, place the following:
Parameter Settings
#Set "Hardware Settings" → "Hardware Execution" as follows:
Uploading to Arduino and Execution
#We will upload the program to the Arduino and enable automatic execution.
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.