PCF8574 Expansor E/S a I2C

          El CI PCF8574 es un expansor de 8-bit de líneas de entrada y/o salida a interfaz I2C. Es decir con solo dos hilos SCL y SDA podemos controlar ocho líneas. Funciona entre 2,5 y 6 voltios. Las salidas pueden controlar directamente LED (25mA). En el arranque, todas las líneas (p0-p7) están en alto. Con los A0, A1 y A2 podemos definir su dirección. Yo he usado un módulo ya ensamblado con dirección 0x20.
          Aunque usaré dos librerías para manejar un teclado y otra para entradas y salidas, estrictamente no las necesitaríamos ya que escribir o leer del I2C es sencillo.  En primer lugar usamos este montaje.
#include <Wire.h> 
const int address = 0x20;
 
void setup(){
   Wire.begin();
}
 
void loop(){
   for (short channel = 0; channel < 8; channel++){
      // Escribir dato en cada uno de los 8 canales
      Wire.beginTransmission(address);
      //Enviamos en binario el nivel que queremos en los 8 pines.
      //En este caso se enciende solo el led verde.
      //El cuarto cero contando desde la derecha.
      Wire.write(B00010111);
      Wire.endTransmission();
   }
}
#include <PCF8574.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
// Definir constantes
#define ANCHO_PANTALLA 128 // ancho pantalla OLED
#define ALTO_PANTALLA 64 // alto pantalla OLED
// Objeto de la clase Adafruit_SSD1306
Adafruit_SSD1306 display(ANCHO_PANTALLA, ALTO_PANTALLA, &Wire, -1);
PCF8574 pcf20(0x20);

const byte LedRojo = 2, LedVerde = 3, LedAzul = 4;

unsigned int blinkMillis;
unsigned int RMillis, VMillis, AMillis;

void setup() {
  Serial.begin(115200);
  pcf20.begin();
  // Iniciar pantalla OLED en la dirección 0x3C
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
   #ifdef __DEBUG__
    Serial.println("No se encuentra la pantalla OLED");
   #endif
    while (true);
  }     
}

void loop() {
  static bool stateR, stateV, stateA;
  unsigned int currentMillis = millis();
   if(currentMillis - RMillis >= 1000){  //Led rojo cada segundo
    RMillis = currentMillis;
    stateR=!stateR;
    pcf20.write(LedRojo, stateR);
  }
  if(currentMillis - VMillis >= 500){   //Led verde cada medio segundo
    VMillis = currentMillis;
    stateV=!stateV;
    pcf20.write(LedVerde, stateV);
  }
  if(currentMillis - AMillis >= 2000){  ////Led azul cada 2 segundos
    AMillis = currentMillis;
    stateA=!stateA;
    pcf20.write(LedAzul, stateA);
  }

  //Datos por Serial cada medio segundo
  if(currentMillis - blinkMillis >= 500){
    //actualiza time
    blinkMillis = currentMillis;
    Serial.print("Valor leido: ");
    Serial.println(pcf20.read8(), BIN);
    display.clearDisplay();   
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(0,0);
    display.println(" Botones   pulsados");
    display.setTextSize(3);   

    if(!pcf20.read(0)){  //Lee boton en p0
     display.setCursor(30,40);
     display.println("0");
    }
   if(!pcf20.read(1)){  //Lee boton en p1
     display.setCursor(80,40);
     display.println("1");
    }   
    display.display(); 
  }
}
          Vemos arriba un ejemplo sin usar librerías

          A la derecha con el uso de la librería PCF8574.h que nos permite mayor comodidad en la programación.

         Todos estas facilidades podemos verlas en la página de gitbub del autor

        Por ejemplo podemos leer o escribir solo pin
read(pin), Write(pin, value)



   read8() reads all 8 pins at once. This one does the actual reading.
   
read(pin) reads a single pin; pin = 0..7
  
value() returns the last read inputs again, as this information is buffered in the class this is faster than reread the pins.
   
write8(value) writes all 8 pins at once. This one does the actual reading.
   
write(pin, value) writes a single pin; pin = 0..7; value is HIGH(1) or LOW (0)
   
valueOut() returns the last written data.
          En el Sketch he incluido una pantalla OLED para ver la pulsación de los botones

         Recordar que por defecto los 8 pines del PCF8574 está a nivel alto, por eso los LED están conectados al positivo y estarán apagados. Al poner un pin a masa se encenderá.

         Advertir que no está enm el esquema, pero todos los LED  tiene una resistencia limitadora de 220Ω


        
También advertir que las salidas del modulo PCF8574 son de tipo Latch, por lo que mantienen el valor asignado sin necesidad de refresco constante y las mantiene al apagar y volver a encender el circuito.



          El esquema para usar el PCF8574 para gestionar un teclado 4x4 o menor.

          La salida de información también es en un display OLED y por serial.
#include "Wire.h"
#include "I2CKeyPad.h"
#include <Adafruit_SSD1306.h>
// Definir constantes
#define ANCHO_PANTALLA 128 // ancho pantalla OLED
#define ALTO_PANTALLA 64 // alto pantalla OLED
// Objeto de la clase Adafruit_SSD1306
Adafruit_SSD1306 display(ANCHO_PANTALLA, ALTO_PANTALLA, &Wire, -1);

const uint8_t KEYPAD_ADDRESS = 0x20;
I2CKeyPad keyPad(KEYPAD_ADDRESS);
uint32_t start;
uint32_t lastKeyPressed = 0;

void setup(){
  Serial.begin(115200);
  Wire.begin();
  Wire.setClock(400000);
  if (keyPad.begin() == false){
    Serial.println("\nERROR: sin comunicación al teclado.");
    while(1);
  }
  // Iniciar pantalla OLED en la dirección 0x3C
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
#ifdef __DEBUG__
    Serial.println("No se encuentra la pantalla OLED");
#endif
    while (true);
  } 
  display.setTextSize(4);
  display.setTextColor(WHITE);
  display.setCursor(0,25); 
}

void loop(){
  uint32_t now = millis();
  char keys[] = "123A456B789C*0#DNE";  // N = Ninguna tecla, F = Error
  if (now - lastKeyPressed >= 100){
    lastKeyPressed = now;
    uint8_t idx = keyPad.getKey();
    Serial.print(idx);
    Serial.print("\t");
    Serial.println(keys[idx]);
    display.clearDisplay();
    display.setCursor(15,20);    
    display.println(keys[idx]);
    display.display();
  }
}
Menu