Main Content

Deploy Generated C Code to External Hardware: Raspberry Pi Examples

Use MATLAB® Coder™ to generate C code for basic or advanced MATLAB algorithms, and then deploy the algorithms to external hardware platforms. These examples show deployment scenarios for the Raspberry Pi® platform. You can use platforms such as the Raspberry Pi to prototype a more complex or larger scale deployment workflow. The Raspberry Pi runs a 32-bit Linux® operating system environment on an ARM® processor.

This figure shows the image produced by the generated code for a spring mass damper algorithm running on a Raspberry Pi. The C main function for the algorithm incorporates USB mouse input by using the Linux device file interface.

Prerequisites

  • Raspberry Pi Model 3 B+. Older models of Raspberry Pi hardware might exhibit reduced performance.

  • Network access or another file transfer mechanism, such as a microSD card reader.

  • Remote desktop connection or an external monitor.

  • Wired USB mouse for low-latency input.

Hardware Implementation Parameters

When generating code for external hardware, the code generator requires knowledge of the hardware-platform settings, as specified by a coder.HardwareImplementation object. This object contains implementation parameters that affect assumptions made by the code generator and that are important for achieving expected behavior.

For example, consider a Raspberry Pi running 32-bit Linux and an 8-bit Arduino® platform. The C compiler on the Arduino assigns an int 16 bits, whereas for the Raspberry Pi, the C compiler assigns 32 bits. If you generate C code that uses int variable declarations, then running the same code on both platforms can cause different integer overflow behavior.

Because of these platform differences, set the hardware implementation parameters specifically for whichever platform you expect to run the generated code on. By default, the parameters are set for the MATLAB host platform. You can use the MATLAB Coder app or command line to set hardware parameters, or you can use a Hardware Support Package.

Set Parameters by Using App and Command Line

To set the hardware implementation parameters via coder.HardwareImplementation, open your configuration object in the MATLAB Coder app. For example:

cfg = coder.config('lib');
open cfg;

Configure the implementation parameters for a Raspberry Pi. Click the Hardware pane and select the Device vendor as ARM Compatible and Device type as ARM Cortex. This selection is equivalent to entering:

cfg.HardwareImplementation.ProdHWDeviceType = 'ARM Compatible->ARM Cortex';

Setting the ProdHWDeviceType parameter triggers the appropriate settings for all the other coder.HardwareImplementation parameters.

Set Parameters by Using Hardware Support Package

If you have access to the MATLAB Support Package for Raspberry Pi Hardware, you can set up a connection to your Raspberry Pi from inside the MATLAB environment. You can set the coder.HardwareImplementation settings by choosing Raspberry Pi from the Hardware Board menu in the MATLAB Coder app, or from the command line, by entering:

cfg = coder.config('lib');
hwObj = coder.hardware('Raspberry Pi');
cfg.Hardware = hwObj; 

The coder.hardware function creates a coder.Hardware object. When you assign the coder.Hardware object to the configuration object, the hardware implementation parameters are set accordingly.

Hello World Example

Generate C Source Code for External Hardware

Consider an elementary MATLAB Hello World function.

function helloworld %#codegen
fprintf('Hello world!\n');

Create a configuration object and specify source code generation. Set the hardware implementation parameters for the Raspberry Pi.

cfg = coder.config('lib','ecoder',false);
cfg.GenCodeOnly = true;
cfg.HardwareImplementation.ProdHWDeviceType = 'ARM Compatible->ARM Cortex';

Generate code:

codegen -config cfg helloworld -report

Transfer Files to Device

You can package the generated code for file transfer by using the packNGo function. This function creates a zip file containing the required generated code files. The packNGo function does not include the generated example main files that you can use to compile the code into an executable. Move the generated example main files or your own handwritten main files separately.

From the directory from which you entered the codegen command, gather the files for deployment:

myBuildInfoFile = 'codegen/lib/helloworld/buildInfo.mat';
load(myBuildInfoFile);
packNGo(buildInfo);

movefile ./codegen/lib/helloworld/examples/main.c
movefile ./codegen/lib/helloworld/examples/main.h

Transfer the files from your host machine running MATLAB to your external hardware target. You can use a file transfer program for your platform or direct commands, such as scp with the destination IP address of the Raspberry Pi.

Build Code on Device

Once you have transferred the files to a directory, from the terminal, run unzip on the zip file. Then use the Linux gcc build tool to create an executable. Name it helloworld with the -o option:

gcc helloworld.c helloworld_initialize.c helloworld_terminate.c main.c -o helloworld

To run the executable and verify that the build was successful, enter:

./helloworld

The terminal displays the output:

Hello world!

Spring Mass Damper System Example

Generate Source Code for a Spring Mass Damper System

This example shows how to generate C source code for a spring mass damper system that you can then build and run on a Raspberry Pi.

The Spring Mass Damper Model

The spring mass system with damping is a fundamental system in mechanics and dynamics. By using the equations of motion you can solve for the displacement of the mass in response to different initial conditions and external forces.

The function springMassEqns encodes the equations of motion in the form of two first order linear differential equations. The variables dxdt(1) and dxdt(2) are the velocity and the acceleration of the mass, respectively. The variable x(1) represents the position of the mass.

function dxdt = springMassEqns(t,x,x0,k,m,c,F)
dxdt = zeros(2,1);
dxdt(1) = x(2);
dxdt(2) = F/m - k/m*(x(1)-x0) - c/m*x(2);

MATLAB Algorithm

To simulate the displacement as a function of time, the function springMassStep applies the ODE solver ode45 to the equations of motion.

function [x] = springMassStep(xi,vi,ti,dt,g) %#codegen
% Set spring equilibrium position 
x0 = 1; 
% Set spring, mass, damper constants
k = 1000;
m = 10; 
c = 25; 
% Scale acceleration g like a gravity force
F = m*g;
% Solve ODE for displacement at ti + dt
initCond = [xi vi];
tspan = [ti ti+dt];
[~,x] = ode45(@(t,x) springMassEqns(t,x,x0,k,m,c,F),tspan,initCond);

The springMassTakeStep function calls the springMassStep function and returns the final displacement at the end of a fixed time interval.

function [xf, vf] = springMassTakeStep(xi,vi,ti,dt,g) %#codegen
% Function springMassTakeStep acts as a wrapper for the ODE solving function, step.
% It takes the same input parameters as springMassStep, but only outputs the final 
% position and velocity. 
x = springMassStep(xi,vi,ti,dt,g);
xf = x(end,1);
vf = x(end,2);

Algorithm Results

To understand typical behavior of the model and the algorithm, the script springMassSim simulates the system over a typical parameter range. The output results show the displacement of the mass as a function of time. You can adjust the initial conditions, model parameters, and forcing function to see how the model responds.

springMassSim

Generate C Source Code

After verifying that the MATLAB model works as expected, generate C source code for deployment.

xi = 0.5;
vi = 0;
ti = 0;
dt = .01;
g = 0;

cfg = coder.config('lib','ecoder',false);
cfg.GenCodeOnly = true;
cfg.HardwareImplementation.ProdHWDeviceType = 'ARM Compatible->ARM Cortex';
codegen springMassTakeStep -args {xi,vi,ti,dt,g} -config cfg -report
Code generation successful: To view the report, open('codegen/lib/springMassTakeStep/html/report.mldatx')

Transfer Files to Device

After generating the C source code for the algorithm, you can modify the example main.c and main.h files for your application. For this example, the attached file springMass_main.c shows how to use the generated code. The corresponding header file springMass_main.h is also attached to the previous example with the supporting files.

From the directory from which you generated code, gather the files for deployment:

myBuildInfoFile = 'codegen/lib/springMassTakeStep/buildInfo.mat';
load(myBuildInfoFile);
packNGo(buildInfo);

Transfer the zip file and your main .c and .h file from your host machine that is running MATLAB to the target. You can use a file transfer program for your platform or direct commands, such as scp with the destination IP address of the Raspberry Pi.

Build Code on Device

Main File.  The main function springMass_main.c executes the generated code to simulate the displacement of the spring mass damper system over time. The function uses the USB mouse input from the Raspberry Pi to impart a force on the mass. The strength of the force is proportional to the speed of the horizontal mouse movement. If you do not move the mouse, the example simulates the unforced dynamics. To provide a visualization of the dynamics, the main file includes a routine to print the position of the mass over time.

Device File.  To use the mouse input, you must identify which device file on your system corresponds to the mouse. On the Linux platform, external USB device input is recorded in a device file stored in the /dev/input/ folder. The /dev/input/ folder typically contains files for multiple input devices. To identify which file corresponds to your USB mouse, use the od command on each file, and check to see which file updates in response to mouse movement.

od filename

Build.  To build the code from the Linux terminal, navigate to the location where you transferred your files. Unzip the zip file. Use the gcc command and specify all the .c files from the spring mass example:

gcc *.c -o springMassSim -lm

The -lm flag instructs the compiler to link to the required C math libraries. To run the executable, specify the previously identified USB mouse device file, here assumed to be event0:

./springMassSim /dev/input/event0

Move the mouse to apply a force to the mass and view the resulting dynamics. If the mass does not respond to mouse movement, try specifying a different device file. Terminate the program by entering ctrl + c during execution.

See Also

| |

Related Topics