I2C issues with esp32 S3

Hello

I am currently working on a board that interfaces with a flight controller via I2C.
I created a pcb using an ESP32 S3, since i am familiar with the regular ESP32.
I noticed that there was this weird artifact appearing in the data that the flight controller was receiving.
I created a simplified version of the code and ran it, same issue.
Replaced the flight controller with an ESP32, same issue.
Replaced the ESP32 S3 with an ESP32 (two esp32 talking with eachother), the issue disappeared.

I noticed that if the slave sends more bytes than the master requests then the issue becomes worse.

The data that was to be sent from the slave is 0x01FF03FF. With 2 ESP32 this is what i get.
When i change the slave to an ESP32 S3 i get 0x61, 0xff, 0x03, 0xff on the master.

What i did notice is that the address is 0x30, the first byte on the data that the master gets is the address, bit shifted left once and the write bit is on. I Tried changing the address and the values on this byte change accordingly.

If i request 5 bytes then something even weirder happens, the response in the master shifts around.

It looks like it is loosing sync with the I2C frame.

The code is as follows:

Slave

#include "Wire.h" 						// i2c library

#define I2C_DEV_ADDR 0x30			// i2c adress, needs to be the same as in the lua script

int opcode = 0;							// received operation code
int i2cCommand = 0;						// received i2c command



typedef union Dados_I {  				// union for sending int via i2c
  int i;
  byte b[4];
};



Dados_I batata;

void setup() {
   Serial.begin(115200);				// start the serial port, used for debuging
  Serial.setDebugOutput(true);
  Wire1.onReceive(onReceive);		// if there is a i2c receive call then onReceive function is called
  Wire1.onRequest(onRequest);		// if there is a i2c request call then onRequest function is called
  //Wire1.begin(I2C_DEV_ADDR);
  Wire1.begin(I2C_DEV_ADDR,14,21,0 );// start the i2c channel with the I2C_DEV_ADDR adress
  Serial.println("setup");

  batata.i=0x01FF03FF;
}

void loop() {
  // put your main code here, to run repeatedly:

}





void onReceive(int len) { 		// on receive function, used to update local variables or activate local functions
Serial.println("receive");
Serial.println(len);
  i2cCommand = 0;				// resets the command
  opcode = Wire1.read();			// reads the operation code
  Serial.println(opcode);
  if (len == 2) {				// if there are 2 bytes
    i2cCommand = Wire1.read();	// the second byte is the command
    Serial.println(i2cCommand);
  }

  while (Wire1.available()) {	// clears the buffer if there are more requests
  Serial.println("lixo");
    int dadosExtra = Wire1.read();
  }
}

void onRequest() { 					// on request function, sends data via i2c depeding on the request
Serial.println("send");
 Wire1.write(batata.b, 4);
}

Master:

#include "Wire.h"

#define I2C_DEV_ADDR 0x30

uint32_t i = 0;


void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  Wire.begin();
}

void loop() {
  delay(100);


  uint8_t bytesReceived = Wire.requestFrom(I2C_DEV_ADDR, 4);
  Serial.printf("requestFrom: %u\n", bytesReceived);
  if ((bool)bytesReceived) {  //If received more than zero bytes
    uint8_t temp[bytesReceived];
    Wire.readBytes(temp, bytesReceived);
    log_print_buf(temp, bytesReceived);

    Serial.println(Wire.available());
  }
}

Does anyone know a solution for this problem?

Welcome to the forum.

It is not clear what you use as Master and what as Slave. Is the flight controller always a ESP32 ? Is the flight controller the Master ?

It could be a bug in the ESP32-S3 code.
I have not fully read this, but it seems serious: https://github.com/espressif/arduino-esp32/issues/8545

The ESP32 has a weird thing that newer variants do not have: https://docs.espressif.com/projects/arduino-esp32/en/latest/api/i2c.html#slavewrite
They say that the ESP32-S2 and ESP32-C3 are okay.

Tips:

  1. Please the defaults as much as possible. The default I2C bus with the default pins.
  2. Usually, the Wire.onReceive() and Wire.onRequest() are called after the Wire.begin().
  3. Do you use the Serial over USB for the ESP32-S3 ? Please don't call those Serial function from the onReceive and onRequest handlers.
  4. There is no need to clear a buffer in the onRequest handler. It should make no difference.

These tips might be useless, because I think it is a bug in the ESP32-S3 code.

Thank you.

The FC is the master, the ESP32S3 device is the slave.

The ESP32 is behaving normally. The ESP32S3 has a weird behavior with the same code.

1-AFAIK with the ESP32S3 you can put the I2C on any pins. I think there is no default pins. Also i am using the second I2C on the chip, the first one will be busy with something else.

2- Going to try that.

3- I am using Serial over USB, will also try that.

4- The clearing the buffer thing was a sanity check.

Tomorrow morning i'm going to take a good read on those links and try the tips you sent.
Thanks!

ESP32-S3 in Arduino mode and using Wire.begin() uses SDA = 8 and SCL = 9.

I changed the position on the onreceive and onrequest to after wire.begin. Same issue.

Removed the serial.print from the onreceive and onrequest. Same issue.

I tried reversing the boards. Now the ESP32S3 is the master and the ESP32 is the slave, the pins are the same. The issue goes away and works flawlessly. Even when i used wire1 on the S3.

The issue is isolated to the ESP32S3 working as a slave.

It looks like it is placing the slave address + read/write bit inside the first data frame.

If i request 2 bytes from the slave and the slave responds with 0x01FF03FF, i should get 0xFF and 0x03. What i'm getting is 0x61 and 0xFF.
0X61 is the device address, 0x30, shifted left once and the read/write bit is active.

Looks like there is a bug in the slave library for the esp32S3 or the ESP32S3 i have is faulty. Where should i report a bug?

I think that the link that I gave to the Issue on Github has this problem already in it.
If you think that you have additional information then you can add it. If you think this is yet another problem, then you can make a new Issue there.

What are you going to do with your project ?

I am doing a multi sensor hub that gets sensor data from several I2C sensors, processes them and sends them to the FC.

I asked a friend to lend me his nice osciloscope that has a signal analyzer but does not have the decoder package.

ESP32 as master and ESP32 S3 as slave

ESP32 S3 as master and ESP32 as slave

It looks like the slave does not take control of the clock signal. When the S3 is the slave.

EDIT:

I think it is an issue where the slave takes too long to take control of the clock pin and the master sends the request again.

EDIT2:

After reading a bit more it looks like it is only the master that controls the clock pin. This looks like an issue where the S3 does not send an ACK.

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