Skip to content

SDA / SCL read very unstable #659

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
euquiq opened this issue Sep 23, 2017 · 11 comments
Closed

SDA / SCL read very unstable #659

euquiq opened this issue Sep 23, 2017 · 11 comments

Comments

@euquiq
Copy link

euquiq commented Sep 23, 2017

Hi there !

On the esp8266 there was a known limitation about reading from Wire, which had to be capped to 32 bytes at a time.

On the esp32 this seems to be yet far worse, and even when I manage to read some values (from, say an eeprom) it would work for one or two hours, but then it would crash.

Example, this would work as is on an esp8266:

void readEEPROM() { for (int j = 0; j<256; j += 32) { Wire.beginTransmission(MY_EEPROM); Wire.write(j); byte rc = Wire.endTransmission(); Wire.requestFrom(MY_EEPROM, 32); for (int i = 0; i < 32; i++) { eepromData[j + i] = (uint8_t)Wire.read(); } } }

But in order for it to work into my ESP32, I need to tone it down and read it even in lesser chunks at a time:

void readEEPROMesp32() { for (int j = 0; j<256; j += 8) { Wire.beginTransmission(MY_EEPROM); Wire.write(j); byte rc = Wire.endTransmission(); Wire.requestFrom(MY_EEPROM, 8); for (int i = 0; i < 8; i++) { eepromData[j + i] = (uint8_t)Wire.read(); } } }

And even with this last code, it would work fine for an hour or so and then go south.

I think this may be a severe problem, since the Wire interface is kind of a "must" for most projects.

Hopefully it is fixable (or there is a workaround you may point me to).

Regards,

Enrique

@euquiq
Copy link
Author

euquiq commented Sep 24, 2017

Update:

As soon as I created the issue above, I did yet another modification on my code, which now reads one byte at a time only:

void readEEPROM() { for (int j = 0; j<256; j += 1) { Wire.beginTransmission(MY_EEPROM); Wire.write(j); byte rc = Wire.endTransmission(); Wire.requestFrom(MLX90621_EEPROM, 1); eepromData[j] = (uint8_t)Wire.read(); } }

Under such speed /efficiency penalty, My code is working fine (no glitches after about 24 hours ).

Maybe this behavior has something to do with RTOS and the tasks / interrupts unsafe thingy ?

@euquiq
Copy link
Author

euquiq commented Sep 25, 2017

uhm ... reading went south after 26 / 28 hours, even reading byte per byte.

@me-no-dev
Copy link
Member

What exactly went south? maybe you can post a dump? decoded exception?

@deanm1278
Copy link

I have this same (or very similar) issue. Using this library:
adafruit/Adafruit_APDS9960#2 (comment)

and the gesture sensor example:
https://github.com/adafruit/Adafruit_APDS9960/blob/master/examples/gesture_sensor/gesture_sensor.ino

and the adafruit huzzah 32 https://www.adafruit.com/product/3405

I2C either freezes after a short while or will continue to clock SCL indefinitely.
This happens even if I slow SCL down to 10khz. The issue also happens (but seems to happen after a longer amount of time) if I drop down the number of bytes read at a time here:

uint8_t Adafruit_APDS9960::read(uint8_t reg, uint8_t *buf, uint8_t num)
{
	uint8_t value;
	uint8_t pos = 0;
	bool eof = false;
	
	//on arduino we need to read in 32 byte chunks
	while(pos < num && !eof){
		
               //CHANGE 32 TO LOWER NUMBER HERE, I2C WORKS SLIGHTLY LONGER
		uint8_t read_now = min(32, num - pos); 
		Wire.beginTransmission((uint8_t)_i2caddr);
		Wire.write((uint8_t)reg + pos);
		Wire.endTransmission();
		
		Wire.requestFrom((uint8_t)_i2caddr, read_now);
		
		for(int i=0; i<read_now; i++){
			if(!Wire.available()){
				eof = true;
				break;
			}
			buf[pos] = Wire.read();
			pos++;
		}
	}
	return pos;
}

The example works fine on arduino UNO and SAMD based arduino cores.

@euquiq
Copy link
Author

euquiq commented Sep 27, 2017

My problem occurs when interfacing with a Melexis MLX90621 thermal array sensor.

After some working time, temps returned by the sensor went berzerk. I reset the ESP32 and everything is OK again.

I am not that proficient debuging the problem, but I observed that, "when things go south", the Wire interface starts returning a value of 255 on every byte read from the sensor.

I have no idea why this happens.

I have no way of reproduce the problem, other than let the ESP32 read the Melexis MLX90621 sensor for some (mostly random) time.

Right now, I am taking a good look (and doing some tests) into this post:

esp8266/Arduino#1025

Which although is from ESP8266, it might be a "related" problem.

I will keep this thread up to date, if I find anything more conclusive.

Regards, Enrique

@stickbreaker
Copy link
Contributor

@euquiq , I have something similar happening. I have a MCP23008 scanning a 4x4 matrix. I have been noticing that sometimes after I download a program, I start receiving continuous key presses, my keypad library interprets it as a '1'. It could actually be a continuous 255 from the I2C subsystem.

I have been able to touch reset and the problem disappears.

I'm in the process of converting all my libraries to ESP32 and AVR compatibility.

My current hardware testbed is:
WeMos ESP32 Bluethooth+Battery,

  1. 3.3V I2C bus segment
    1. 3x 24LC64, 3x 24LC512,
  2. One 5V I2C bus segment
    1. DS1307 RTC (tinyRTC)
    2. 24LC32
    3. 2x MCP23008 I/O expanders
  3. connecting the 3.3V and 5V is a SparkFun level shifter using BSS138 fets

I'll try running this problem down. As you can see I use the I2C bus quite extensively.

Chuck.

@euquiq
Copy link
Author

euquiq commented Oct 26, 2017

Update: With latest repository updates my problems communicating with my i2c sensor (a thermal array from MELEXIS, the MLX90621) got worser and worser.

If I choose core debug: error when compiling my code, Now I get TONS of errors right from the start (copy / paste only one instance of each):

[E][esp32-hal-i2c.c:161] i2cWrite(): Busy Timeout! Addr: 60
and
[E][esp32-hal-i2c.c:313] i2cRead(): Timeout! Addr: 60, index 16

If expand the scope of the core debug into INFO, I get also tons of:

[W][esp32-hal-i2c.c:334] i2cRead(): Ack Error! Addr: 60

Since I know the values (value scope) to be read beforehand (I can catch weird temperatures being read as a result of i2c error), I did a quick dirty "error catching routine" after each i2c error, which resets the i2c interfase and retries the reading.

Even while reseting the i2c interfase several times per second, some temperature values get wrong (my routine only catches the REALLY WEIRD values).

I tried with five ESP32 boards. I got the same behaviour on all of them.

The same code and sensor, run on an ESP8266, works flawlessly.

This is really bad! Is there anything I can do to help from my side ?

Regards,

Enrique.

@dstoiko
Copy link
Contributor

dstoiko commented Nov 3, 2017

+1, started getting these weird errors when I updated to the latest master branch. Got a DS3231 RTC chip mounted as SMT component on a PCB with the ESP32 DevKit-C.

@stickbreaker
Copy link
Contributor

@euquiq , The I2C subsystem is timing dependent. If any of the core error messages are generated it causes a chain reaction of additional timeout/ack failures. Disable the core logging and test the return codes in your application. uint8_t err=Wire.endTransmission() uint8_t err=Wire.requestFrom(slaveId,count);

Chuck.

@stickbreaker
Copy link
Contributor

@dstoiko I have posted a fix for this issue, it needs thorough review and testing though. I would appreciate if you could test it on your hardware.
See message #839

Chuck.

@copercini
Copy link
Contributor

The I2C core was changed to @stickbreaker code officially after 13dcfe5 (thanks @stickbreaker), Let's close issues with old code and if have problems with the new code, open new issues =)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants