Electronic – arduino – Solution for level-translation (3.3V Arduino Due <-> 5V shield)

arduinoarduino-shieldlevel-shifting

The new Arduino Due board has its microcontroller running at 3.3V, but unfortunately most standard Arduino add-on shields (boards) run at 5V, thus their I/O signals are at different logic levels.

The number of signals is approximately 20, and includes:

  • standard digital lines (some with hardware interrupt capability)
  • analog I/O
  • Serial UART lines
  • as well as SPI and I2C signals

Now, I would like to add an in-between shield (board) so as to facilitate compatibility between the 3.3V Arduino Due board and all the signals of any given 5V shield. This in-between board would need to allow interfacing between the 3.3V signals and the 5V signals (i.e., both ways).

What is the best way to create bidirectional level-translation for a case like the above? Here, by "best", I just mean straightforward, inexpensive, and would work without problems across the various shields and signal types.

Based on my research of this kind of level shifting so far, the options available seem to be:

  • A set of diodes that create a voltage drop (but this would be uni-directional)
  • A set of resistive dividers (again uni-directional)
  • A specialized level shifting chip?…

Best Answer

I've designed a small system that might work for your particular application. Here is the schematic: Level Translator

I forgot the reference node, it must be connected to terminal 2 of BT1. How does this work?

From high to low

First of all let's assume we can neglect the current flowing in/from "low".

When high is pulled up (5V) in R1 no current flows, while the three diodes are conducting. Assuming a forward drop voltage of 0.6V the voltage at low will be 3.2V, and the current flowing from high will be approximately 320uA.

When high is pulled down (0V) all the diodes are interdicted, so the voltage at low will be pulled down by R2. The current that high must sink is approximately 500uA.

From low to high

Now let's assume high is not consuming current.

When low is pulled up (3.3V) the diodes can not conduct because the voltage at high would be more than 5V, so high is pulled up by R1, the diodes are off and low must provide about 330uA.

When low is pulled down (0V) the diodes are correctly polarized, R2 has zero volt across, the voltage at high is about 1.8V and the current sunk by low is approximately 180uA.

As you can see, the big problem is that 1.8V is a bit too much: a CMOS circuit would probably read that "low", while a TTL is likely to read that "high". A better approach could use a 1.5V zener diode instead of the three small signal diodes, with the cathode connected to R1 and the anode to R2. The resistor will probably need to be reduced to meet the minimum polarization current of the zener diode.

One last thing about the resitors is that you can use any value from 1k to 100k, of course higher resistance values correspond to lower current consumption, but also to slower transient response, and vice versa.