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(); } }
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.
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(); } }