mas-pines-digitales-con-arduino-y-el-expansor-es-i2c-pcf8574

Más pines digitales con Arduino y expansor E/S I2C PCF8574

¿Qué es el PCF8574?

El PCF8574 es un expansor de entradas y salidas digitales por bus I2C fabricado por Philips. Puede conectarse a un procesador como Arduino para controlar más dispositivos empleando con menos pines.

El PCF8574 incorpora 8 pines cuasi-direccionales basados en salidas CMOS en configuración drenador abierto. Esto significa que pueden ser empleados tanto como entradas como salidas, con ciertas consideraciones que veremos en el apartado de conexión y montaje.

La corriente máxima que puede suministrar cada pin, cuando actúa como salida, es de 25mA cuando actúa como sink (sumidero, la corriente fluye hacia el PCF8574) y 300µA cuando actúa como source (fuente, la corriente fluye desde el PCF8574). Por tanto, la configuración normal es como sink.

Todas las salidas disponen de Latches, es decir, mantienen el estado por sí mismas sin necesidad de acciones desde Arduino. Únicamente debernos actuar cuando queramos modificar el estado de unas de las salidas.

arduino-pcf8574-interior

La comunicación se realiza a través del bus I2C, por lo que es sencillo obtener los datos medidos. Dispone de 3 pines de dirección, lo que da 8 posibles conectados al mismo bus I2C. Por tanto, es posible controlar 64 dispositivos usando únicamente 2 pines.

También dispone de una línea de interrupción (INT) que puede ser empleada para detectar una variación en uno de sus pines. Conectada a un pin de interrupciones de Arduino podemos detectar la recepción de datos sin necesidad de monitorizar constantemente por el estado de las entradas.

La tensión de alimentación del PCF8574 es entre 2.5V y 6V. Por otro lado su consumo en stand-by es muy bajo, inferior a 10 µA.

Podemos emplear el PCF8574 para ampliar el número de entradas y salidas digitales disponibles, y controlar 8 dispositivos (o hasta 64 si usamos varios módulos) únicamente con 2 pines. Esto es especialmente útil en modelos de Arduino con menor número de pines, como el Attiny85 empleado en placas Digispark .

Precio

Podemos encontrar módulos con PCF8574 listos para conectar con Arduino por 1.30€, buscando en vendedores internacionales de eBay y AliExpress.

arduino-pcf8574-componente

En caso de adquirir el integrado suelto, sin el módulo, podemos encontrarlos por 0.30€.

Esquema de montaje

La conexión de los módulos que integran el PCF8574 es bastante sencilla, simplemente alimentamos el módulo desde Arduino mediante GND y 5V y conectamos el pin SDA y SCL de Arduino con los pines correspondientes del sensor.

arduino-pcf8574-esquema

En caso de estar usando el integrado directamente, el esquema de conexión sería el siguiente.

arduino-PCF8574-integrado

En ambos casos la conexión vista desde Arduino sería la misma, según el siguiente esquema

arduino-PCF8574-conexion

En Arduino Uno, Nano y Mini Pro, SDA es el pin A4 y el SCK el pin A5. Para otros modelos de Arduino consultar el esquema patillaje correspondiente.

Conectar las cargas a cada uno de los 8 pines tampoco es difícil, si tenemos en cuenta ciertas consideraciones. Como hemos dicho cada pin cuasi-bidireccional tiene configuración de drenador abierto.

A modo resumen algo simplificado, dentro de cada pin tenemos un transistor CMOS junto con una débil resistencia de pull-up, que impone una intensidad de corriente de 100 uA cuando el transistor está activado.

arduino-transistor-mosfet-montaje-inductiva

Cuando el pin actúa como salida el PCF8574 actúa como sumidero de corriente, es decir, la corriente fluye hacia dentro, y la lógica de las salidas está negada.

  • Cuando la salida está en LOW el voltaje visto por la carga vale Vdd, y por tanto no conduce corriente.
  • Cuando la salida está en HIGH la carga queda conectada a Gnd, y puede pasar hasta 25 mA.

Cuando el pin del PCF8574 actúa como entrada deberemos ponerlo siempre a HIGH. En estas condiciones, la resistencia interna de pull-up limita la corriente de pérdidas a 100 uA. Al conectar una carga, deberemos usar una resistencia de pull-up, igual que hacemos siempre que leemos un pulsador.

  • Cuando la carga externa está cerrada, la tensión en el pin pasa a GND.
  • Cuando la carga externa está abierta, la tensión en el pin pasa a Vdd.

Ejemplos de código

Sin librería

El siguiente código muestra el uso del PCF8574 como salida. En el ejemplo, encendemos y apagamos en bucle cada uno de los pines. Observar que la señal del canal se envía negada, porque el PCF8574 actúa como sumidero de corriente y el pin está activo cuando la salida es LOW.

#include <Wire.h>

const int pcfAddress = 0x38;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

void loop()
{
  for (short channel = 0; channel < 8; channel++)
  {
    // Escribir dato en canal 'channel'
    Wire.beginTransmission(pcfAddress);
    Wire.write(~(1 << channel));
    Wire.endTransmission();
    
    // Leer dato de canal
    delay(500);
  }
}

El siguiente código muestra el uso del PCF8574 como entrada. En el ejemplo realizamos la lectura progresiva de cada uno de los pines, y mostramos su valor por puerto serie.

#include <Wire.h>

const int pcfAddress = 0x38;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

void loop()
{
  short channel = 1;
  byte value = 0;

  // Leer dato de canal 'channel'
  Wire.requestFrom(pcfAddress, 1 << channel);
  if (Wire.available())
  {
    value = Wire.read();
  }
  Wire.endTransmission();

  // Mostrar el valor por puerto serie
  Serial.println(value);
}

Con librería

Alternativamente podemos emplear una librería como la desarrollada por SkyWood disponible en https://github.com/skywodd/pcf8574_arduino_library. La librería proporciona códigos de ejemplo para ilustrar su uso. No obstante, aquí tenéis un ejemplo resumido que muestra su uso

#include <Wire.h>
#include "PCF8574.h"

PCF8574 expander;

void setup() 
{
  Serial.begin(9600);
  
  expander.begin(0x20);
  
  /* Setup some PCF8574 pins for demo */
  expander.pinMode(0, OUTPUT);
  expander.pinMode(1, OUTPUT);
  expander.pinMode(2, OUTPUT);
  expander.pinMode(3, INPUT_PULLUP);

  /* Blink hardware LED for debug */
  digitalWrite(13, HIGH);  
  
  /* Toggle PCF8574 output 0 for demo */
  expander.toggle();
  
  /* Blink hardware LED for debug */
  digitalWrite(13, LOW);
}

void loop() 
{
}

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github. github-full