Interfacing the PCA9306 Level Shifter With Arduino Uno (5V to 3.3V I2C)

by ElectroScope Archive in Circuits > Arduino

12 Views, 0 Favorites, 0 Comments

Interfacing the PCA9306 Level Shifter With Arduino Uno (5V to 3.3V I2C)

Interfacing PCA9306 Module with Arduino Uno.jpg

In this build, I’m using a PCA9306 bidirectional logic level shifter to safely connect a 3.3V I2C sensor to a 5V Arduino Uno. Specifically, I’m reading data from a BMP180 pressure sensor, which only tolerates 3.3V logic. The PCA9306 sits between the Arduino and the sensor and takes care of translating the I2C signals automatically. No configuration. No code tricks. Just proper wiring.

If you’ve ever tried connecting a 3.3V I2C sensor directly to an Arduino Uno and had it not show up on the bus, this is the clean way to fix it.

Most of this writeup is about how to wire it correctly, how to avoid the common mistakes, and how to test it once everything is connected.

What You’ll Be Building

You’ll end up with:

  1. An Arduino Uno running standard I2C code
  2. A PCA9306 level shifter translating 5V I2C to 3.3V
  3. A BMP180 pressure sensor communicating reliably
  4. Serial output showing temperature and pressure readings

No special libraries for the PCA9306. It works entirely in hardware.

Supplies

Here’s what I had on my bench:

  1. Arduino Uno
  2. PCA9306 logic level shifter module
  3. BMP180 pressure sensor module (3.3V I2C)
  4. Breadboard
  5. Jumper wires
  6. USB cable for Arduino

That’s it. No resistors, no extra components, assuming your PCA9306 board already has pull-ups on the low-voltage side, which most do.

Understanding the PCA9306 Before Wiring Anything

PCA9306-Module-Pinout_1.jpg

Before connecting wires, it helps to understand how this module works in real terms.

The PCA9306 is designed specifically for I2C. That’s important. I2C uses open-drain lines, which means devices pull the line low but never drive it high. The line goes high through pull-up resistors. The PCA9306 takes advantage of this behavior.

The chip has two voltage reference pins:

  1. VREF1 sets the logic level for the low-voltage side
  2. VREF2 sets the logic level for the high-voltage side

In this project:

  1. VREF1 = 3.3V (sensor side)
  2. VREF2 = 5V (Arduino side)

The SDA and SCL lines are duplicated on both sides. The PCA9306 automatically translates signals in both directions. You don’t need to tell it which direction data is flowing.

One thing that matters a lot is ground. Both sides must share the same ground reference. If you forget this, the bus will not work, even if everything else is wired correctly.

Take a minute to identify each pin on your board before moving on.

Pin Roles in Plain Language

This is how I think about the pins when wiring:

  1. VREF1: 3.3V reference for the sensor side
  2. VREF2: 5V reference for the Arduino side
  3. SDA1, SCL1: I2C lines going to the 3.3V sensor
  4. SDA2, SCL2: I2C lines going to the Arduino
  5. EN: Enable pin. Must be tied high
  6. GND: Common ground for everything

Most PCA9306 breakout boards expect EN to be pulled up to VREF2. Some boards already do this. Mine didn’t, so I wired it manually.

Power Connections

I always start with power and ground first.

Here’s what I connected:

  1. Arduino 3.3V → PCA9306 VREF1
  2. Arduino 5V → PCA9306 VREF2
  3. Arduino GND → PCA9306 GND
  4. Arduino GND → BMP180 GND

Make sure all grounds are tied together. I usually run one ground rail on the breadboard and connect everything to that.

At this point, do not connect SDA or SCL yet. Just verify power.

If you have a multimeter, check:

  1. VREF1 is around 3.3V
  2. VREF2 is around 5V

If these are swapped, stop and fix it. Reversing them can damage a 3.3V sensor.

Enable the PCA9306

The EN pin enables the internal circuitry. If this pin is left floating, the level shifter may not work at all.

What I did:

  1. Connected EN directly to VREF2 (5V)

Some modules include a resistor that already does this. If yours does, you can skip this step. If you’re not sure, just connect it manually. It won’t hurt.

The Wiring

PCA9306-Wiring-Diagram.jpg

On the Arduino Uno, I2C is fixed to these pins:

  1. SDA → A4
  2. SCL → A5

Here’s how I wired the high-voltage side of the PCA9306:

  1. PCA9306 SDA2 → Arduino A4
  2. PCA9306 SCL2 → Arduino A5

Keep these wires short. Long wires increase capacitance and can cause I2C errors, especially at 400 kHz.

Sensor Side

The BMP180 has these I2C pins:

  1. SDA
  2. SCL

I connected:

  1. BMP180 SDA → PCA9306 SDA1
  2. BMP180 SCL → PCA9306 SCL1
  3. BMP180 VCC → 3.3V
  4. BMP180 GND → GND

Do not power the BMP180 from 5V. Even though the PCA9306 protects the I2C lines, it does nothing for the power pin.

Final Wiring Check

Before plugging in USB:

  1. VREF1 = 3.3V
  2. VREF2 = 5V
  3. EN tied high
  4. Grounds common
  5. SDA and SCL not crossed

Once this matches your setup, you’re ready to upload code.

Arduino Code

The nice part about this project is that the PCA9306 needs zero code support. As far as the Arduino is concerned, it’s talking directly to the BMP180.

I used the standard BMP180 library and the Wire library.

Here’s a trimmed version of the sketch:


#include <Wire.h>
#include <Adafruit_BMP085.h>

Adafruit_BMP085 bmp;

void setup() {
Serial.begin(9600);
Wire.begin();

if (!bmp.begin()) {
Serial.println("BMP180 not detected");
while (1);
}
}

void loop() {
Serial.print("Temperature: ");
Serial.print(bmp.readTemperature());
Serial.println(" C");

Serial.print("Pressure: ");
Serial.print(bmp.readPressure());
Serial.println(" Pa");

Serial.println();
delay(1000);
}

That’s it. No voltage logic. No conditionals. No special handling.

Upload the sketch and open the Serial Monitor at 9600 baud.

Testing the Setup

PCA9306-With-Arduino_Uno.gif

Once the code is running, you should see temperature and pressure values updating every second.

If you see valid numbers, the level shifter is doing its job.

If you see nothing, or “BMP180 not detected”, don’t panic. That usually means a wiring issue.

Common Problems and Fixes

Here are the issues I actually ran into or have seen others hit.

Sensor Not Detected

Things to check:

  1. EN pin is high
  2. Grounds are shared
  3. SDA and SCL are not swapped
  4. VREF1 is actually 3.3V

Also make sure you didn’t accidentally connect the sensor SDA to SDA2 instead of SDA1

I2C Scanner Finds Nothing

If you’re using an I2C scanner sketch and nothing shows up:

  1. Check pull-up resistors
  2. Keep wires short
  3. Try lowering I2C speed to 100 kHz

Some PCA9306 boards only have pull-ups on the low-voltage side. The Arduino usually provides pull-ups on the high side internally, but not always strongly enough.

Unstable or Random Readings

This is usually a wiring quality issue.

  1. Shorten wires
  2. Avoid loose breadboard connections
  3. Make sure power is stable

I2C is very sensitive to noise and capacitance.

Wrapping Up

This build shows how simple voltage level shifting can be when you use the right part. The PCA9306 doesn’t need configuration, calibration, or special firmware. If it’s wired correctly and powered correctly, it just works.

Once you’ve done this once, adding 3.3V I2C devices to a 5V Arduino becomes routine instead of stressful.

If you want the original files, diagrams, and demo media, the full project repository is here:

PCA9306 Module with Arduino Uno