Pcf8574 sometimes dont get i2c data

I have a PCF8574 and I'm trying to control 8 LEDs that are connected to it via the ESP32's SDA and SCL pins.

The SDA and SCL wires are 80cm long and made from Cat5e (Ethernet cable).

The problem I'm encountering is that sometimes the LED control works, but at other times, it does not. For instance, when I send the command "00000000," the LEDs are supposed to be ON , but sometimes they remain OFF so I have to resend the command multiple times to get the desired result.

I'm looking for a way to diagnose and address this issue. Is there a method to check if the command has been accepted or determine why it's not being accepted consistently?

  unsigned long ms_LCD = 0;                     // millis();
String lcd="11111111";//all OFF
void setup(){
  Wire.begin();           //LCD I2C
  Wire.setClock(100000);  // Set I2C clock speed to 100 kHz

}

void loop(

 if (millis() - ms_LCD > 2000) {  //update lcd every 2 sec
      String lcd_tmp = lcd;
      if (throttle_out == 0) {
        lcd_tmp[7] = '1';  
        lcd_tmp[6] = '1';  
      } else if (throttle_out < 26) {
        lcd_tmp[7] = '0'; 
        lcd_tmp[6] = '1';  
      } else {
        lcd_tmp[7] = '1';  
        lcd_tmp[6] = '0'; 
      }

      if (lcd != lcd_tmp) {
        Serial.println(lcd_tmp);
        lcd = lcd_tmp;
        Wire.beginTransmission(0x20);                  // I2C address
        Wire.write(strtol(lcd_tmp.c_str(), NULL, 2));  // Write the updated LED state to the PCF8574 using c_str()
        Wire.endTransmission();
      }
      ms_LCD = millis();
    }

}

Try short cables made from ordinary connecting wire. Does the problem still occur?

Which conductors within the ethernet cable are you using?

Have you tried adding external pull-up resistors to SCA & SDL?

endTransmission() returns an error code which can be checked.

sometimes return 0 sometimes 2

10k

Try something a little lower like 4K7 or 3K3.

Reviewing your partial code, I can't see a problem, but it could be a heck of a lot more efficient and simpler! Looks like it was written by someone more used to Python or Visual BASIC.

EDIT: actually I can see a problem, but it's probably the usual result of posting only part of your code instead of complete code. The variable lcd is declared local to setup(), so would not be accessible from loop(). That would cause a compile error.

i fixed it ( i tried to post just code that has to do with i2c to make things simpler)

can u suggest something

unsigned long ms_LCD = 0;                     // millis();
byte lcd= 0b11111111;//all OFF

void setup(){
  Wire.begin();           //LCD I2C
  Wire.setClock(100000);  // Set I2C clock speed to 100 kHz

}

void loop(

 if (millis() - ms_LCD > 2000) {  //update lcd every 2 sec
      byte lcd_tmp = lcd;
      if (throttle_out == 0) {
        bitWrite(lcd_tmp, 7, 1);  
        bitWrite(lcd_tmp, 6, 1);  
      } else if (throttle_out < 26) {
        bitWrite(lcd_tmp, 7, 0);
        bitWrite(lcd_tmp, 6, 1);  
      } else {
        bitWrite(lcd_tmp, 7, 1);
        bitWrite(lcd_tmp, 6, 0);  
      }

      if (lcd != lcd_tmp) {
        Serial.println(lcd_tmp, BIN);
        lcd = lcd_tmp;
        Wire.beginTransmission(0x20);                  // I2C address
        Wire.write(lcd_tmp);  // Write the updated LED state to the PCF8574 using c_str()
        Wire.endTransmission();
      }
      ms_LCD = millis();
    }

}

Alternatively

unsigned long ms_LCD = 0;                     // millis();
byte lcd= 0b11111111;//all OFF

void setup(){
  Wire.begin();           //LCD I2C
  Wire.setClock(100000);  // Set I2C clock speed to 100 kHz

}

void loop(

 if (millis() - ms_LCD > 2000) {  //update lcd every 2 sec
      byte lcd_tmp = lcd & 0b00111111;
      if (throttle_out == 0) {
        lcd_tmp |= 0b11000000;  
      } else if (throttle_out < 26) {
        lcd_tmp |= 0b01000000;
      } else {
        lcd_tmp |= 0b10000000;
      }

      if (lcd != lcd_tmp) {
        Serial.println(lcd_tmp, BIN);
        lcd = lcd_tmp;
        Wire.beginTransmission(0x20);                  // I2C address
        Wire.write(lcd_tmp);  // Write the updated LED state to the PCF8574 using c_str()
        Wire.endTransmission();
      }
      ms_LCD = millis();
    }

}

Hello arpa123

Read and check the I²C specification to find an answer.

if i add 4.7ohm resistor i still see error sometimes.

if i add 1K ohm or 1.5K ohm resistor then all is ok .

but is it ok using 1.5K ohm resistor? i read that people use between 4.7k- 10k

Are the pullups, the PCF8574 and LEDs all running at 3v?
If not, are you using a level shifter on the I2C signals to convert between the
3v and the 5v i2c buses.
i.e. you should not hook the 3v processor i2c signals to a 5v I2C bus which is what you have if you run the PCF8574 and the LEDs at 5v.

Also for a bit of robustness, you could alter the code to retry the write operation if the i2c write fails.
Just keep in mind that it may never work in some situations.
i.e. don't write the code so it can get hung in loop doing continuous retries.

--- bill

That is telling me you have noise on those lines and or they are way to long. I2C was designed for IC to IC on the same board, not a network. If you want to use the lower value resistors that is OK but you need to check the data sheets for each device on the bus to see if they will drive that much current. If there are other pull up resistors on the bus they form a parallel network and need to also be taken into account also. Switch to something like CAN designed for talking to wires. CAN's bus impedance is about 60 ohms, not several K ohms.

i just send 4 wires from esp32 (3.3v gnd ,sda,scl) (80cm long ) to pcf 8574

and there added leds , anode of led is on 3.3v(with resistor) and cathode is on pcf8574 pins

80 cm is pretty long for I2C, but should not cause such issues.

Also you mention you use CAT5 cable. Do not try to put SDA and SCL on the same pair, you will get crosstalk. Ideally both SCL and SDA are each paired with a ground return. Use a separate pair for the 5V supply, and the remaining pair for an additional ground connection.

If for some reason you can use only two pairs (four wires) bundle SCL with GND and SDA with the 5V.

For pull-up resistor: the minimum value as per I2C specifications is 1k. If you're using a breakout board for the PCF8574 it likely has 10k pull-up resistors on board as well. Keep that in mind.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.