Expansor de portas PCF8574 - Preciso muito de ajuda


#1

Olá pessoal, tudo bem?
Gostaria muito da ajuda de vocês pois há alguns dias venho tentando operar o PCF8574P e não consig
Não sou nenhum expert em eletronica, mas possuo conhecimento básico, e gosto de mexer em projetos com arduino
Agora estou em um projeto onde tenho a necessidade de aumentar o número de portas que serão utilizadas como entrada e para isso recorri ao PCF8574P

Já tentei seguir inúmeros circuitos, como por exemplo:


Mas até agora (já estou a dias tentando e pesquisando, por isso resolvi pedir ajuda) nâo consegui fazer funcionar nada, nem operando como expansor de entradas ou saidas.

Segue um checklist do que já fiz para tentar resolver:

  • Revisei, montei e remontei os circuitos inúmeras vezes
  • Tentei utilizar o PCF8574 com diferentes configurações de endereço (através dos pinos A0 A1 A2)
  • Coloquei resistores pull up nos terminais SDA e SCL
  • Troquei o PCF8574 2 vezes, pois pensei que poderia ter danificado por alguma ligação errada
  • Utilizei o Sketch de SCANNER I2C (https://playground.arduino.cc/Main/I2cScanner) ao realizar isso nunca nenhum endereço retorna nada. Na maioria dos testes que realizei deixei o PCF8574 com todos os pinos de endereço no GND, nesse caso o scan não deveria encontrar um dispositivo I2C no endereço 32 (decimal)?
  • Não é problema no Arduino, pois já fiz um teste utilizando um segundo arduino como I2C slave e a comunicação funciona normalmente

Enfim, de verdade já tentei inúmeras vezes e não consegui nada
Alguém pode me dar uma luz ou uma direção a seguir?

Tem outra coisa que acho dificil, mas por desencargo, vale a pena comentar

1 - A loja onde comprei os PCF8574P fica na minha cidade (é uma loja pequena, onde não se costuma encontrar uma variedade muito grande de CI’s, normalmente vou até outra cidade comprar minhas peças ou compro pela internet, achei até estranho encontrar este CI lá rsrs)
Existe a possibilidade de este CI que estou utilizando ser um CI com outra função e não um PCF8574. Apesar que o CI está claramente com o nome e marca legível (Philips PCF8574P). É possível existir um CI com mesmo nome?


#2

Talvez isso ajude:


#3

Cara, acho que o adequado seria você postar o código que você está usando pra podermos dar uma olhada.

Posso sugerir um teste bem simples? Aterre os pinos 1, 2, 3, 11 e 12. Cheque se a conexão do SDA e SCL estão OK e tente ler a partir dos endereços 0x40 (64 decimal), 0x20 (32) e 0x38 (56), um deles deve ser o do seu CI.
De acordo com o datasheet da Philips o correto seria 0x40, então comece tentando ele.

Printe o valor lido na porta serial: Se o resultado for 0x3f, 63 ou “?” você (ironicamente) leu certo.

Eu nunca vi um CI marcado como algo não ser o que o nome sugere mas ser outro. Mas também, se visse, eu certamente o consideraria um CI defeituoso e jogaria fora, não pararia pra ver se ele faz alguma coisa diferente do que eu esperava que ele fizesse.


#4

Lint, desde já muito obrigado pela ajuda!

Aterrei os pinos 1, 2, 3, 11 e 12 e chequei a conexão SDA e SCL
Sem sucesso ainda =/

O código que estou usando no momento é um de Scanner I2C (https://playground.arduino.cc/Main/I2cScanner)
Primeiro quero conseguir identificar o I2C, depois implementar os códigos de leitura das portas

Porém até agora não consegui se quer identificar o PCF8574 conectado ao arduino


#5
//
//    FILE: MultiSpeedI2CScanner.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.7
// PURPOSE: I2C scanner at different speeds
//    DATE: 2013-11-05
//     URL: http://forum.arduino.cc/index.php?topic=197360
//
// Released to the public domain
//

#include 
#include 

TwoWire *wi;

const char version[] = "0.1.7";


// INTERFACE COUNT (TESTED TEENSY 3.5 AND ARDUINO DUE ONLY)
int wirePortCount = 1;
int selectedWirePort = 0;


// scans devices from 50 to 800KHz I2C speeds.
// lower than 50 is not possible
// DS3231 RTC works on 800 KHz. TWBR = 2; (?)
const long allSpeed[] = {
  50, 100, 200, 300, 400, 500, 600, 700, 800
};
long speed[sizeof(allSpeed) / sizeof(allSpeed[0])];
int speeds;

int addressStart = 0;
int addressEnd = 127;


// DELAY BETWEEN TESTS
#define RESTORE_LATENCY  5    // for delay between tests of found devices.
bool delayFlag = false;


// MINIMIZE OUTPUT
bool printAll = true;
bool header = true;


// STATE MACHINE
enum states {
  STOP, ONCE, CONT, HELP
};
states state = STOP;


// TIMING
uint32_t startScan;
uint32_t stopScan;


void setup()
{
  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting...");
  Wire.begin();

#if defined WIRE_IMPLEMENT_WIRE1 || WIRE_INTERFACES_COUNT > 1
  Wire1.begin();
  wirePortCount++;
#endif
#if defined WIRE_IMPLEMENT_WIRE2 || WIRE_INTERFACES_COUNT > 2
  Wire2.begin();
  wirePortCount++;
#endif
#if defined WIRE_IMPLEMENT_WIRE3 || WIRE_INTERFACES_COUNT > 3
  Wire3.begin();
  wirePortCount++;
#endif

  wi = &Wire;

  setSpeed('0');
  displayHelp();
}


void loop()
{
  char command = getCommand();
  switch (command)
  {
    case '@':
      selectedWirePort = (selectedWirePort + 1) % wirePortCount;
      Serial.print(F("I2C PORT=Wire"));
      Serial.println(selectedWirePort);
      switch (selectedWirePort)
      {
        case 0:
          wi = &Wire;
          break;
        case 1:
#if defined WIRE_IMPLEMENT_WIRE1 || WIRE_INTERFACES_COUNT > 1
          wi = &Wire1;
#endif
          break;
        case 2:
#if defined WIRE_IMPLEMENT_WIRE2 || WIRE_INTERFACES_COUNT > 2
          wi = &Wire2;
#endif
          break;
        case 3:
#if defined WIRE_IMPLEMENT_WIRE3 || WIRE_INTERFACES_COUNT > 3
          wi = &Wire3;
#endif
          break;
      }
      break;

    case 's':
      state = ONCE;
      break;
    case 'c':
      state = CONT;
      break;
    case 'd':
      delayFlag = !delayFlag;
      Serial.print(F("") : F("0>"));
      break;

    case 'e':
      // eeprom test TODO
      break;

    case 'h':
      header = !header;
      Serial.print(F("") : F("no>"));
      break;
    case 'p':
      printAll = !printAll;
      Serial.print(F("") : F("found>"));
      break;

    case '0':
    case '1':
    case '2':
    case '4':
    case '8':
      setSpeed(command);
      break;

    case 'a':
      setAddress();
      break;

    case 'q':
    case '?':
      state = HELP;
      break;
    default:
      break;
  }

  switch (state)
  {
    case ONCE:
      I2Cscan();
      state = HELP;
      break;
    case CONT:
      I2Cscan();
      delay(1000);
      break;
    case HELP:
      displayHelp();
      state = STOP;
      break;
    case STOP:
      break;
    default: // ignore all non commands
      break;
  }
}


void setAddress()
{
  if (addressStart == 0)
  {
    addressStart = 8;
    addressEnd = 120;
  }
  else
  {
    addressStart = 0;
    addressEnd = 127;
  }
  Serial.print(F(""));

}

void setSpeed(char sp)
{
  switch (sp)
  {
    case '1':
      speed[0] = 100;
      speeds = 1;
      break;
    case '2':
      speed[0] = 200;
      speeds = 1;
      break;
    case '4':
      speed[0] = 400;
      speeds = 1;
      break;
    case '8':
      speed[0] = 800;
      speeds = 1;
      break;
    case '0':  // reset
      speeds = sizeof(allSpeed) / sizeof(allSpeed[0]);
      for (int i = 0; i < speeds; i++)
      {
        speed[i] = allSpeed[i];
      }
      break;
  }
}

char getCommand()
{
  char c = '\0';
  if (Serial.available())
  {
    c = Serial.read();
  }
  return c;
}

void displayHelp()
{
  Serial.print(F("\nArduino MultiSpeed I2C Scanner - "));
  Serial.println(version);
  Serial.println();
  Serial.print(F("I2C ports: "));
  Serial.println(wirePortCount);
  Serial.println(F("\t@ = toggle Wire - Wire1 - Wire2 [TEENSY 3.5 or Arduino Due]"));
  Serial.println(F("Scanmode:"));
  Serial.println(F("\ts = single scan"));
  Serial.println(F("\tc = continuous scan - 1 second delay"));
  Serial.println(F("\tq = quit continuous scan"));
  Serial.println(F("\td = toggle latency delay between successful tests. 0 - 5 ms"));
  Serial.println(F("Output:"));
  Serial.println(F("\tp = toggle printAll - printFound."));
  Serial.println(F("\th = toggle header - noHeader."));
  Serial.println(F("\ta = toggle address range, 0..127 - 8..120"));
  Serial.println(F("Speeds:"));
  Serial.println(F("\t0 = 50 - 800 Khz"));
  Serial.println(F("\t1 = 100 KHz only"));
  Serial.println(F("\t2 = 200 KHz only"));
  Serial.println(F("\t4 = 400 KHz only"));
  Serial.println(F("\t8 = 800 KHz only"));
  Serial.println(F("\n\t? = help - this page"));
  Serial.println();
}


void I2Cscan()
{
  startScan = millis();
  uint8_t count = 0;

  if (header)
  {
    Serial.print(F("TIME\tDEC\tHEX\t"));
    for (uint8_t s = 0; s < speeds; s++)
    {
      Serial.print(F("\t"));
      Serial.print(speed[s]);
    }
    Serial.println(F("\t[KHz]"));
    for (uint8_t s = 0; s < speeds + 5; s++)
    {
      Serial.print(F("--------"));
    }
    Serial.println();
  }

  // TEST
  // 0.1.04: tests only address range 8..120
  // --------------------------------------------
  // Address  R/W Bit Description
  // 0000 000   0 General call address
  // 0000 000   1 START byte
  // 0000 001   X CBUS address
  // 0000 010   X reserved - different bus format
  // 0000 011   X reserved - future purposes
  // 0000 1XX   X High Speed master code
  // 1111 1XX   X reserved - future purposes
  // 1111 0XX   X 10-bit slave addressing
  for (uint8_t address = addressStart; address <= addressEnd; address++)
  {
    bool printLine = printAll;
    bool found[speeds];
    bool fnd = false;

    for (uint8_t s = 0; s < speeds ; s++)
    {
#if ARDUINO >= 158
      wi->setClock(speed[s] * 1000);
#else
      TWBR = (F_CPU / (speed[s] * 1000) - 16) / 2;
#endif
      wi->beginTransmission (address);
      found[s] = (wi->endTransmission () == 0);
      fnd |= found[s];
      // give device 5 millis
      if (fnd && delayFlag) delay(RESTORE_LATENCY);
    }

    if (fnd) count++;
    printLine |= fnd;

    if (printLine)
    {
      Serial.print(millis());
      Serial.print(F("\t"));
      Serial.print(address, DEC);
      Serial.print(F("\t0x"));
      if (address < 0x10) Serial.print(0, HEX);
      Serial.print(address, HEX);
      Serial.print(F("\t"));

      for (uint8_t s = 0; s < speeds ; s++)
      {
        Serial.print(F("\t"));
        Serial.print(found[s] ? F("V") : F("."));
      }
      Serial.println();
    }
  }

  stopScan = millis();
  if (header)
  {
    Serial.println();
    Serial.print(count);
    Serial.print(F(" devices found in "));
    Serial.print(stopScan - startScan);
    Serial.println(F(" milliseconds."));
  }
}