Open dpnebert opened 2 months ago
A new i2c driver is now available in ESP-IDF V5.2. A new i2c driver is now simpler than the legacy i2c driver.
I hope this is helpful to read a value from the device.
https://github.com/espressif/esp-idf/tree/master/examples/peripherals/i2c/i2c_tools
I have this issue to. I need the ability to create an i2c command with a repeated start command:
-> start, i2c address + write bit, 2 byte data
-> start, i2c address + write bit, 2 byte data
-> start, i2c address + read bit, 9 byte data
-> stop
With the new API function i2c_master_transmit_receive
i can't insert the repeated start operation into that transaction.
I would love to move to the new driver because of the nice way to configure the master and devices, but this is hindering me for now.
Any plans to reintroduce that style of creating i2c transactions?
An hour after you posted, I started typing up a response, but then realized I didn't know what you were truly going for.
Actually just did it again. I found a good issue for illustration: https://github.com/espressif/esp-idf/issues/13952
I believe you'll have to split up this to three calls:
uint8_t data1[3] = {0x01, 0x10, 0x20};
i2c_master_transmit(handle, data1, 3, -1); // this will write 0x10 to register address 0x01, and 0x20 to register address 0x02
uint8_t data2[3] = {0x03, 0x10, 0x20};
i2c_master_transmit(handle, data1, 3, -1); // this will write 0x10 to register address 0x03, and 0x20 to register address 0x04
uint8_t data3[1] = {0x04};
uint8_t data4[9] = {0};
i2c_master_transmit_receive(handle, data3, 1, data4, 9, -1); // this will write 0x04 to set the register address to be read from. Then will perform 9 reads.
I believe this to be correct. If anyone could correct me, I'd appreciate helping me get better at the "new" way of doing ESP32s
This sadly won't work in my case since a i2c_master_transmit
puts a stop command at the end. Your suggestion would end up with this i2c activity on the bus:
# first i2c_master_transmit
<start>, <dev-addr> | WRITE_BIT, 0x01, 0x10, 0x20, <stop>
# second i2c_master_transmit
<start>, <dev-addr> | WRITE_BIT, 0x03, 0x10, 0x20, <stop>
# i2c_master_transmit_receive
<start>, <dev-addr> | WRITE_BIT, 0x04, <start>, <dev-addr> | READ_BIT, <data[0]>, ... , <data[8]>, <stop>
Unfortunatly the sensor i am working with is very strict about it's commands.
Maybe edit the IDF source? You could duplicate the transmit_receive method and rename it to suit your needs.
/components/esp_driver_i2c/i2c_master.c
It seems like if you can daisy chain the commands (like the old command link).
i2c_operation_t i2c_ops[] = {
{.hw_cmd = I2C_TRANS_START_COMMAND},
{.hw_cmd = I2C_TRANS_WRITE_COMMAND(i2c_dev->ack_check_disable ? false : true), .data = (uint8_t *)write_buffer, .total_bytes = write_size},
{.hw_cmd = I2C_TRANS_START_COMMAND},
{.hw_cmd = I2C_TRANS_READ_COMMAND(ACK_VAL), .data = read_buffer, .total_bytes = read_size - 1},
{.hw_cmd = I2C_TRANS_READ_COMMAND(NACK_VAL), .data = (read_buffer + read_size - 1), .total_bytes = 1},
{.hw_cmd = I2C_TRANS_STOP_COMMAND},
};
Then you get to perform all your transactions before the last element to stop.
I thought about that as well, but i2c_master_transmit
internally uses s_i2c_synchronous_transaction
or s_i2c_synchronous_transaction
respectively which are private functions I can't access easily.
I would much rather have an API that allows me to create such specific i2c bus transactions, much like the old API. Don't get me wrong, the new API is nice, but the advanced use case is just missing for my requirements. The i2c_operation_t just looks like what I want but I can't access the needed functions for that :(
Answers checklist.
General issue report
I'm using an ESP32-S3 with ESP-IDF v.5.2.1. In the API reference for i2c (https://docs.espressif.com/projects/esp-idf/en/v5.2.2/esp32s3/api-reference/peripherals/i2c.html), it states, "In order to organize the process, the driver uses a command link, that should be populated with a sequence of commands and then passed to I2C controller for execution." But it see in, "[Migration Guides] » [Migration from 5.1 to 5.2] » Peripherals" (https://docs.espressif.com/projects/esp-idf/en/v5.2/esp32/migration-guides/release-5.x/5.2/peripherals.html), it states, "i2c_cmd_link_xxx functions have been removed, user doesn't need to use link to link commands on its own."
I've used 'i2c_master_transmit_receive' to read a value from the device, but I'm struggling with how to do a 'write-write' using the write_buffer and an array.
Could more information about what strategy replaced the command link would be great! Thanks!