-
Notifications
You must be signed in to change notification settings - Fork 162
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
Reboot loop when I2C Bus is not in a good state #50
Comments
Back Finally I've found a first issue The reboot is due to a division by 0 in => I suggest to replace the formula with that one return (((timeout_period_us * 1000) + (macro_period_ns / 2)) / (macro_period_ns ? macro_period_ns : 1)); In my (big) project, I do not want anything to reboot my ESP ! I'm still searching if this is possible to initialise the chip when it is in a bad state. Maybe it is impossible... |
The problem during the initialization is that the VL53 does not respond when asking for its identification if (readReg(IDENTIFICATION_MODEL_ID) != 0xEE) { return false; I've tried to add a pause during startup, or init the module with Adafruit : no success... The only way seems to power off / on My I2C Scanner did not find the chip. Still searching ... Even if I think that I won't find interresting things now |
I think I've found the problem which is an I2C bus problem (And have renamed the Tittle of this issue since the solution could be usefull to others). The solution to my problem to reset the I2C bus with that function. Imho, this function should be part of the Wire.h library, and shoud be call each time Wire.begin() is called. int I2C_ClearBus() {
#if defined(TWCR) && defined(TWEN)
TWCR &= ~(_BV(TWEN)); //Disable the Atmel 2-Wire interface so we can control the SDA and SCL pins directly
#endif
pinMode(SDA, INPUT_PULLUP); // Make SDA (data) and SCL (clock) pins Inputs with pullup.
pinMode(SCL, INPUT_PULLUP);
delay(2500); // Wait 2.5 secs. This is strictly only necessary on the first power
// up of the DS3231 module to allow it to initialize properly,
// but is also assists in reliable programming of FioV3 boards as it gives the
// IDE a chance to start uploaded the program
// before existing sketch confuses the IDE by sending Serial data.
boolean SCL_LOW = (digitalRead(SCL) == LOW); // Check is SCL is Low.
if (SCL_LOW) { //If it is held low Arduno cannot become the I2C master.
return 1; //I2C bus error. Could not clear SCL clock line held low
}
boolean SDA_LOW = (digitalRead(SDA) == LOW); // vi. Check SDA input.
int clockCount = 20; // > 2x9 clock
while (SDA_LOW && (clockCount > 0)) { // vii. If SDA is Low,
clockCount--;
// Note: I2C bus is open collector so do NOT drive SCL or SDA high.
pinMode(SCL, INPUT); // release SCL pullup so that when made output it will be LOW
pinMode(SCL, OUTPUT); // then clock SCL Low
delayMicroseconds(10); // for >5uS
pinMode(SCL, INPUT); // release SCL LOW
pinMode(SCL, INPUT_PULLUP); // turn on pullup resistors again
// do not force high as slave may be holding it low for clock stretching.
delayMicroseconds(10); // for >5uS
// The >5uS is so that even the slowest I2C devices are handled.
SCL_LOW = (digitalRead(SCL) == LOW); // Check if SCL is Low.
int counter = 20;
while (SCL_LOW && (counter > 0)) { // loop waiting for SCL to become High only wait 2sec.
counter--;
delay(100);
SCL_LOW = (digitalRead(SCL) == LOW);
}
if (SCL_LOW) { // still low after 2 sec error
return 2; // I2C bus error. Could not clear. SCL clock line held low by slave clock stretch for >2sec
}
SDA_LOW = (digitalRead(SDA) == LOW); // and check SDA input again and loop
}
if (SDA_LOW) { // still low
return 3; // I2C bus error. Could not clear. SDA data line held low
}
// else pull SDA line low for Start or Repeated Start
pinMode(SDA, INPUT); // remove pullup.
pinMode(SDA, OUTPUT); // and then make it LOW i.e. send an I2C Start or Repeated start control.
// When there is only one I2C master a Start or Repeat Start has the same function as a Stop and clears the bus.
/// A Repeat Start is a Start occurring after a Start with no intervening Stop.
delayMicroseconds(10); // wait >5uS
pinMode(SDA, INPUT); // remove output low
pinMode(SDA, INPUT_PULLUP); // and make SDA high i.e. send I2C STOP control.
delayMicroseconds(10); // x. wait >5uS
pinMode(SDA, INPUT); // and reset pins as tri-state inputs which is the default state on reset
pinMode(SCL, INPUT);
return 0; // all ok
}
``` |
Hi, hsaturn. Thanks for sharing what you found out about this issue. Have you seen this happen when using other I2C devices with the ESP8266 or does it seem relatively unique to the VL53L0X? Is there something specific that seems to trigger the bus problems (like loose connections or a particular startup sequence)? Kevin |
Hi Kevin Yet, I only have a bunch of VL530X on my I2C bus (8 of them actually). And for your 2nd question, yes, there is a specific thing that triggers the problem. 1 - Minimal sketch with your library and the fastest possible read of the VL53 in loop(). In that situation, the I2C bus is constantly used and there are more chance to cause the problem 2 - Simply press the Reset button until the init error occurs. I havn't saved the sketch but it looks like the example of your lib (continuous) |
Kevin I really suggest you to avoid the division by 0, this avoids reboots at very low cost. The next problem I'll have is to change the default address of the VL53 (which is 0x29). I need this because I have eight VL53 connected to my device. Adafruit lib propose this by using lox.begin(new_adress); I haven't search yet if your libray has this feature. |
I will try to see if I can reproduce the problem and if there is anything we can change to make it better. Checking for a divide by 0 is easy so I'll look at putting that in too; at that point the configuration will probably be messed up and the sensor might be left in a bad state, but I think it's still worth doing to avoid the ESP8266 rebooting. This library does let you change the address with the |
Yes, and this is expected (because init() already said that things went wrong and for some reasons, I've removed your infinite while loop of example Continuous.ino => division by 0 after).
Thanks ! I did not notice. Yet, I'm playing with your excellent VL53L1X library. Another great one. |
Kevin I forgot to say that the problem may occur ONLY with the ESP8266 ! |
tried the 'devision by zero' fix, but still stuck in the boot loop. |
Hello
I'm experiencing a boot loop in certain circumstances I'm trying to discover.
The ESP8266 continuously reboot very quickly.
As far as I know, the problem arise only when these conditions are met together
1 - The Chip (Vl53) is in a kind of bad state
2 - We attempt to change the timing budget (sensor.setMeasurementTimingBudget(20000); right after init.
My reduced sketch is
sensor.setTimeout(500);
if (!sensor.init()) { ... }
sensor.setMeasurementTimingBudget(20000);
The text was updated successfully, but these errors were encountered: