Hi, I'm having trouble using two ESP32's to request/send data via I2C. Whenever the master device sends a request it always seems to serial print the previous request from the slave device, as per:
12:36:57.853 -> Send Command: humidity
12:36:57.899 -> Received Data: Temp: 25.30
12:36:57.899 ->
12:36:58.870 -> Send Command: status
12:36:58.948 -> Received Data: Humidity: 60.70
12:36:58.948 ->
12:36:59.935 -> Send Command: temperature
12:36:59.978 -> Received Data: Status: OK
Code for master device:
#include <Wire.h>
#define SDA_PIN 21
#define SCL_PIN 22
#define I2C_DEV_ADDR 0x52
void sendCommandAndRequestData(const char* command) {
Serial.print("Send Command: ");
Serial.println(command);
// Send command to the slave
Wire.beginTransmission(I2C_DEV_ADDR);
Wire.write(command);
Wire.endTransmission();
delay(50); // Allow the slave time to process the command
// Request data from the slave
const int requestSize = 32; // Match the size of the expected data
char receivedData[requestSize + 1]; // Buffer to store received data
int index = 0;
Wire.requestFrom(I2C_DEV_ADDR, requestSize); // Request 32 bytes from the slave
while (Wire.available()) {
receivedData[index++] = Wire.read();
}
receivedData[index] = '\0'; // Null-terminate the string
// Print the received data
Serial.print("Received Data: ");
Serial.println(receivedData);
}
void setup() {
Serial.begin(115200);
Wire.begin(SDA_PIN, SCL_PIN);
}
void loop() {
// Test commands
sendCommandAndRequestData("temperature");
Serial.println("");
delay(1000);
sendCommandAndRequestData("humidity");
Serial.println("");
delay(1000);
sendCommandAndRequestData("status");
Serial.println("");
delay(1000);
}
Code for the slave device:
#include "Wire.h"
#define SDA_PIN 21
#define SCL_PIN 22
#define I2C_DEV_ADDR 0x52
String currentCommand = ""; // Stores the received command
void onRequest() {
char buffer[32] = {0}; // Initialize the buffer with null characters
if (currentCommand == "temperature") {
float temperature = 25.3; // Example temperature data
snprintf(buffer, sizeof(buffer), "Temp: %.2f", temperature);
} else if (currentCommand == "humidity") {
float humidity = 60.7; // Example humidity data
snprintf(buffer, sizeof(buffer), "Humidity: %.2f", humidity);
} else if (currentCommand == "status") {
snprintf(buffer, sizeof(buffer), "Status: OK");
} else {
snprintf(buffer, sizeof(buffer), "Unknown Command");
}
// Pad the remaining buffer with nulls to avoid sending garbage data
Wire.write((uint8_t*)buffer, 32); // Send exactly 32 bytes back to the master
}
void onReceive(int numBytes) {
char receivedCommand[20]; // Buffer to store incoming command
// Read the command sent by the master
Wire.readBytes(receivedCommand, numBytes);
receivedCommand[numBytes] = '\0'; // Null-terminate the string
// Store the command to use in the onRequest function
currentCommand = String(receivedCommand);
Serial.print("Command Received: ");
Serial.println(currentCommand);
}
void setup() {
Serial.begin(115200);
Wire.begin((uint8_t)I2C_DEV_ADDR, (int)SDA_PIN, (int)SCL_PIN, (uint32_t)100000); //device address, sda, scl, frequency
Wire.onReceive(onReceive);
Wire.onRequest(onRequest);
}
void loop() {
}
I've tried a number of things like increasing delays and changing the way requests/repsonses are handled but nothing seems to work. Is there something really obvioius I'm missing here?