Increase the Number of Analog Inputs with an Analog Multiplexer

Increase the Number of Analog Inputs with an Analog Multiplexer

One of the most used micrcontroller in the DIY playground is the ESP8266.

The ESP8266 NodeMCU or the WeMos D1 Mini have one mayor downside because there have only 1 analog input pin on the board.

In this tutorial I show you how to increase the number of analog inputs to 4, 8 or 16 with an analog multiplexer.

Analog Multiplexer Thumbnail

Table of Contents

Function of a Multiplexer

In my opinion the best explanation of a multiplexer is a big switch which connects all inputs with one output. Which input is connected to the output is defined by the state of the select lines pins.
Because only one input is connected to the output, all other lines loose the connection. This is important because devices that require a continuous signal (like a servo motor) will not work in combination with a multiplexer.

Multiplexer Schema

A multiplexer of 2^n inputs has n select lines which is shown in the following table.

 

Number of inputs

Number of select lines

2

1

4

2

8

3

16

4

In this tutorial I use the CD74HC4051 analog multiplex from Texas Instruments

74HC4051 Data Sheet and Pins

Before we start with the practical example, let us quickly summarize the data sheet of the CD74HC4051.
The 74HC4051 is an 8 bit analog multiplexer / demultiplexer and therefore build up with bidirectional switches that allow any analog input to be used as an output and the way around.

The most important value is the maximum input voltage with is 5V for the analog multiplexer. The 5V fits well with all Arduino and the EPS8266 based microcontroller. You find the whole data sheet here.

CD74HC4051

74HC4051 pin

Description and Connection

A0…A7

Analog inputs for multiplexing and demultiplexing (in our example connected to the analog inputs: photoresistor and potentiometer)

GND

Connect to ground on the microcontroller

VCC

Connect to 5V on the microcontroller (2V…6V)

S0…S2

3 select lines for the 8 bits

A

Analog output is connected to an analog pin on the microcontroller (in our example A0 on the NodeMCU)

E

Enable state to enable or disable the functionality (active when LOW)

VEE

Negative power input to operate on negative voltages (0…-6V)

The functionality of the CD74HC4051 as analog multiplexer is easy explained in two steps:

  1. The multiplexer gets the select line signal from the 3 digital outputs of the microcontroller.
  2.  If the enable state is set to LOW, the corresponding analog input (A0…A7) is connected with the analog output (A)

The following table shows the input states of the CD74HC4051 and the corresponding analog output channel.

If Enable (E) is HIGH the multiplexer is disabled independent of the select line signals.

Input States

Analog Output

Enable (E)

S2

S1

S0

LOW

LOW

LOW

LOW

A0

LOW

LOW

LOW

HIGH

A1

LOW

LOW

HIGH

LOW

A2

LOW

LOW

HIGH

HIGH

A3

LOW

HIGH

LOW

LOW

A4

LOW

HIGH

LOW

HIGH

A5

LOW

HIGH

HIGH

LOW

A6

LOW

HIGH

HIGH

HIGH

A7

HIGH

X

X

X

None

Increase the Analog Inputs on the ESP8266

In the following example we increase the number of analog inputs of the ESP8266 NodeMCU and WeMos D1 Mini, which have only one analog input pin. The analog inputs I choose are:

  • 1 photoresistor
  • 1 potentiometer

But you can choose any other analog device.

The following pictures show the wiring between all components and the ESP8266 microcontroller.

NodeMCU Analog Multiplexer

WeMos D1 Mini Analog Multiplexer

The photoresistor is connected to the 74HC4051 via a voltage divider with a 10kΩ resistor on pin A1. The potentiometer is directly connected to the multiplexer on pin A0. All other analog pins are connected to ground. Moreover the pins VEE and E are also connected to ground. The address select pins are connected to the ESP8266 like the following: 

  • S0 -> D3
  • S1 -> D2
  • S2 -> D1

Now lets dive in to the program code. I split the code in two parts so that you can copy both and past in your Arduino IDE.

const int selectPins[3] = {D3, D2, D1};
const int analogInput = A0;

void setup() 
{
  Serial.begin(9600);
  // Set up the select pins as outputs:
  for (int i=0; i<3; i++)
  {
    pinMode(selectPins[i], OUTPUT);
    digitalWrite(selectPins[i], HIGH);
  }
  
  // Create header table
  Serial.println("Y0\tY1\tY2\tY3\tY4\tY5\tY6\tY7");
  Serial.println("---\t---\t---\t---\t---\t---\t---\t---");
}

First we have to define the connected pins. As mentioned before we connected the 3 digital pins D3, D2, D1 as well as the analog input A0. For the digital pins we create an array to loop through the pins easily during later stages in the code.

In the setup function we first set the baud rate to 9600 which must match to the rate in the serial monitor. Then we loop through the selectPins array and set every digital pin as output
The last part of the setup function is more an optical preference. We create a virtual table in the serial monitor by setting a tabulator space between all possible 8 analog values.

void loop() 
{
  // Loop through all eight pins.
  for (byte pin=0; pin<=7; pin++)
  {
      for (int i=0; i<3; i++) {
          digitalWrite(selectPins[i], pin & (1 << i)?HIGH:LOW);
      }
      int inputValue = analogRead(analogInput);
      Serial.print(String(inputValue) + "\t");
  }
  Serial.println();
  delay(1000);
}

In the loop function we loop over all 8 possible analog pins and set the select pins HIGH and LOW with a little bit confusing formula. But the following table shows all the different combinations to get the selected pins set correct.

We calculate the state of each select pin in 3 steps:

  1. 1<<i: calculate the bit-shift of each 3 select pins
  2. pin & (1<<i): bitwise AND with the selected analog output which should be selected
  3. pin & (1<<i)?HIGH:LOW: calculate the ternary conditional which is in this case very easy. If pin & (1<<i) is 0, then set the condition to LOW and otherwise HIGH.

pin

i

1<<i

pin & (1<<i)

pin & (1<<i)?HIGH:LOW

Input state

Analog Output

0 (0000)

1

0001

0 (0000)

0

S0

A0

0 (0000)

2

0010

0 (0000)

0

S1

0 (0000)

3

0100

0 (0000)

0

S2

1 (0001)

1

0001

1 (0001)

1

S0

A1

1 (0001)

2

0010

0 (0000)

0

S1

1 (0001)

3

0100

0 (0000)

0

S2

2 (0010)

1

0001

0 (0000)

0

S0

A2

2 (0010)

2

0010

2 (0010)

1

S1

2 (0010)

3

0100

0 (0000)

0

S2

3 (0011)

1

0001

1 (0001)

1

S0

A3

3 (0011)

2

0010

2 (0010)

1

S1

3 (0011)

3

0100

0 (0000)

0

S2

4 (0100)

1

0001

0 (0000)

0

S0

A4

4 (0100)

2

0010

0 (0000)

0

S1

4 (0100)

3

0100

4 (0100)

1

S2

5 (0101)

1

0001

1 (0001)

1

S0

A5

5 (0101)

2

0010

0 (0000)

0

S1

5 (0101)

3

0100

4 (0100)

1

S2

6 (0110)

1

0001

0 (0000)

0

S0

A6

6 (0110)

2

0010

2 (0010)

1

S1

6 (0110)

3

0100

4 (0100)

1

S2

7 (0111)

1

0001

1 (0001)

1

S0

A7

7 (0111)

2

0010

2 (0010)

1

S1

7 (0111)

3

0100

4 (0100)

1

S2

After we set the select pins, the analog multiplexer is configured to read the desired output. We read the analog value with the build in function analogRead and print the value to the serial monitor. Each value is separated with a tabulator like the header we created in the setup function.

Now the program is reading all analog input values. In the following picture you see a screenshot of the serial monitor

Analog Multiplexer Serial Output

The first value Y0 is the potentiometer. You see from the picture that I increase and decrease the resistance and therefore the analog value. The second value Y1 is the photoresistor which I influence by holding my hand on it to make it dark and change the analog value.

One thing that surprises me is that all other analog values Y2…Y7 are not always 0 although I connected all other analog input pins on the multiplexer with ground. My assumption is that there are some back coupling between the analog signals but I do not know how to remove the noise in the analog signals which are connected to ground. If you know why the other analog values are not zero, write your suggestion in the comment section below.

I also installed a decoupling capacitor between VCC and ground on the 74HC4051 because I saw this circuit for the sparkfun 74HC4051 multiplexer breakout board. But after the installation of the decoupling capacitor there was no change in the serial monitor.

In my opinion, either you know which analog signals from the multiplexer are connected and only read for example the first three or you can set a threshold > 10 to read all analog signals.

I hope you like this tutorial how you can increase the analog inputs on your ESP8266 NodeMCU or WeMos D1 Mini for your next project. If you have any questions you can use the comment section below and I will ask your questions as soon as possible.

If you are also interested how to increase the number of digital outputs with a shift register, then I can recommend this article.

12 Responses

Leave A Comment