This can be an important normal task, for instance when retrying an eeprom waiting for its last write burn cycle to complete before it will respond again.

Example code

void WaitForLastWriteToComplete ()
	uint16_t TriesCount = 5000;

	i2c_cmd_handle_t OurI2cCmdHandle = i2c_cmd_link_create();

	while (1)
		i2c_master_write_byte(OurI2cCmdHandle, EXAMPLE_I2C_ADDR | EXAMPLE_I2C_WRITE_BIT, EXAMPLE_I2C_ACK_CHECK_EN);
		//Send queued commands
		i2c_ret = i2c_master_cmd_begin(EXAMPLE_I2C_PORT_NUMBER, OurI2cCmdHandle, (1 / portTICK_PERIOD_MS));	//ticks_to_wait small value as we're not expecting the device to clock stretch 

		if (i2c_ret != ESP_FAIL)	//ESP_FAIL returned for Sending command error, slave hasn't ACK the transfer
		if (TriesCount == 0)

	} //while (1)


Things discovered when getting this to work on an ESP32 S3

Do not use i2c_cmd_link_delete() and i2c_cmd_link_create() between back-to-back retrying. In tests it causes a 1 second delay after the first NACK generating i2c_ret == 0x107 which is Operation timed out. Very odd as it should have just generated a new short attempt and i2c_ret == -1 ESP_FAIL like the first attempt. But it doesn’t, removing the use of i2c_cmd_link_delete() and i2c_cmd_link_create() between tries solved it.

i2c_master_write_byte() ack_en (Enable ACK signal) value must be 1, not 0. If you use 0 then the NACK is ignored and you get a ESP_OK back on the first try.

We benefit hugely from resources on the web so we decided we should try and give back some of our knowledge and resources to the community by opening up many of our company’s internal notes and libraries through mini sites like this. We hope you find the site helpful.
Please feel free to comment if you can add help to this page or point out issues and solutions you have found, but please note that we do not provide support on this site. If you need help with a problem please use one of the many online forums.


Your email address will not be published. Required fields are marked *