Una de las particularidades del NodeMCU con el chip ESP8266 es tener un solo puerto analógico, a diferencia del Arduino UNO o Nano que tienen varios, esta diferencia genera que al momento de querer trabajar con más de un sensor analógico tengamos una limitante y debamos buscar alternativas.
Podemos resolver este problema utilizando diferentes métodos, por ejemplo utilizar un Arduino conectado al NodeMCU para que sense los valores de los sensores analógicos y los comunique por serie; pero se incorpora cierta complejidad y no podríamos resolver todo con MicroPython en un solo programa.
![](https://www.gsampallo.com/blog/wp-content/uploads/2019/09/multiplexor.png)
La solución que encontré es con un pequeño chip llamado 74HC4067 que nos permite tener hasta 16 entradas analógicas por medio de una multiplexación de 4 canales digitales.
La forma de conectarlo es la siguiente:
![](https://www.gsampallo.com/blog/wp-content/uploads/2019/09/analog_multiplexer-1024x419.png)
NodeMCU Pin | Multiplexor Analógico |
D4 | S0 |
D3 | S1 |
D2 | S2 |
D1 | S3 |
VCC | 3v3 |
GND | GND |
EN | GND |
SIG | A0 |
En el diagrama anterior tenemos conectado la salida de cada potenciometro a un puerto analógico de 74HC4067, en nuestro ejemplo solo utilizaremos 3 entradas para mostrar su uso. Cada sensor analógico va conectado en alguno de los puerto C0-C15.
Para poder leer cada uno de los valores de los puertos C0-C15 tenemos que poner en HIGH o LOW los puertos S0-S3 siguiendo la tabla indicada por el fabricante, se puede encontrar en el siguiente link: http://www.ti.com/lit/ds/symlink/cd74hct4067.pdf.
![](https://www.gsampallo.com/blog/wp-content/uploads/2019/09/tabla.png)
De esta forma si queremos leer el puerto C0 debemos poner en en LOW D4,D3,D2 y D1. Para leer el puerto C1 seria HIGH D4 y LOW D3,D2 y D1. Extendiendo esto se entiende la idea.
Si solo deseamos leer los puerto C0, C1 y C3 para poder probar el ejemplo del diagrama se puede utilizar el siguiente código de ejemplo:
from machine import Pin, ADC
import time
s0 = Pin(2, Pin.OUT)
s1 = Pin(0, Pin.OUT)
s2 = Pin(4, Pin.OUT)
s3 = Pin(5, Pin.OUT)
adc = ADC(0)
while True:
# Se lee C0
# Todos los pins van a LOW
s0.off()
s1.off()
s2.off()
s3.off()
c0 = adc.read()
# Se lee C1
# Ponemos en HIGH S0 y el resto en LOW
s0.on()
s1.off()
s2.off()
s3.off()
c1 = adc.read()
# Se lee C2
# Ponemos en HIGH S1 y el resto en LOW
s0.off()
s1.on()
s2.off()
s3.off()
c2 = adc.read()
print(c0,c1,c2)
time.sleep_ms(250)
Si en cambio deseamos tener una forma dinámica de acceder a cada uno de los pins, podemos crear una lista con los elementos de la tabla de verdad anterior y recorrerla según el nro. de pin analógico que deseamos leer, a continuación el programa completo:
from machine import Pin, ADC
import time
s0 = Pin(2, Pin.OUT)
s1 = Pin(0, Pin.OUT)
s2 = Pin(4, Pin.OUT)
s3 = Pin(5, Pin.OUT)
adc = ADC(0)
multiplexor = [
[0,0,0,0], #0
[1,0,0,0], #1
[0,1,0,0], #2
[1,1,0,0], #3
[0,0,1,0], #4
[1,0,1,0], #5
[0,1,1,0], #6
[1,1,1,0], #7
[0,0,0,1], #8
[1,0,0,1], #9
[0,1,0,1], #10
[1,1,0,1], #11
[0,0,1,1], #12
[1,0,1,1], #13
[0,1,1,1], #14
[1,1,1,1], #15
]
pinCx = list(range(0,15))
while True:
# Si queremos leer los valores de todos los puertos Cx
for pin in pinCx:
s0.value(multiplexor[pin][0])
s1.value(multiplexor[pin][1])
s2.value(multiplexor[pin][2])
s3.value(multiplexor[pin][3])
cx = adc.read()
print(pin," = ",cx)
# Se lee C2
# Ponemos en HIGH S1 y el resto en LOW
s0.value(multiplexor[2][0])
s1.value(multiplexor[2][1])
s2.value(multiplexor[2][2])
s3.value(multiplexor[2][3])
c2 = adc.read()
print("Valor de C2 = ",c2)
time.sleep_ms(250)
Si utilizamos una función, podemos simplificar aún mas:
def valor_analogico(cx):
s0.value(multiplexor[pin][0])
s1.value(multiplexor[pin][1])
s3.value(multiplexor[pin][3])
s2.value(multiplexor[pin][2])
lectura = adc.read()
return lectura
Para utilizar simplemente invocamos de la siguiente manera:
lectura = valor_analogico(2) #leemos C2
Se puede encontrar el ejemplo en github:
https://github.com/gsampallo/micropython_examples/blob/master/74HC4067/multiplexor.py