By Esther Ling, 14 December 2015

** Update: View Part 2 here **

Recently I had to prepare a demo that involved serial communication between a Raspberry Pi and an Arduino.

Mathworks has released support packages for a number of low cost hardware boards, such as Arduino, Raspberry Pi and BeagleBoard.

Searching the library blocks for the Raspberry Pi, I noticed that there weren’t any blocks for serial receive, like there is for the Arduino library.

So this meant that I would need to write a driver using the S-Function builder.

If you are new to writing drivers with S-Function builder, here is a blog post by Guy Rouleau.

Hardware Note – Connecting the Pi and Arduino

The voltage at the TX/RX pins for the Pi (3.3V) and Arduino (5V) are different, so I set up a voltage divider circuit to scale the voltages appropriately. With a limited number of resistors at my disposal, I had to calculate a combination of resistors that would do the trick.

Rather than spend time calculating different values on paper, I wrote a MATLAB script that would do the job.

Vo = 3.3;
Vs = 5;

R2 = input(‘What is resistor value R2 (Ohms)?: ‘, ‘s’);
R2 = str2double(R2);

R1 = Vs/Vo*R2 – R2;
display(R1, ‘Value of R1’);

Vdiv
Voltage Divider Circuit

The Arduino Model

To set up the Arduino to transmit data, I pulled the Serial Transmit block from the Simulink Library and connected a constant block set to emit uint8 values.

Writing the Serial Receive Driver for Raspberry Pi

The serial port associated with the TX/RX pin is /dev/ttyAMA0. In order to use this port on the Pi, the serial console needs to be disabled and then the system rebooted.

You could do this manually through Putty by editing cmdline.txt and inittab as described here.

However, there is a more straightforward method through MATLAB by creating a raspi object connection to the Pi.

>> mypi = raspi

>> system(mypi, ‘rpi-serial-console status’)

>> system(mypi, ‘sudo rpi-serial-console disable’)

>> system(mypi, ‘sudo shutdown -r now’)

>> clear mypi

Now, for serial communication. Gordon from GordonsProjects has a WiringPi library written in C that can be used on the Raspberry Pi. This library would give me access to C functions such as serialOpen() and fflush() needed for this task.

I downloaded this library to the Pi.

Before starting with the code, I wanted to test that the Rx pin was working. I shorted the Tx and Rx pins on the Pi and ran minicom to see if it would print what was being typed on the keyboard.

minicom
minicom on Pi via Putty

Now that the hardware was ready, I set out to write the software part.

S-Function Builder

Since I would be working with external C-libraries, I included them in the “Libraries” pane of the S-Function builder.

The “Discrete Update” pane contained initialization tasks such as opening the /dev/ttyAMA0 port for reading.

The “Outputs” pane contained the code to read from the open serial port.

Running on External Mode

My first test was to send uint8 data from the Arduino and receive it on the Raspberry Pi. A live test would be to run both the Arduino and Raspberry Pi models in External mode. This would allow me to use my PC to control what character was being sent from the Arduino and view it as it was received by the Raspberry Pi.

The Arduino Mega uses Serial Port 0 to run External Mode, so I made sure that data was being sent on a different serial port. I used Serial Port 1, which is connected to Tx1 Pin 18.

megatx.png
Tx1 Pin on Arduino Mega

 

I had the Raspberry Pi plugged in to my office network, so my computer could communicate with it over the network. This meant I could run External Mode on the Pi concurrently with running External Mode on the Arduino without having a communication conflict.

Sending a value of ‘65’ from the Arduino, I received the character ‘A’, which is the ASCII equivalent for 65.

raspi_mode
Receiving ‘A’ on the Raspberry Pi

When I deployed the model to the Arduino and then ran minicom, it would display ‘A’ as well.

minicom_con
Displaying received data on minicom

A Final Caveat

When I first tried compiling the S-Function Builder, there were a couple of un-resolvable undefined references. What was happening was that the Simulink makefile did not include the wiringPi library by default. John Whittington here found an undocumented function as a workaround: call xmakefilesetup in the command window and add –lwiringPi at Linker > Arguments.

 

That’s serial communication, done!

 

Update 22 December 2015:

You can find the model files on File Exchange. I have posted them here:

http://www.mathworks.com/matlabcentral/fileexchange/54601-raspberry-pi-and-arduino-serial-communication

Update 18 January 2016:

View Part 2 of this project that sends data collected from a sensor.

Advertisements