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
packNGo
| coder.HardwareImplementation
| coder.hardware