I2C Issue with MPU6050 – ACK received, but WHO_AM_I always returns 0x00

I'm using an ESP32 S3 with the MPU6050 connected via I2C using manual bit-banging (not using the Wire library).

I successfully get ACKs from both the device address (0x68) and the WHO_AM_I register (0x75), but the returned value is always 0x00.

Could this be due to missing pull-up resistors on SDA/SCL?
Has anyone encountered a similar issue?

#define SDA                     (42)
#define SCL                     (41)
#define MPU6050_BASE_ADD        (0X68)
#define WHO_AM_I_REG            (0x75)
#define WRITE                   (0)
#define READ                    (1)
#define MPU5060_WRITE(address)  ((address << 1) | WRITE)
#define MPU5060_READ(address)   ((address << 1) | READ)        

void i2c_delay() {
  delayMicroseconds(20); 
}

void i2c_init()
{
  pinMode(SDA, OUTPUT);
  pinMode(SCL, OUTPUT);
  digitalWrite(SDA, HIGH);
  digitalWrite(SCL, HIGH);
  i2c_delay();
}

void i2c_start()
{
  pinMode(SDA, INPUT);

  digitalWrite(SCL, HIGH);   
  i2c_delay();
  pinMode(SDA, OUTPUT);

  digitalWrite(SDA, LOW);
  i2c_delay();

  digitalWrite(SCL, LOW);
  i2c_delay();
}

void i2c_write_bit(bool bit)
{
  digitalWrite(SCL, LOW);
  i2c_delay(); // 1

  digitalWrite(SDA, bit);
  i2c_delay();

  digitalWrite(SCL, HIGH); // slave read
  i2c_delay(); // 5

  digitalWrite(SCL, LOW);
  i2c_delay(); // 2
}

bool i2c_read_ack()
{
  pinMode(SDA, INPUT);
  digitalWrite(SCL, HIGH);
  i2c_delay(); // 5

  bool ack = (digitalRead(SDA) == LOW);

  digitalWrite(SCL, LOW);
  pinMode(SDA, OUTPUT);

  return ack;
}

bool i2c_write_byte(uint8_t byte)
{
  pinMode(SDA, OUTPUT);
  i2c_delay();

  uint8_t m = 1 << 7;

  while(m)
  {
    i2c_write_bit(byte & m);
    m >>= 1;
  }

  pinMode(SDA, INPUT);

  return i2c_read_ack();
}

uint8_t i2c_read_byte()
{
  uint8_t value = 0;
  int i = 0;

  pinMode(SDA, INPUT);

  for (i = 0; i < 8; ++i)
  {
    digitalWrite(SCL, LOW);
    i2c_delay();

    digitalWrite(SCL, HIGH);
    i2c_delay();

    value <<= 1;
    if (digitalRead(SDA))
    {
      value |= 1;
    }
  }

  // end transmition and sending NACK
  digitalWrite(SCL, LOW);
  pinMode(SDA, OUTPUT);
  digitalWrite(SDA, HIGH); // NACK
  i2c_delay();

  digitalWrite(SCL, HIGH);
  i2c_delay();

  digitalWrite(SCL, LOW);
  i2c_delay();

  digitalWrite(SDA, HIGH); 
  pinMode(SDA, INPUT);

  return value;
}


void i2c_stop()
{
  pinMode(SDA, OUTPUT);
  digitalWrite(SDA, LOW);
  digitalWrite(SCL, HIGH);
  i2c_delay();

  pinMode(SDA, INPUT);
  i2c_delay();
}



void setup()
{
  Serial.begin(115200);
  delay(1000);
  Serial.println("Hello from LOLIN S3!");

  i2c_init();
}


void loop()
{
  delay(1000);  

  i2c_start();

  bool ack = i2c_write_byte(MPU5060_WRITE(MPU6050_BASE_ADD));
  Serial.printf("ACK1=%d  (ADD)\n", ack);
  if(ack != true)
  {
    Serial.println("no ack arrived. ERR 1.");
  }

  ack = i2c_write_byte(WHO_AM_I_REG);
  Serial.printf("ACK2=%d  (WHO_AM_I)\n", ack);
  if(ack != true)
  {
    Serial.println("no ack arrived. ERR 2.");
  }

  i2c_start();
  ack = i2c_write_byte(MPU5060_READ(MPU6050_BASE_ADD));
  Serial.printf("ACK3=%d  (READ)\n", ack);
  if (ack != true)
  {
    Serial.println("no ack arrived. ERR 3.");
  }

  uint8_t value = i2c_read_byte();

  i2c_stop();


  Serial.printf("value: 0x%02X\n", value);

  Serial.println("delay");
  delay(1000);  
}

The output is:

ACK1=1  (ADD)
ACK2=1  (WHO_AM_I)
ACK3=1  (READ)
value: 0x00
delay

I moved your topic to an appropriate forum category @matanspada.

In the future, when creating a topic please take some time to pick the forum category that best suits the subject of your topic. There is an "About the _____ category" topic at the top of each category that explains its purpose.

This is an important part of responsible forum usage, as explained in the "How to get the best out of this forum" guide. The guide contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

Manufacture of the MPU6050 was discontinued years ago, and you probably have a reject, fake or counterfeit chip.

Modern replacements such as the ISM330x significantly outperform it.

Of course.