Open AndreCilia opened 10 months ago
van you please also provide a basic master side of code?
Hi, The master is sending out data as follows:
Wire.beginTransmission(devAddr/2); Wire.write(regAddr); byte error = Wire.endTransmission(false); delayMicroseconds(100); if(error == 0) { Wire.requestFrom(devAddr/2, len); delayMicroseconds(10); }
With the data in the buffer being read out to be forwarded over serial like so: `bufIdx = Wire.readBytes(buff, requestLen);
for(uint8_t idx = 0; idx < bufIdx; idx++)
{
numToChar(buff[idx], prnt);
Serial.print(prnt);
Serial.print(" ");
}
Wire.endTransmission();
bufIdx = 0;
requestLen = 0;
Serial.println();`
Please go through this issue. I think you have to send stop before request as of now,
Hi AAJAYS,
Thanks for your reply, however it does not solve anything because of two things:
1) The master still needs to delay requesting data after writing - by quite a lot. This is also mentioned in that issue. 2) SMBus requires a restart operation not a STOP and START
Therefore as things stand there is nothing else we can do?
Try to implement ESP-IDF I2C slave device. I think this might be helpful
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2c.h"
#define I2C_SLAVE_ADDR 0x50 // Replace with your desired slave address
static void i2c_slave_task(void *arg) {
i2c_config_t conf;
conf.mode = I2C_MODE_SLAVE;
conf.sda_io_num = I2C_SLAVE_SDA_IO; // Replace with the GPIO pin number for SDA
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = I2C_SLAVE_SCL_IO; // Replace with the GPIO pin number for SCL
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.slave.addr_10bit_en = 0;
conf.slave.slave_addr = I2C_SLAVE_ADDR;
i2c_param_config(I2C_NUM_0, &conf);
i2c_driver_install(I2C_NUM_0, conf.mode,
0, 0, 0);
uint8_t data_received;
while (1) {
i2c_slave_read_buffer(I2C_NUM_0, &data_received, 1, portMAX_DELAY);
printf("Received data: 0x%02x\n", data_received);
// Process the received data or perform any necessary actions
// Send response data back to the master
uint8_t response_data = 0xAA; // Change this to your response data
i2c_slave_write_buffer(I2C_NUM_0, &response_data, 1, portMAX_DELAY);
}
}
void app_main() {
xTaskCreate(i2c_slave_task, "i2c_slave_task", 2048, NULL, 10, NULL);
}
Hi AAJAYS,
I have copied and pasted your code and compile on PlatformIO using ESP-IDF 5.1.0.
First off I had to replace your line:
i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0);
with
i2c_driver_install(I2C_NUM_0, conf.mode, 128, 128, 0);
Otherwise the ESP32 is stuck rebooting because the buffer size is too small.
Following that correction I sent out a Write followed Read request with a RESTART condition in the middle.
However the same issue happens: When first sending a Write, the value written is correctly shown by the debugging text. However the data returned is garbage (in my case 0x17). When sending a second write, the value written is again correctly shown by the debugging text. However now the data returned is the correct value written in the task (0xAA). Regards, Andre Cilia
This is the error text I get when driver install is called with buffer sizes equal to zero:
.[0;31mE (10) i2c: i2c_driver_install(245): i2c buffer size too small for slave mode.[0m .[0;31mE (10) i2c: i2c_slave_read_buffer(1538): i2c driver install error.[0m Received data: 0x00 .[0;31mE (20) i2c: i2c_slave_write_buffer(1508): i2c driver install error.[0m
#include <Arduino.h>
#define I2C_DEV_MASTER
#include <Wire.h>
#ifdef I2C_DEV_MASTER
#else
#include "driver/i2c.h"
void i2c_slave_task(void *param) {
i2c_config_t conf;
conf.mode = I2C_MODE_SLAVE;
conf.sda_io_num = SDA; // Replace with the GPIO pin number for SDA
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = SCL; // Replace with the GPIO pin number for SCL
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.slave.addr_10bit_en = 0;
conf.slave.slave_addr = 0x55;
i2c_param_config(I2C_NUM_0, &conf);
i2c_driver_install(I2C_NUM_0, conf.mode,
128, 128, 0);
uint8_t counter = 0;
uint8_t recv_buff[128];
while (1) {
int len = i2c_slave_read_buffer(I2C_NUM_0, recv_buff, 1, portMAX_DELAY);
if (len) {
// Resp...
i2c_slave_write_buffer(I2C_NUM_0, &counter, 1, portMAX_DELAY);
counter++;
Serial.printf("Recv Len: %u\r\n Data:\r\n", len);
for (int i = 0; i < len; i++) {
Serial.printf("%02X ", recv_buff[i]);
if ((i + 1) % 8 == 0) Serial.println();
}
}
}
vTaskDelete(NULL);
}
#endif
void setup() {
Serial.begin(115200);
#ifdef I2C_DEV_MASTER
Wire.begin();
#else
// Wire.begin(0x55);
// Wire.onReceive(_onReceive);
// Wire.onRequest(_onRequest);
xTaskCreate(i2c_slave_task, "i2c_slave_task", 2048, NULL, 0, NULL);
#endif
}
void loop() {
#ifdef I2C_DEV_MASTER
Wire.beginTransmission(0x55);
Wire.write(10);
byte error = Wire.endTransmission(false);
if (error == 0) {
if (Wire.requestFrom((uint8_t)0x55, 1) > 0) {
Serial.printf("Recv %u\r\n", Wire.read());
}
}
Wire.endTransmission();
#else
#endif
delay(1000);
}```
Board
ESP32-S3
Device Description
I have a custom ESP32-S3 board based on the ESP32-S3-DevKitC-1 development board that I am programming using PlatformIO with the Arduino framework.
The Arduino Framework has version 2.0.11, the ESP-IDF has version 4.5.0.
The ESP32-S3 is connected to an SMBus Master which can be any SMBus compatible device but in testing stage I am using a custom programmed Arduino board.
Hardware Configuration
SDA - GPIO 1 SCL - GPIO 2
Application is running BLE, Wire1 as an I2C master, a couple of LED's driven by separate transistors
Version
v2.0.11
IDE Name
VS Code
Operating System
Windows 10
Flash frequency
40MHz
PSRAM enabled
no
Upload speed
115200
Description
I need an I2C slave function to act as an SMBus slave. Howevern when I am sending a Write followed by a RESTART condition and a Read request, the Request interrupt is triggered BEFORE the Receive interrupt, thus not giving me time to process which data is being requested and buffering it.
Following is the code setting up the I2C slave:
Wire.begin(0xb, SLAVE_SDA, SLAVE_SCL, 100000UL); Wire.onReceive(_onReceive); Wire.onRequest(_onRequest);
with the interrupts being handled as follows:
`void _onRequest() { Serial.println("Request Rx"); }
void _onReceive(int len) { Serial.print("Receive: "); Serial.print(len); Serial.println("bytes"); }`
Sketch
`Wire.begin(0xb, SLAVE_SDA, SLAVE_SCL, 100000UL); Wire.onReceive(_onReceive); Wire.onRequest(_onRequest);` with the interrupts being handled as follows: `void _onRequest() { Serial.println("Request Rx"); } void _onReceive(int len) { Serial.print("Receive: "); Serial.print(len); Serial.println("bytes"); }`
Debug Message
No issue here
Other Steps to Reproduce
No response
I have checked existing issues, online documentation and the Troubleshooting Guide
- [x] I confirm I have checked existing issues, online documentation and Troubleshooting guide.
This code is also valid. Because on master code Wire.endTransmission(false)
does not write data and add it to queue. Try ArduinoUno as master with same code. This might work as expected.
ArduinoUno= I2C master. ESP32 = I2C Slave.
Hi AAJAY,
Unfortunately I can only have access to the MASTER on the test bench - but on the field the master is completely beyond my control. Therefore the slave MUST work well without any intervention on the master.
On the other hand I do not understand what I need to do with the above code.
Thanks and regards, Andre Cilia
You can give try with this slave code.
Where recv_buff
is buffer to store received data, len
is received data len.
counter
is value you want to send onRequest().
#include <Arduino.h>
#include <Wire.h>
#include "driver/i2c.h"
void i2c_slave_task(void *param) {
i2c_config_t conf;
conf.mode = I2C_MODE_SLAVE;
conf.sda_io_num = SDA; // Replace with the GPIO pin number for SDA
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = SCL; // Replace with the GPIO pin number for SCL
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.slave.addr_10bit_en = 0;
conf.slave.slave_addr = 0x55;
i2c_param_config(I2C_NUM_0, &conf);
i2c_driver_install(I2C_NUM_0, conf.mode,
128, 128, 0);
uint8_t counter = 0;
uint8_t recv_buff[128];
while (1) {
int len = i2c_slave_read_buffer(I2C_NUM_0, recv_buff, 1, portMAX_DELAY);
if (len) {
// This is your onRecive();
// Load data you want to send onRequest()
i2c_slave_write_buffer(I2C_NUM_0, &counter, 1, portMAX_DELAY);
counter++;
Serial.printf("Recv Len: %u\r\n Data:\r\n", len);
for (int i = 0; i < len; i++) {
Serial.printf("%02X ", recv_buff[i]);
if ((i + 1) % 8 == 0) Serial.println();
}
}
}
vTaskDelete(NULL);
}
void setup() {
Serial.begin(115200);
xTaskCreate(i2c_slave_task, "i2c_slave_task", 2048, NULL, 0, NULL);
}
void loop() {
}```
@AndreCilia Were you able to get the I2C slave working?
Simple answer is no. I am still handling this with Espressif though, so there may be a way forward at some point
Board
ESP32-S3
Device Description
I have a custom ESP32-S3 board based on the ESP32-S3-DevKitC-1 development board that I am programming using PlatformIO with the Arduino framework.
The Arduino Framework has version 2.0.11, the ESP-IDF has version 4.5.0.
The ESP32-S3 is connected to an SMBus Master which can be any SMBus compatible device but in testing stage I am using a custom programmed Arduino board.
Hardware Configuration
SDA - GPIO 1 SCL - GPIO 2
Application is running BLE, Wire1 as an I2C master, a couple of LED's driven by separate transistors
Version
v2.0.11
IDE Name
VS Code
Operating System
Windows 10
Flash frequency
40MHz
PSRAM enabled
no
Upload speed
115200
Description
I need an I2C slave function to act as an SMBus slave. Howevern when I am sending a Write followed by a RESTART condition and a Read request, the Request interrupt is triggered BEFORE the Receive interrupt, thus not giving me time to process which data is being requested and buffering it.
Following is the code setting up the I2C slave:
Wire.begin(0xb, SLAVE_SDA, SLAVE_SCL, 100000UL); Wire.onReceive(_onReceive); Wire.onRequest(_onRequest);
with the interrupts being handled as follows:
`void _onRequest() { Serial.println("Request Rx"); }
void _onReceive(int len) { Serial.print("Receive: "); Serial.print(len); Serial.println("bytes"); }`
Sketch
Debug Message
Other Steps to Reproduce
No response
I have checked existing issues, online documentation and the Troubleshooting Guide