Micropython: ampliando la capacidad de GPIO del ESP8266 con el PCF8574

Los módulos basados en el ESP8266, como el Nodemcu o el D1 mini son fabulosos para una amplia gama de proyectos, particularmente aquellos que requieren de una conexión a Internet. Sin embargo, la cantidad de pines de E/S (GPIO) es una limitante a la hora de encarar proyectos que requieran de una gran cantidad de conexiones. En este artículo veremos como ampliar la capacidad de GPIO de un módulo basado en el ESP8266 de una manera muy sencilla empleando el circuito integrado PCF8574 controlado desde un programa escrito en Micropython.

El ESP8266 tiene muchos puntos destacables, como la capacidad de conectar a una red Wifi con una gran facilidad, pero sin dudas un punto débil es la cantidad limitada de entradas y salidas digitales (GPIO) con que cuenta para conectarse con otros dispositivos. Además, algunos pines tienen funciones especiales en el momento del arranque, así que su uso posterior tiene ciertas restricciones que nos limitan aún mas.

Afortunadamente, hay una forma sencilla de aumentar la cantidad de pines disponibles con el empleo de un circuito integrado muy popular: el PCF8574. El PCF8574 puede utilizarse como un simple chip o en distintos módulos, para conectar señales de uso múltiple o con alguna funcionalidad especial, como los módulos diseñados especialmente para controlar displays LCD.

El PCF8574 como chip
Módulo para controlar un display LCD
Módulo de ampliación de uso múltiple

El PCF8574

Este popular circuito integrado es un conversor I2C a paralelo, con un registro cuasi-bidireccional de 8 bits. Esto significa que se conecta con el ESP8266 a través de los dos bits de I2C, los que se “convierten” en 8 entradas o salidas digitales denominadas P0 a P7. Cuando funcionan como salidas, estos pines tienen un latch que almacena el valor escrito hasta la siguiente actualización y una capacidad de corriente de 25 mA, lo que permite la conexión de leds u otras cargas que necesiten de cierta corriente. Al ser usados como salidas, los pines del PCF8574 drenan corriente de la carga hacia GND (no suministran corriente a la carga) por lo que debemos conectar un extremo de la misma al positivo y el otro a uno de los pines, como se ve en la siguiente imagen.

Corriente circulando dentro del PCF8574

Esto implica que si escribimos un valor “1” o Alto a la salida (P0 en el ejemplo de la imagen), los dos terminales del Led van a estar a positivo y por lo tanto no va a encender, mientras que si escribimos un “0” o nivel Bajo, el cátodo será mas negativo que el ánodo, con lo que circulará la corriente como se ve en la imagen y el led prenderá. Entonces, la salida funciona invertida: el led prende al escribir “0” y apaga al escribir “1”.

Salidas

Como el PCF8574 drena corriente de la carga, las salidas funcionan invertidas.

Otra consideración importante al momento de utilizar el PCF8574 es que para que los pines (P0..P7) funcionen como entradas, primero debemos escribir un valor “1” en la salida correspondiente. Al encenderlo, esta es la condición por defecto.

Entradas

Antes de usar un pin como entrada debemos escribir en él un valor “1”.

No es necesario configurar o programar la dirección de cada pin. En cualquier momento podemos utilizarlo como salida o entrada, a condición de que tengamos la precaución mencionada anteriormente.

Respecto a la tensión de alimentación, el PCF8574 puede ser alimentado en un rango amplio, entre los 2,5V y los 5,5V, así que puede ser utilizado en módulos y micros que funcionen tanto a 3,3V como con 5V.

Conexión básica de un PCF8574 (Fuente: Texas Instruments)

Se pueden conectar hasta 8 PCF8574 en el mismo bus I2C, lo que nos da la posibilidad de tener hasta 64 entradas y salidas. Para ello debemos configurar la dirección de cada uno de ellos, conectando a VCC o GND los pines A0, A1 y A2, con lo que podremos identificar a cada chip en el bus I2C con una dirección individual a partir de 0x20, como se puede ver en la siguiente tabla:

Pines A0..A2 y direcciones I2C

Cada uno de los pines P0 a P7 es capaz de manejar hasta 25 mA cuando se lo usa como salida, pero la corriente máxima que soporta el chip considerando el total de las salidas es de 100 mA, así que debemos tener especial cuidado en limitar el consumo individual si vamos a usar varias salidas simultáneamente.

Finalmente, la salida INT permite generar una interrupción en el ESP8266 cuando cambia cualquiera de los pines que se usen como entrada. Esto es particularmente útil porque evita tener que leer continuamente las entradas para detectar algún cambio: si usamos la interrupción, podemos esperar a que el PCF8574 “nos avise” que cambió una entrada y en la rutina de interrupciones leer las entradas y procesarlas.

Programación

No es difícil escribir nuestro propio código para controlar el PCF8574 a través del bus I2C, sin embargo, hay varios módulos ya probados que funcionan correctamente y nos permiten ahorrar ese tiempo y esfuerzo.

El que usaré en los ejemplos es el escrito por Mike Causer y que se puede descargar desde su repositorio.

Como siempre que usamos un módulo no estándar, que no está incluido en el firmware de Micropython, debemos descargarlo primero y copiarlo luego a nuestra placa. En el caso de que usemos Thonny, podemos abrirlo y luego copiarlo usando Fichero – Guardar Como – Micropython device.

Una vez hecho esto, podemos importarlo en nuestro código. Como también usaremos el bus I2C y los pines GPIO, deberemos importar las clases correspondientes del módulo machine:

import pcf8574
from machine import I2C, Pin

Luego creamos un objeto para el bus I2C, inicializándolo en los pines GPIO4 y GPIO5 que en la placa D1 Mini que usaré de ejemplo corresponden a las señales SDA y SCL.

i2c = I2C (scl=Pin(5), sda=Pin(4))

Luego podemos crear o instanciar un objeto de la clase PCF8574 del módulo que incluimos, cuyo constructor requiere el objeto del bus I2C y su dirección.

pcf = pcf8574.PCF8574 (i2c, 0x20)

Esta clase cuenta con los siguientes métodos:

pin (pin, valor): Escribe valor en el pin número pin. Si no se especifica valor, entonces devuelve el valor leído en ese pin.

toggle (pin): Cambia el estado de pin

Además, tiene la siguiente propiedad:

port: Valor de los 8 bits como conjunto. Si escribimos en esta propiedad, escribimos en todos los pines al mismo tiempo y si la leemos, leemos todos los pines al mismo tiempo.

Veamos una serie de ejemplos de aplicación, basados en el siguiente circuito, que utiliza los pines P0, P1 y P2 como salidas para controlar Leds y el pin P3 como una entrada.

Esquemático del circuito de pruebas
Circuito de pruebas

Ejemplo1: Control de salidas individuales

En este ejemplo haremos el típico “Blink” con tres leds conectados al PCF8574

import pcf8574
from machine import I2C, Pin

from time import sleep

#definir el puerto I2C en D1, D2 (GPIO5, GPIO4) del D1 Mini
i2c = I2C (scl=Pin(5), sda=Pin(4))

#Definir objeto pcf
pcf = pcf8574.PCF8574(i2c, 0x20)

ON = 0
OFF = 1

while (True):
     #Prende los 3 leds
     pcf.pin (0, ON)
     pcf.pin (1, ON)
     pcf.pin (2, ON)
     sleep (1)
     #Apaga los 3 leds
     pcf.pin (0, OFF)
     pcf.pin (1, OFF)
     pcf.pin (2, OFF)
     sleep (1)

Ejemplo2: Lectura de una entrada

En este segundo ejemplo se usa el Pin 3 como entrada, que se pone a nivel 1 o Alto en la línea 14.

import pcf8574
from machine import I2C, Pin
from time import sleep

#definir el puerto I2C en D1, D2 (GPIO5, GPIO4) del D1 Mini
i2c = I2C (scl=Pin(5), sda=Pin(4))

#Definir objeto pcf
pcf = pcf8574.PCF8574(i2c, 0x20)

ON = 0
OFF = 1

pcf.pin (3, 1)  #Poner a 1 el Pin3 para usarlo como entrada

while (True):
     #Ver el valor de la entrada 3
     if (pcf.pin(3) == 1):
         #Prender si vale 1
         pcf.pin (0, ON)
         pcf.pin (1, ON)
         pcf.pin (2, ON)
     else:
         #Apagar si vale 0
         pcf.pin (0, OFF)
         pcf.pin (1, OFF)
         pcf.pin (2, OFF)

Ejemplo3: Escritura del puerto completo y Toggle

Finalmente, en este ejemplo vemos como escribir el puerto completo y como usar el método Toggle.

import pcf8574
from machine import I2C, Pin
from time import sleep

#definir el puerto I2C en D1, D2 (GPIO5, GPIO4) del D1 Mini
i2c = I2C (scl=Pin(5), sda=Pin(4))

#Definir objeto pcf
pcf = pcf8574.PCF8574(i2c, 0x20)

ON = 0
OFF = 1

#Apaga los tres leds poniendo todo a 1
pcf.port = 0xff

while (True):
     #Parpadea
     pcf.toggle (0)
     sleep (1)

Conclusión

El PCF8574 tiene innumerables aplicaciones, siendo sumamente útil en aquellos casos en los que nuestro micro tenga pocos pines de GPIO como es el caso concreto del ESP8266. Su programación es muy sencilla. Aunque existen varios módulos para su uso desde Micropython, algunos con mas funciones que otros, vimos uno básico que tiene las funciones elementales pero que es suficiente para aprovechar las capacidades del chip.

Espero que el artículo les haya sido de utilidad, y como siempre, cualquier sugerencia o duda pueden dejarla en la sección de comentarios mas abajo.

2 comentarios en «Micropython: ampliando la capacidad de GPIO del ESP8266 con el PCF8574»

  1. Muchas Gracias Profe, una consulta, es aplicable al nodeMCU esp32 tambien, no? aunque tiene mas pines, se podria utilizar igual? Mas allá del cuidado del consumo que hay que tener, con que otra desventaja nos encontrariamos? Vayamos al ejemplo: un esp32 de 30 pines contra uno de 36 pines, es lo mismo en ampliar el de 30 pines con el PCF que cambiarlo por uno de 36 pines? Salvando la complicación de armar toda la electrónica, no? Digo, operacionalmente es igual? Gracias por sus aportes…

    Responder
    • Hola Mario!
      En lo que hace a módulos como los NodeMCU, Wemos D1 o D1 mini, debería aplicarse a todos por igual, porque todas tienen el ESP8266 y algunas diferencias en lo que hace a la cantidad o distribución de señales. En el caso del ESP32 en principio también, aunque no lo he probado todavía, pero el funcionamiento es exactamente el mismo.

      Responder

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

A %d blogueros les gusta esto: