Introduction: Arduino to RPi: Three Ways to Convert 5 Volts to 3.3 Volts

About: Jack passed away May 20, 2018 after a long battle with cancer. His Instructables site will be kept active and questions will be answered by our son-in-law, Terry Pilling. Most of Jack's instructables are tuto…

There is a problem when connecting an Arduino to the GPIO on a RaspberryPi. The logic level on the Arduino is five volts and the RaspBerryPi requires 3.3 volts. Sending a five volt signal to a GPIO pin will damage the RaspberryPi. When I wire something wrong I want to a see spectacular blow-up. You will see nothing, no fireworks, not even a little smoke. No fun, it just stops working.

This tutorial will illustrate three different ways to convert 5 volts from an Arduino into 3.3 volts for a RaspberryPi.

1 - A voltage divider

2 - An Optoisolator (Optocoupler)

3 - A bi-directional level shifter

The RaspberryPi program in this tutorial uses the wiringPi
libraries, written by Gordon Henderson, for programming the GPIO in C.

wiringPi must be installed. Instructions for download, installation and use are located at http://wiringpi.com

wiringPi uses it's own pin numbering scheme.

All RaspberryPi pin numbers are wiringPi numbers unless otherwise specified.

You will need a way to run wires from the RaspberryPi to the breadboard. You can use male/female jumper wires but one of the Pi Cobblers listed on this page from Adafruit will make it a lot easier: http://www.adafruit.com/search?q=cobbler

Step 1: Building the Circuit

To build the circuit you will need:

Arduino

RaspberryPi

Jumper wires

Breadboard

LED - RGB Common Anode https://www.sparkfun.com/products/10821

4 270-560 Ohm resistors (For LEDs and Optoisolator)

2 10K resistors (Pulldowns)

3 1K resistors (For voltage divider)

Optoisolator https://www.sparkfun.com/products/314

Bi-directional Level Shifterhttps://www.sparkfun.com/products/314 or https://www.sparkfun.com/products/314

Male Headers (For level shifter) https://www.sparkfun.com/products/116

For my build I used the Sparkfun level shifter and my diagram shows the Adafruit part. The reason for this is that I don't have the Fritzing part for the Sparkfun level shifter. The two parts are electrically identical, but the pinouts are different. Make sure you check the pinouts for the part you use.

Sparkfun also sells a good resistor assortment that includes all the resistors you need for this project and many more, look here: https://www.sparkfun.com/products/10969

Sparkfun has a good tutorial for their level shifter here: https://learn.sparkfun.com/tutorials/bi-direction...

Follow the diagram above to build the circuit.

Step 2: The Voltage Divider

The voltage divider is a simple circuit made up of two resistors.

To calculate the output voltage use this formula: Vout = Vin * (R2 / (R2 + R1))

3.3 volts is 2/3 of 5 volts so the value of R2 should be double R1.

I used 1K resistors with two resistors in series for R2 and one for R1.

When the pin on the Arduino goes high the signal is sent to the RaspberryPi.

Step 3: The Optoisolator

The Optoisolator is sometimes referred to as an Optocoupler. The two names sound opposite but the Optoisolator does both. It allows you to pass a signal from one device to another with no electrical connection. The small four pin IC contains an LED and a photo diode. When the LED is lit current is allowed to pass through the photo diode.

Step 4: The Bi-directional Level Shifter

The Bi-directional level shifter has high voltage and low voltage inputs, and a ground on both sides. And there are four input/output channels. A high voltage applied the high voltage side of any channel will result in a low voltage on corresponding low side, and vice versa. This is a good way to go if you are passing signals in both directions.

Step 5: RaspberryPi Code

This is the code for the RaspberryPi.

The "!" before the digitalRead() functions is a "NOT" to reverse the pin because I am using a common anode RGB LED.

/******************************************************************
 * Filename: 3-Way.c
 *
 * An Arduino controls the tri color LED attached to the RaspberryPi
 * through a level shifter, an optocoupler, and a voltage divider.
 *
 * This demonstrates three ways to step the five volt signal from
 * the Arduino down to the 3.3 volts required for the RaspberryPi.
 *
 * Use the _3_Way.ino program to send the signal from the Arduino.
 ******************************************************************/

#include <wiringpi.h>

int main (void)
{
  wiringPiSetup();    // Enable wiringPi.
 
  pinMode(0, INPUT);  // Level Shifter, input.
  pinMode(2, INPUT);  // Optocoupler, input.
  pinMode(3, INPUT);  // Voltage Divider, input.

  pinMode(6,OUTPUT);  // Level Shifter LED, output.
  pinMode(10,OUTPUT); // Optocoupler LED, output.
  pinMode(11,OUTPUT); // Voltage Divider LED, output.

  while(1)
  {
    digitalWrite(6, !digitalRead(0)); // Level Shifter
    digitalWrite(10,!digitalRead(2)); // Optocoupler
    digitalWrite(11,!digitalRead(3)); // Voltage Divider
  }
  return 0;
}

Attachments

Step 6: Arduino Code

Copy this code into the Arduino IDE and upload it to your Arduino.

It will blink the tri-color LED connected to the RaspberryPi through a cycle (red, green, blue, yellow, magenta, cyan, white) five times. Next it will send Pulse Width Modulation (PWM) signals to fade the LED in then out, first red, then green, and finally blue, to demonstrate that a PWM signal can be sent with all three methods.

//****************************************************************
// Filename: _3_Way.ino
//
// The Arduino program to send signals to the 3_Way.c program
// Running on the RaspberryPi.
//
//****************************************************************

int outpin[3]={11,10,9};

//****************************************************************
// setup()
//****************************************************************
void setup()
{
  for(int i=0;i<3;i++) pinMode(outpin[i], OUTPUT);
}
//****************************************************************
// function alloff() - Sets all pins low.
//****************************************************************
void alloff()
{
  delay(500);
  for(int i=0;i<3;i++) digitalWrite(outpin[i], LOW);
}
//****************************************************************
// blink() Blink red, green, blue, yellow, magenta, cyan, white.
//****************************************************************
void blink()
{
  for(int i=0;i<3;i++) 
  {
    alloff();    
    digitalWrite(outpin[i], HIGH); // Red, Green, Blue.
  }
  alloff();    
  digitalWrite(outpin[0], HIGH);  // Yellow, Red + Green.
  digitalWrite(outpin[1], HIGH);
  alloff();    
  digitalWrite(outpin[0], HIGH);  // Magenta, Red + Blue.
  digitalWrite(outpin[2], HIGH);
  alloff(); 
  digitalWrite(outpin[1], HIGH);  // Cyan, Green + Blue.
  digitalWrite(outpin[2], HIGH);
  alloff();    
  digitalWrite(outpin[0], HIGH);  // White, Red + Green + Blue.
  digitalWrite(outpin[1], HIGH);
  digitalWrite(outpin[2], HIGH);
}
//****************************************************************
// loop()
//****************************************************************
void loop()
{
  int delaytime=20;

  for(int i=0;i<5;i++) blink();
  alloff();
  delay(1000);
  for(int j=0;j<3;j++)
  {
    int x=1;
    for(int i=0;i>-1;i+=x)
    {
      analogWrite(outpin[j], i); // Fade in and out,
      if(i==255) x=-1;           // RGB sequence.
      delay(delaytime);
    }
  }
  alloff();
  delay(1000);
}