Using a 2-wire serial connection we can communicate from a Rapsberry Pi (RPi) to an Arduino. For the Rasperry Pi we’ll use the built in UART accessed through a
tty, and the Arduino we’ll use the Serial Communication Library.
What this Example Does?
This example will use a RPi and Arduino to send a fixed message from the RPi to the Arduino. The Arduino will then echo what it receives back the RPi. The hardware used was a RPi B+ and the Arduino Due. The code is all in C/C++.
How this Post is Organized
- Pre-Requisites of the setup. This is mostly preparing your
ttyin Raspbian and proper file permissions
- Wiring. The physical wiring between the Raspberry Pi and the Arduino.
- Terminals (
tty) in Unix, some theory, how to test, and get information
- C Code for the Raspberry Pi
- Arduino Sketch to echo what is sent from the Raspberry Pi to the Arduino
- Running and downloading the example
For the pre-requisites in this example a Rasbperry Pi B+ was used with the following version of Raspbian.
The Arduino is an Arduino Due with Arduino Genuino 1.18.2.
Note: There really isn’t any reason you cannot use any of the Raspberry Pi and Arduino product line, it’s just a matter of mapping the pins, files, functionality and hardware to the product. I’d actually be surprised if it wasn’t easy, or even no real changes to use something else.
Wiring - Do you have a 3.3V to 5V Issue?
Before you even start the RPi I/O operates at +3.3V and most, not all Arduinos operate at +5V. You will need to use one of the various mechanisms to translate +3.3V to +5V. If you don’t you’ll damage the pins on the RPi. For this I used an Arduino Due which has +3.3V I/O Pins, and it’s easy since you can directly connect to the Raspberry Pi.
Wiring two UARTs together requires connecting Tx and Rx pins from the Raspberry Pi to the Rx and Tx pins on the Arduino. The Tx pin on one, goes to the Rx pin on the other. On my RPi B+ these are the
RXD pins which map to Pins 8 and 10, which map to BCM 14 an BCM 15. Refer to this excellent Raspberry Pi Pinout. For the Arduino Due the pins
Theory Using a UART in Unix
A Universal Asynchronous Receiver/Transmitter (UART) does serial communications. There is also a Universal Synchronous/Asynchronous Receiver/Transmitter (USART). For this example we actually will do synchronous serial communications, although, it could be extended to do asynchronous where the RPi and Arduino could both send and receive asynchronously.
To communicate with a UART in Unix you use a Terminal. This is also referred to as a
tty for TeleTYpewriter and goes WAY back. To communicate with a tty we do basic file I/O where the file is a Unix Character Device. This device on the RPi happens to be
/dev/ttyAMA0 on the RPi. In order to do file I/O on a terminal we have to configure it properly using the
termios sturcture. An example will be shown below on how this
termios structure is setup.
There are lot of example to use a
tty in Unix online. However, I highly recommend reading all of
man termios. It’s a VERY good authoritative reference.
The UART as a Terminal in Raspbian
As mentioned we’ll be configuring
/dev/ttyAMA0 as a Terminal. The amount of attributes to configure terminals can be overwhelming because there are so many. These attributes relate to input, output, control, local modes, as well as, special characters. Terminals in Unix handle so many things, from USB, UARTs, VIM, SSH, Shells, Serial Ports, … They need to be very flexible and hence have a lot of attributes.
You can easily see the attributes or a terminal device. First let’s get the permissions of our character
tty device correct so we don’t have to be
We don’t want to be
root to do everything. let’s add ourself to the
tty group and change the permissions of the character device to have group read privileges.
We have to
exit and log back in for the group privileges to be applied.
Now let’s check out our terminal settings.
There is a LOT of output here from the
stty tool. The attributes at the bottom that start with a
- means they are not enabled. For example ICANON - canonical mode - is disabled because we see
-icanon. The attribute
cs8 is enabled. We can see that the baud rate is
115200. All of this is documented. It can be seen by doing a
man termios. To search for attributes using upper case. E.g.
icanon as displayed by
Terminal Cooked mode versus Raw Mode
There are two modes for a Terminal in Linux. Cooked Mode - also known as Canonical Mode, and Raw mode - also known as non-canonical mode. The difference really is Cooked mode will read a line at a time, and Raw mode will read a character at a time. Here is a great explanation of this. For this example we’ll use Raw Mode so we’re sending a character (byte) at a time from the Rasberry Pi to the Arduino.
C Header to Communicate with the UART
A C Header to communicate with the UART for the Raspberry Pi. It’s simple, we’ll just define one function called
uart_open that will return a file descriptor. If it’s less than 1 then it’s an error.
C Implementation to set up the UART
Here is where the main challenge is. We will have to open our terminal device, set up the terminal in raw mode and return the file descriptor. From here, we can treat the UART as a normal file. This means we can use the
write functions to simple read and write to our UART.
Running the UART Example
To run the example we have our main method. Note, you must pass in an argument for it to read back. This is mainly for debugging purposes.
After this code is run it will set-up our terminal with a bunch of new attributes. We can see them with the
stty command. This is different than what we see at the start of this post with the default attributes.
Downloading the Example
Download the rpi-arduino-uart example. Then to run do the following:
hello world was sent out the UART of the Raspberry Pi to the Arduino and from the Arduino back to the Raspberry Pi and printed to the terminal.
Arduino Sketch to Echo Back through the UART
The following sketch will echo back what is sent on
Serial1 which corresponds to a UART back out to what was received. All the characters that come in through
Serial1 will go back out
Serial1. This is so when we run the C on our Raspberry Pi we’ll see our message back on the terminal.
Where to go from Here?
Depending on what you want to send and receive this example needs to be adapted. Perhaps, it’s just output to the terminal of the Raspberry Pi so you want to just display it to the terminal. You might want to look at Cooked mode and have Arduino send lines ending with a new line. Perhaps, you want to send commands to the Arduino and based on what it reads from the UART it will do something. Another use would be asynchronous where at any given time the Raspberry Pi would be sending or receiving. Here you’d need to look at
man select and do Asynchronous I/O in Unix. Doing this when the terminal is opened be sure to open with
O_NONBLOCK and likely some other changes need to be done. For example
VMIN could be 0 or we could have a deadlock. Which I’ve seen
EDEADLK errno come while playing around with it.
It should be noted to use USB instead of the UART it’s very easy. You can simply replace
/dev/ttyACM0 in the C code and
SerialUSB in the Arduino code.