espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.75k stars 7.44k forks source link

Data order getting changed in I2C in ESP32 Arduino #10383

Closed UmerSoftwares closed 2 months ago

UmerSoftwares commented 2 months ago

Board

ESP32 Dev Module

Device Description

I am using 2 ESP32 Dev modules and a breadboard. The SDA (GPIO21) and SCL (GPIO22) of both ESP32s are connected together as well as pulled up to 3.3V using 4.7k resistors.

Hardware Configuration

Only the SDA (GPIO21) and SCL (GPIO22) of both ESP32s are connected together and pulled up to 3.3V using 4.7k resistors.

Version

v3.0.4

IDE Name

Arduino IDE

Operating System

Windows 10

Flash frequency

80MHz

PSRAM enabled

no

Upload speed

921600

Description

I programmed an ESP32 as an I2C slave. I was using arduino IDE to program the ESP32 and the version installed in the boards manager is 3.0.4. When I tested it with a master, the data order was incorrect on the received data. To test it at a very basic level, I wrote a piece of code where whatever the master wrote to the slave, the slave would return the double of it on the next data request. The issue is that, the data is delayed by one read. To understand, see the the master and slave output:

Master Output

Sent: 1, Received: 10
Sent: 2, Received: 2
Sent: 3, Received: 4
Sent: 4, Received: 6
Sent: 5, Received: 8
Sent: 1, Received: 10
Sent: 2, Received: 2
Sent: 3, Received: 4
Sent: 4, Received: 6
Sent: 5, Received: 8

Slave Output

Received from master: 1, Prepared to send: 2
Received from master: 2, Prepared to send: 4
Received from master: 3, Prepared to send: 6
Received from master: 4, Prepared to send: 8
Received from master: 5, Prepared to send: 10
Received from master: 1, Prepared to send: 2
Received from master: 2, Prepared to send: 4
Received from master: 3, Prepared to send: 6
Received from master: 4, Prepared to send: 8
Received from master: 5, Prepared to send: 10

The slave sends te correct responses but the master receives it the next time.

After working on the issue, I can say that the issue is on the slave side. I uploaded the same slave code to an arduino mega and used it with ESP32 as the master and the response is correct without the data order getting changed.

Following is the master code

#include <Wire.h>

const int slaveAddress = 0x08; // I2C address of the slave

void setup() {
  Wire.begin(); // join I2C bus as master
  Serial.begin(115200);
}

void loop() {
  // Send numbers 1, 2, 3, 4, 5 in series
  for (int valueToSend = 1; valueToSend <= 5; valueToSend++) {
    sendAndReceive(valueToSend); // Send and receive for each number
    delay(1000);                 // 1-second delay between transmissions
  }
}

void sendAndReceive(int valueToSend) {
  // Send the value to the slave
  Wire.beginTransmission(slaveAddress);
  Wire.write(valueToSend); // Send the number to be doubled
  Wire.endTransmission();

  delay(5000); // Small delay to ensure the slave processes the request

  // Request 1 byte back from the slave
  Wire.requestFrom(slaveAddress, 1);

  if (Wire.available()) {
    int receivedValue = Wire.read(); // Read the response from the slave
    Serial.print("Sent: ");
    Serial.print(valueToSend);
    Serial.print(", Received: ");
    Serial.println(receivedValue); // Expecting the doubled value
  } else {
    Serial.println("No response from slave");
  }
}

The slave code is also attached

Sketch

#include <Wire.h>

int receivedValue = 0;
int responseValue = 0;

void setup() {
  Wire.begin(0x08); // join I2C bus with address 0x08
  Wire.onReceive(receiveEvent); // register event for receiving data from master
  Wire.onRequest(requestEvent); // register event for responding to master requests

  Serial.begin(115200);
}

void loop() {
  }

// This function is triggered when data is received from the master
void receiveEvent(int howMany) {
  if (Wire.available()) {
    receivedValue = Wire.read(); // Receive the number sent by the master
    responseValue = receivedValue * 2; // Double the value
    Serial.print("Received from master: ");
    Serial.print(receivedValue);
    Serial.print(", Prepared to send: ");
    Serial.println(responseValue);
  }
}

// This function is triggered when the master requests data
void requestEvent() {
  Wire.write(responseValue); // Send the doubled value back to the master
}

Debug Message

Not Applicable

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

me-no-dev commented 2 months ago

this is expected behavior on ESP32. You need to preload the data. All other ESP32-x chips work as you expect. ESP32 is the only one that needs pre-loading.

UmerSoftwares commented 1 month ago

I searched about preload but did not find anything. Is there a guide on how to preload the data to solve the issue?

me-no-dev commented 1 month ago

it's done here in the example: https://github.com/espressif/arduino-esp32/blob/master/libraries/Wire/examples/WireSlave/WireSlave.ino#L28-L32