Raspberry Pi and Arduino via GPIO UART

In an attempt to get my Raspberry Pi talking to my Arduino I’m exploring various different options. The first was to just use the USB connection, but that was too simple. So, here is how to connect the two using the UART on the GPIO pins of the Raspberry Pi.

To make testing easier I wanted to keep the Arduino’s serial connected via USB to my PC so I can print messages there and read it with the Serial Monitor. This meant using the SoftSerial library to implement a second serial port to talk to the Raspberry Pi. To protect my Raspberry Pi and to convert the 5V of the Arduino to 3.3V the Raspberry Pi needs I used a CD4050.

To show how this works the Arduino is running a small program that reads from the Raspberry Pi’s and copies this to my PC via USB.

By default the Raspberry Pi uses the UART in two ways:

  1. Console Messages (including bootup messages)
  2. A getty so you can login via serial

To use this serial port for your own uses you need to disable these two services. I decided to leave them enabled to test how well the serial connection works. However, the SoftSerial library on the Arduino doesn’t work so well at the default baudrate of 115200, so I changed this on the Raspberry Pi to 9600:

To change the console baudrate, edit /boot/cmdline.txt to look like this (this is all one line):

dwc_otg.lpm_enable=0 console=ttyAMA0,9600 kgdboc=ttyAMA0,9600 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait

Also, edit /etc/inittab to change the baudrate of the getty (you should fine a line like this with the baudrate of 115200, change that number to 9600):

2:23:respawn:/sbin/getty -L ttyAMA0 9600 vt100

Ok, now upload the program to your Arduino:

 

/*

 Connects Arduino to Raspberry Pi
 Arduino: SoftSerial
 Raspberry Pi: GPIO UART

 This is just a simple passthrough, based on Arduino SoftSerial example

 */
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

void setup()  
{
 // Open serial communications to PC and wait for port to open:
  Serial.begin(57600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.println("Connected to PC");

  // set the data rate for the SoftwareSerial port to Raspberry Pi
  mySerial.begin(9600);
}

void loop() // run over and over
{
  // If data is available on Raspberry Pi, print it to PC
  if (mySerial.available())
    Serial.write(mySerial.read());
  // If data is available on PC, print it to Raspberry Pi
  if (Serial.available())
    mySerial.write(Serial.read());
}

Connect the Arduino to the Raspberry Pi:

Raspberry Pi Pins used:

  • 1 : 3.3V
  • 6 : Ground
  • 8 : UART TXD
  • 10: UART RXD
CD4050 Pins used:

  • 1 : VDD (3.3V)
  • 2 : Output A
  • 3 : Input A
  • 4 : Output B
  • 5 : Input B
  • 8 : VSS (Ground)

If you then open your Serial Monitor on you PC, and set the baudrate to 57600 you should get the following message:

Connected to PC

If you then reboot your Raspberry Pi, the console messages should be echoed back to the Serial Monitor running your PC and leave you with a login prompt from the getty:

If you change ‘No Line Ending’ to ‘Newline’ you can enter your username and are then prompted for a password. Unfortunately the password doesn’t work. I still need to figure out why it’s not accepting my password. I suspect it’s to do with a line termination character or something.

Next step to connect this with a Serial library on the Raspberry Pi to talk to the Arduino. Maybe using pySerial like Dr Monk did in his Raspberry Pi and Arduino project. You should be able to use this in exactly the same way after disabling the console and getty and using ttyAMA0 as the serial port.

 

16 thoughts on “Raspberry Pi and Arduino via GPIO UART”

  1. hey,

    I Rebuild your setup for my own purposes. Works very good, thanks for this walktrough. But i have some issues aswell. Even at 9600 baud there are dropped chars. This could even be the solution for your not working password. By setting the baudrate even lower, it works fine for me but sometimes there still missing or wired characters. I’m still not sure why. Did you do any progress with your setup since you posted this article?

    1. I did do a bit more work and also noticed dropped characters when sending data from the Arduino to the Raspberry Pi. I’ve not worked out exactly why yet, but when I changed the PC Serial to 9600 to match the 9600 between Arduino and Raspberry Pi the dropped characters stopped.

  2. thank you. just had to do some little adjustments to set up the Arduino Mega because the serial ports are named differently (Serial, Serial1, Serial2). Everything works just fine. I can log in by setting Carriage Return in the serial monitor.

  3. Even at low baud rates you need flow control, either through CTS/RTS or XON/XOFF. If neither of these are being used then you will lose characters. As you have not connected CTS/RTS then you must use XON/XOFF (ie the receiver sends XOFF when the buffer is getting full and XON when it is empty enough to take more input). How to do this is another matter …

  4. Hi! Awesome work! I’ll try to implement your setup as soon as I manage to get a Pi.
    Speaking of which…
    I’m aware this is off-topic, and apologize in advance. I’d like to ask whether anyone here knows where to get a Pi here in Cape Town… (Because the PayPal and Credit Card options for the online purchase don’t work for me) I’d appreciate if you could drop me any info on a deal I might get in SA. Thanks 🙂

  5. Hi Andre!
    Great article, it helped me a lot. I managed to fix the issue with dropped characters. The problem was that available() function returns not a boolean value, but the number of characters in the input buffer. I slightly modified the loop() function and that solved the problem:
    void loop() // run over and over
    {
    int byteCount;

    // If data is available on Raspberry Pi, print it to PC
    if (byteCount = mySerial.available())
    {
    while (byteCount–)
    {
    Serial.write(mySerial.read());
    }
    }

    // If data is available on PC, print it to Raspberry Pi
    if (byteCount = Serial.available())
    {
    while (byteCount–)
    {
    mySerial.write(Serial.read());
    }
    }
    }

  6. Dear all,

    It works fine here, also I replaced IC CD4050 by a pair of optocouplers 4n25.

    Thanks for the amazing how-to

    1. Hi, I am interested to know how you achieved it (Naive at electronics – pure s/w guy trying hardware) . Please do a little post for people like us 🙂

  7. Hi Andre,

    Thanks for the tutorial! I was wondering whether you could be of help with the following:
    I would like to read bytes from the RPi UART RX – but I don’t know what the name for RX is.
    From your tutorial I gathered that TX would be ttyAMA0, is that correct? What about RX?
    If you could briefly explain and give me some pointers, I would greatly appreciate it.

    Thanks in advance!

  8. hi, I do not understand something in the connection.
    The TX Arduino is 5 volts and could break the raspberry and where you use the CD4050 to reduce the voltage from 5v to 3.3v. But in the opposite case, that is, the TX of raspberry (3.3v) because it can not be connected directly to the ‘RX arduino without going through the CD4050 seen coming out to 3.3ve so do not ruin the Arduino?

    Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *