In this tutorial you will learn what differs analog pin from digital and how to combine multiple devices when different voltage levels for power and communications are needed.
Table of contents
- Background of the problem
- Two devices powered with different voltage levels
- Send logic signals from 3.3V device to 5V device
- Send logic signals from 5V device to 3.3V device
- Bi-directional communication
- Example
Every microcontroler has multiple pins and they fulfill various roles but you can group them into three categories:
- power pins,
- analog pins,
- digital pins.
In case of Arduino, the power pins are as follows:
- Vin. The input voltage to the Arduino/Genuino board when it's using an external power source (as opposed to 5 volts from the USB connection or other regulated power source). You can supply voltage through this pin, or, if supplying voltage via the power jack, access it through this pin.
- 5V.This pin outputs a regulated 5V from the regulator on the board. The board can be supplied with power either from the DC power jack (7 - 12V), the USB connector (5V), or the VIN pin of the board (7-12V). Supplying voltage via the 5V or 3.3V pins bypasses the regulator, and can damage your board. We don't advise it.
- 3V3. A 3.3 volt supply generated by the on-board regulator. Maximum current draw is 50 mA.
- GND. Ground pins.
- IOREF. This pin on the Arduino/Genuino board provides the voltage reference with which the microcontroller operates. A properly configured shield can read the IOREF pin voltage and select the appropriate power source or enable voltage translators on the outputs to work with the 5V or 3.3V.
Digital pin reads voltage from a given range and transforms it to a set of only two possible values: HIGH and LOW logic state. For example, in Arduino Uno input voltage from range [0, 5] volts is transformed to a value HIGH for input voltage equal to 5V and to LOW for 0V. Being more precise, voltage close to 5V is transformed to HIGH and voltage close to 0V is transformed to LOW. In consequence , you have a following relationship:
Voltage range | Logic level | Logic value |
---|---|---|
[0,0+l] | LOW | 0, false |
[5-h, 5] | HIGH | 1, true |
In my tutorial Potentiometer you can read how you can find values $l$ and $h$ to determine ranges when voltage is treated as HIGH or LOW state.
Analog pin reads voltage from a given range and transforms it to a number, in most cases an integer from a given range. For example, in Arduino input voltage from range [0, 5] volts is transformed to an integer from range [0, 1023]. In consequence, analog pins read continuous signal (analog) but returns a limited number of differnt values (1024).
Sometimes, even if you can only read from an analog pin, you can also choose to use it as a typical digital pin (but the opposite is not true) -- check documentation or pinout of your microcontroller (for Arduino Uno you can use this way any pin from A0 to A5).
To use an analog pin as a digital pin, you simply have to set the mode for the pin, as you would do for digital pins in the setup()
function. Then, you can use the digitalWrite()
and digitalRead()
functions as you do for pure digital pins.
Keep in mind that pin A4 works also as SDA pin, while A5 works as SCL pin when you use I2C bus.
You should separate two aspects of voltages used by electronic devices:
- One voltage level is used to power electronic device.
- At the same time it may happend that your electronic device communicates with other devices using different voltage level, named logic level.
As you can see on the back side of HC-05 module, it uses 5V as a main power voltage while 3.3V to communicate (pins RX and TX).
In consequence you may face the following problems (or their mixture):
- You use two devices powered with two different voltage levels, for example 5V and 3.3V.
- You send logic signals from device where 3.3V = HIGH to device where 5V = HIGH (sending data on one wire from lower logic level to higher logic level).
- You send logic signals from device where 5V = HIGH to device where 3.3V = HIGH (sending data on one wire from higher logic level to lower logic level).
- You send logic signals from/device where 3.3V = HIGH to/from device where 5V = HIGH (bi-directional communication on the same wires).
Let's discusse all of them.
Fortunately there is a very simple solution to our problem. You can use linear voltage regulator, switching converter or use a voltage divider as it is described in my Power tutorial.
Although voltage divider is widely used in many home made application and works quite well you have to remember that the current and voltage across divider produce power, which is dissipated in the form of heat. If that power exceeds the rating of the resistor, the heat begins to become a major problem and potentially may destroy resistor. Another aspect is efficiency or rather inefficiency of a voltage-divider-power-supply. The preffered solution, if you need to drop down a voltage to use it as a power supply, is a voltage regulator or switching converter.
In most cases this is not a problem, because 3.3V is accepted as a HIGH level for 5V logic level devices. As you know from preceding part, this is possible because to HIGH state is maped voltage from interval [5-h,5] volts where in most cases $h$ is big enough so the value 3.3 is in this range. If for some reason case would be different and our 5V device doesn't accept 3.3V as a HIGH level, look into further solutions.
This case is a little bit difficult. Solution seems to be simple: we can use a voltage divider. We will not dive into details about voltage divider here and give only a sample solution to give an idea. For details look into Voltage divider tutorial.


Generally speaking, formula used to calculate $V_{out}$ takes a form
$$V_{out} = \frac{V_{in}R_{2}}{R_{1}+R_{2}}$$
Be careful: I have found some cases when this approach doesn't work. I didn't have time to investigate this but my theory is that this might be a case for high speed communication (high sped switching from one logic state to other).
Todo (id=voltage_level_coexistence:voltage_divider_speed_test): Voltage divider speed test
In such a case we can use ready to use (bi-directional) logic level converter (see next section).
The real problem is when on the same wire sometimes we want send some data but other time receive them. In such a case a bi-directional logic level converter (BD-LLC for short) would be very helpful.


From technical point of view BD-LLC is a very simple device. There is basically one level-shifting circuit on the board, which is repeated four times to create four level-shifting channels. The circuit uses a single N-channel MOSFET and a couple pull-up resistors to realize bi-directional level shifting. Below ther is one the bi-directional level-shifting circuit used on all four channels of the Sparkfun BD-LLC

Let's take a closer look into pinouts of a Sparkfun BD-LLC. The smallest version of the Sparkfun BD-LLC which has 12 total pins – six headers arranged in two rows. One row contains all of the high voltage (e.g. 5V) inputs and outputs, the other row has all things low voltage (e.g. 3.3V).

To make things simple, the pins are labeled on both sides of the board, and organized into groups.
The pins labeled HV, LV, and two GND’s provide high and low voltage references to the board. Supplying a steady, regulated voltage to both of these inputs is required.
There are four separate data channels on this BD-LLC, each capable of shifting data to and from high and low voltages. These pins are labeled HV1, LV1, HV2, LV2, HV3, LV3, HV4, and LV4. The number at the end of each label designates the channel of the pin, and the HV or LV prefix determines whether it’s on the high or low side of the channel. Quite logic, isn't it?
A low-voltage signal sent in to LV1, for example, will be shifted up to the higher voltage and sent out HV1. Something sent in HV3 will be shifted down and sent out of LV3 .
Keep in mind that these level shifters are purely digital. They can’t map an analog voltage from one max voltage to another. Other words, we can't use it instead of voltage regulator or switching converter.
In this example you will see how to use bi-directional logic level converter connecting Bluetooth HC-05 with Arduino Uno.