Guy on Simulink

Simulink & Model-Based Design

Creating Driver Blocks for Arduino, Lego, and other targets 10

Posted by Guy Rouleau,

As you may know, it is easy to run Simulink models on a set of supported target hardware. This has been possible since R2012a.

Even if we add more targets and support more features for each target with every new release, it is still possible that you will need a driver that is not included in the Simulink support package. If you desperately need a driver for your hardware, you can always build it yourself.

Let's see how this works using an example from a LEGO NXT project I worked on.

The LEGO Light Sensor

The LEGO NXT kit ships with a Light Sensor including a red LED that can be turned on or off. In the Simulink support package, you can control the light from a checkbox parameter in the block dialog.

Dialog of the LEGO Light Sensor driver block

For our project, we used this sensor to make a line following robot. To make our algorithm more robust, we thought it would be interesting to turn the light on and off while tracking the line, to actively filter out the ambient light.

Step 1: Determine the code to be generated for your driver block

In the LEGO MINDSTORMS NXT Support from Simulink, you can find many small examples showing how the robot can be programmed in C. By default, they are located in C:\MATLAB\SupportPackages\R2013a\nxtOSEK\samples_c. In one of those example, I found a function initializing the robot that looked like:

Example code used to program the NXT brick in C

The function ecrobot_set_light_sensor_active is exactly what I need to generate from my driver block. I also figured that a corresponding function ecrobot_set_light_sensor_inactive exists to turn the light off, and I found that those functions are declared in a file named ecrobot_interface.h.

Step 2 - Create an S-Function

Here you have 2 options to create the S-Function

Step 2 - Option 1: S-Function Builder Block

My colleague Giampiero Campa published a very good submission on MATLAB Central titled Device Drivers showing how to use the S-Function Builder block to include the code you found during step 1 in your model.

His submission contains detailed procedures and screen captures to guide you through the process step-by-step. If you are intimidated by writing an S-function, I recommend using his S-Function Builder technique.

Step 2 - Option 2: Writing an S-Function and a TLC file

If you are like me and want to understand the magic that is happening when you click build in the S-Function Builder block, this second option is for you.

First, we need to realize that unless you model the interaction of the sensor/actuator with the environment, in simulation, driver blocks typically do nothing. All blocks must specify the number of ports and parameters, and their dimensions, even if they do nothing. In my case, I created an s-function with 1 input port of dimension 1 to specify if the light should be on or off. Here is the entire code for my s-function.

S-Function to control the light of the LEGO light sensor

To specify the code generated for your block, you need to use the Target Language Compiler.

Concretely, this means that you need to write a TLC file for your block. For that, I recommend starting with examples from sfundemos.

For this example we need our TLC to do two things: Tell the compiler to include ecrobot_interface.h, and call ecrobot_set_light_sensor_active and ecrobot_set_light_sensor_inactive. Here is what it looks like.

TLC file to control the light of the LEGO light sensor

Note that I used BlockTypeSetup to include the header file, and Outputs to define what the block output method should be.

Now it's your turn

Download this LEGO example or a similar example for the Arduino target and begin creating your own driver blocks!

If you develop custom drivers for the Simulink Target Hardware, share them on MATLAB Central and let us know by leaving a comment here.

10 CommentsOldest to Newest

Roni replied on : 1 of 10
Hi, Good and informative. But - it is a bit more tricky for the Raspberry. How can I do the same for example to create a "Serial Tx/Rx" from the UART of the Raspberry? Roni.
sepideh replied on : 2 of 10
hi dear Guy i have some question in matlab simulink, how can i contact you? please help me to do my simulink, its critical.
Gökay replied on : 3 of 10
Hey, I tried to compile your example however I get the following errors. At the end, I would like to implement my own I2C funtion on simulink. Please Help me out !! Error: File: myLight.tlc Line: 14 Column: 43 Undefined identifier lcv Error: File: myLight.tlc Line: 14 Column: 48 Undefined identifier sigIdx Error: File: E:\Matlab2012b\rtw\c\tlc\lib\blkiolib.tlc Line: 353 Column: 5 Undefined identifier lcv Error: File: E:\Matlab2012b\rtw\c\tlc\lib\blkiolib.tlc Line: 353 Column: 10 Undefined identifier sigIdx
Guy Rouleau replied on : 4 of 10
@Gokay, sorry about that, there was a typo in the file. I have updated it. To fix the problem, replace this line in the TLC file %assign u = LibBlockInputSignal( 0, "", lcv, sigIdx) with %assign u = LibBlockInputSignal( 0, "", "", 0)
jaradat replied on : 5 of 10
I'm using S-function builder and I want to change the sample time so i need to add it as a parameter.My question is what to write in the code so when i change the parameter the sample time changed. I don't want to use ssSetNumSampleTimes(S,numSampleTimes);
Guy Rouleau replied on : 6 of 10
@jaradat: The sample time should be specified in mdlInitializeSampleTimes, using the marcos ssSetSampleTime and ssSetOffset:
static void mdlInitializeSampleTimes(SimStruct *S)
    ssSetSampleTime(S, 0, SOME_VALUE_FROM_PARAMETER);
    ssSetOffsetTime(S, 0, 0.0);
deepak replied on : 8 of 10
Will this method can be used to generate "return " statement in the required file . Basically currently available block i.e "system output " couldnt be used in my case as it does not support for AUTOSAR CODE generation . So looking for other option to generate "return " statement using matlab modelling for AUTOSAR .
deepak replied on : 9 of 10
Code: void return_statement_step(void) { if (return_statement_U.In1 == return_statement_U.In2) { return; } else { return_statement_Y.Out1 = return_statement_U.In1 + return_statement_U.In2; } return_statement_Y.Out2 = 7.0 * return_statement_U.In1; } Code which i want to generate .
dzung replied on : 10 of 10
Hi Guy, This article is informative and helpful but I am still not really understand Simulink "device driver" means. Is this alike device driver in OS? And could you give me some instructions on building my own custom hardware support package, both hardware side and Simulink side. Thanks in advanced.