Reset I2C

gregstewart90
Posts: 59
Joined: Thu Jan 19, 2017 5:17 pm

Reset I2C

Postby gregstewart90 » Fri Jun 16, 2017 8:41 pm

I'm working on a project using MCP23017's which are port expanders using the i2c protocol. Occasionally, the chips start returning the wrong readings. I use relays in my design, which I imagine is causing the problem. I hooked it up to a login analizer and got the following result.
Screen Shot 2017-06-16 at 2.35.03 PM.png
Screen Shot 2017-06-16 at 2.35.03 PM.png (21.57 KiB) Viewed 19590 times
Right now, when I detect a problem, I reset the esp32 with esp_restart(). This always fixes the issue. Is there a way to correct this without a reset? Is there some way to reset the i2c bus?

Thanks!

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: Reset I2C

Postby kolban » Sat Jun 17, 2017 3:47 am

Howdy there @gregstewart90,
Without more context, the I2C trace doesn't look "wrong".
What you seem to be showing is a clock rate at the top signal and a data trace at the bottom signal. It also looks like you are using the Saleae software for examining the trace. It has an I2C mode where you can ask it to decode the protocol into I2C values. Are these parsing correctly. My arithmetic may be off, but I think I'm seeing 8 clock pulses before repetition.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

gregstewart90
Posts: 59
Joined: Thu Jan 19, 2017 5:17 pm

Re: Reset I2C

Postby gregstewart90 » Mon Jun 19, 2017 12:49 pm

That top is the clock. It is unable to parse the signal. The small segment I showed in the first picture repeats continuously. When it works normally, I only see it poll the mcp's a few times a second.

novalight
Posts: 40
Joined: Tue Apr 19, 2016 1:13 pm

Re: Reset I2C

Postby novalight » Mon Jun 19, 2017 12:54 pm

I think several people have noticed such problems but so far I could not find any solution rather than just reset the ESP32.

Also see:
- https://esp32.com/viewtopic.php?f=2&t=2 ... i2c#p10265
- https://github.com/espressif/esp-idf/issues/680
- https://github.com/espressif/arduino-esp32/issues/349

Maybe someone at espressif can shed some light on what is happening here.

User avatar
rudi ;-)
Posts: 1729
Joined: Fri Nov 13, 2015 3:25 pm

Re: Reset I2C

Postby rudi ;-) » Mon Jun 19, 2017 2:01 pm

gregstewart90 wrote:That top is the clock. It is unable to parse the signal. The small segment I showed in the first picture repeats continuously. When it works normally, I only see it poll the mcp's a few times a second.
ok
we see the clk
we see the data

we see no start condition
we see no stop condition

can you post please the CS ( /CE or RST ) pin too?

or how you interference you the device you want to poll?




thank you

best wishes
rudi ;-)
Last edited by rudi ;-) on Mon Jun 19, 2017 2:12 pm, edited 2 times in total.
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

gregstewart90
Posts: 59
Joined: Thu Jan 19, 2017 5:17 pm

Re: Reset I2C

Postby gregstewart90 » Mon Jun 19, 2017 2:05 pm

With this being i2c, I only have the SCL and SDA lines. What is the CS ( /CE or RST ) pin?

User avatar
rudi ;-)
Posts: 1729
Joined: Fri Nov 13, 2015 3:25 pm

Re: Reset I2C

Postby rudi ;-) » Mon Jun 19, 2017 2:16 pm

gregstewart90 wrote:With this being i2c, I only have the SCL and SDA lines. What is the CS ( /CE or RST ) pin?

if you speak from MCP
there is a CE to select the device

or my second question was:
or how you interference you the device you want to poll?
means then if you talk by address example.

how you set the 3 pins of MCP
A0
A1
A2

btw:
CE = Chip enable
CS = Chip select
RST = Reset
1.png
1.png (23.03 KiB) Viewed 19541 times
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

chegewara
Posts: 2378
Joined: Wed Jun 14, 2017 9:00 pm

Re: Reset I2C

Postby chegewara » Tue Oct 10, 2017 3:41 pm

Hi, im also trying to make mcp23017 to work and those are my findings. During reading there are clock speed drops about 33%. In my test case from 100kHz to about 65kHz and from 200kHz to about 129kHz.
i2c_normal.PNG
i2c_normal.PNG (9.69 KiB) Viewed 18864 times
i2c_issues.PNG
i2c_issues.PNG (9.75 KiB) Viewed 18864 times
I have to say i dont have any issues with mpu6050 on the same i2c line.

gregstewart90
Posts: 59
Joined: Thu Jan 19, 2017 5:17 pm

Re: Reset I2C

Postby gregstewart90 » Tue Oct 10, 2017 3:47 pm

I haven't checked for the slowing clock speed, but I got mine to work with the following code. It's nothing perfect, but I don't miss anything. Occasionally I still get stuck on the i2c line, but I just monitor that and reset as necessary.

Code: Select all


void initI2C() {
	i2c_config_t conf;
	conf.mode = I2C_MODE_MASTER;
	conf.sda_io_num = I2C_SDA;
	conf.scl_io_num = I2C_SCL;
	conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
	conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
	conf.master.clk_speed = 100000;
	ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_1, &conf));
	ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_1, I2C_MODE_MASTER, 0, 0, 0));
}

/**
 * @brief Reads a register of a specified MCP32017
 */
void mcp23017_local_read(uint8_t MCP23017_ADDRESS, uint8_t* data_h){

	i2c_cmd_handler = i2c_cmd_link_create();
	i2c_master_start(i2c_cmd_handler);
	i2c_master_write_byte(i2c_cmd_handler, MCP23017_ADDRESS << 1 | READ_BIT, ACK_CHECK_EN);
	i2c_master_read_byte(i2c_cmd_handler, data_h, NACK_VAL);
	i2c_master_stop(i2c_cmd_handler);
	int ret = i2c_master_cmd_begin(I2C_NUM_1, i2c_cmd_handler, 100 / portTICK_RATE_MS);
//	printf("ret:%d-%d\n", ret, ESP_ERR_TIMEOUT);
	i2c_cmd_link_delete(i2c_cmd_handler);
	if (ret != 0) {
		send_dump_write();
		printf("ERROR\n");
	}
}

/**
 * @brief Write a value to a register of a specified MCP32017
 */
void mcp23017_local_write(uint8_t MCP23017_ADDRESS, uint8_t command){

	vTaskDelay(30 / portTICK_RATE_MS);
	i2c_cmd_handler = i2c_cmd_link_create();
	i2c_master_start(i2c_cmd_handler);
	i2c_master_write_byte(i2c_cmd_handler, MCP23017_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
	i2c_master_write_byte(i2c_cmd_handler, command, ACK_CHECK_EN);// Access IODIRB
	i2c_master_stop(i2c_cmd_handler);
	int ret = i2c_master_cmd_begin(I2C_NUM_1, i2c_cmd_handler, 100 / portTICK_RATE_MS);
	i2c_cmd_link_delete(i2c_cmd_handler);
	if (ret == ESP_FAIL) {
		printf("ERROR\n");
	}
}

/**
 * @brief Writes two values to a register of a specified MCP32017
 */
void mcp23017_duel_write(uint8_t MCP23017_ADDRESS, uint8_t command, uint8_t command2){

	i2c_cmd_handler = i2c_cmd_link_create();
	i2c_master_start(i2c_cmd_handler);
	i2c_master_write_byte(i2c_cmd_handler, MCP23017_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
	i2c_master_write_byte(i2c_cmd_handler, command, ACK_CHECK_EN);// Access IODIRB
	i2c_master_write_byte(i2c_cmd_handler, command2, ACK_CHECK_EN);// Write Register
	i2c_master_stop(i2c_cmd_handler);
	int ret = i2c_master_cmd_begin(I2C_NUM_1, i2c_cmd_handler, 100 / portTICK_RATE_MS);

	i2c_cmd_link_delete(i2c_cmd_handler);
	if (ret == ESP_FAIL) {
		printf("ERROR\n");
	}
}

/**
 * @brief Reads the value of the register of the specified MCP23017
 */
uint8_t mcp23017_read(uint8_t MCP23017_ADDRESS, uint8_t command){
	uint8_t data_h;
	mcp23017_local_write(MCP23017_ADDRESS, command);
	vTaskDelay(30 / portTICK_RATE_MS);
	mcp23017_local_read(MCP23017_ADDRESS, &data_h);
	vTaskDelay(30 / portTICK_RATE_MS);
	return data_h;
}

Who is online

Users browsing this forum: cdollar and 97 guests