read from i2c failed 80 percent chance, after couple reboot it works

trustmiao
Posts: 42
Joined: Mon Aug 06, 2018 5:16 am

read from i2c failed 80 percent chance, after couple reboot it works

Postby trustmiao » Fri Aug 24, 2018 10:36 am

I am trying to connect esp32 to a BNO080 through i2c. The code and bno080 have been tested successfully with Arduino, and there is something weird happening when move to esp32.

The bno080 is connected to 21 22 with 10k pullup from 3.3v. and I am sure the code is fine. but, only one in five times I reset the esp32, it starts to get value from i2c. once it got value, it continues to give value as expected, however, if it doesn't give the value in the first three to five attempt, it will never work, so I will have to reset, until it finally works.

I am using sparkfun_bno080 library, which is tested by many user. So I suspect is there something about i2c in esp32 that i am not aware of. If you have similar experience, please don't hesitate to leave a message, very appreciated. here is the code, I have to write a soft reset loop to get imu working, which is not ideal.

Code: Select all

/*
  Using the BNO080 IMU
  By: Nathan Seidle
  SparkFun Electronics
  Date: December 21st, 2017
  License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

  Feel like supporting our work? Buy a board from SparkFun!
  https://www.sparkfun.com/products/14586

  This example shows how to output the i/j/k/real parts of the rotation vector.
  https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation

  It takes about 1ms at 400kHz I2C to read a record from the sensor, but we are polling the sensor continually
  between updates from the sensor. Use the interrupt pin on the BNO080 breakout to avoid polling.

  Hardware Connections:
  Attach the Qwiic Shield to your Arduino/Photon/ESP32 or other
  Plug the sensor onto the shield
  Serial.print it out at 9600 baud to serial monitor.
*/

#include <Wire.h>

#include "SparkFun_BNO080_Arduino_Library.h"
BNO080 myIMU;
void(* resetFunc)(void)=0;
void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("BNO080 Read Example");

  Wire.begin();
  Wire.setClock(400000); //Increase I2C data rate to 400kHz

  myIMU.begin();

  myIMU.enableRotationVector(10); //Send data update every 50ms
 
//myIMU.enableDebugging();
  
  float fquate=0;
  int count=0;
  while(fquate==0){
    count++;
    Serial.print("trying:");
    Serial.println(count);  
    if(count>5){
      count=0;
      resetFunc();
    }
    
    if (myIMU.dataAvailable() == true){ 
      fquate=myIMU.getQuatI();
      Serial.println(fquate);}
    delay(100);
   
    
  }
  Serial.println(F("Rotation vector enabled"));
  Serial.println(F("Output in form i, j, k, real, accuracy"));
}

void loop()
{
  //Look for reports from the IMU
  
  if (myIMU.dataAvailable() == true)
  {
    float quatI = myIMU.getQuatI();
    float quatJ = myIMU.getQuatJ();
    float quatK = myIMU.getQuatK();
    float quatReal = myIMU.getQuatReal();
    float quatRadianAccuracy = myIMU.getQuatRadianAccuracy();

    Serial.print(quatI, 2);
    Serial.print(F(","));
    Serial.print(quatJ, 2);
    Serial.print(F(","));
    Serial.print(quatK, 2);
    Serial.print(F(","));
    Serial.print(quatReal, 2);
    Serial.print(F(","));
    Serial.print(quatRadianAccuracy, 2);
    Serial.print(F(","));

    Serial.println();
  }
  
}
here is serial print , you can see it always works after couple reboot

Code: Select all

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:952
load:0x40078000,len:6084
load:0x40080000,len:7936
entry 0x40080310

BNO080 Read Example
trying:1
trying:2
trying:3
trying:4
0.00
trying:5
trying:6
Guru Meditation Error: Core  1 panic'ed (InstrFetchProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x00000000  PS      : 0x00060530  A0      : 0x800e6d6e  A1      : 0x3ffb1f70  
A2      : 0x3ffc286c  A3      : 0x3ffc2448  A4      : 0x00000000  A5      : 0x00000000  
A6      : 0x00000000  A7      : 0x00000000  A8      : 0x800d0be0  A9      : 0x3ffb1f50  
A10     : 0x00000003  A11     : 0x00000001  A12     : 0x0000000a  A13     : 0x00000000  
A14     : 0x00000002  A15     : 0x00000000  SAR     : 0x00000015  EXCCAUSE: 0x00000014  
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  

Backtrace: 0x00000000:0x3ffb1f70 0x400e6d6b:0x3ffb1fa0

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:952
load:0x40078000,len:6084
load:0x40080000,len:7936
entry 0x40080310

BNO080 Read Example
trying:1
0.00
trying:2
0.00
trying:3
0.24
Rotation vector enabled
Output in form i, j, k, real, accuracy
0.24,-0.78,-0.54,0.20,0.79,
0.24,-0.78,-0.54,0.20,0.79,
0.24,-0.78,-0.54,0.20,0.79,
0.24,-0.78,-0.54,0.20,0.79,
0.24,-0.78,-0.54,0.20,0.79,
0.24,-0.78,-0.54,0.20,0.79,
0.24,-0.78,-0.54,0.20,0.79,
0.24,-0.78,-0.54,0.20,0.79,

User avatar
fly135
Posts: 606
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: read from i2c failed 80 percent chance, after couple reboot it works

Postby fly135 » Fri Aug 24, 2018 4:24 pm

trustmiao wrote:So I suspect is there something about i2c in esp32 that i am not aware of.
I suspect it's something to do with the Arduino SDK, because I use I2C with the IDF and don't have this problem. But I keep seeing the issue being raised with people who use the Arduino.

John A

madmax__
Posts: 2
Joined: Wed Feb 13, 2019 3:51 pm

Re: read from i2c failed 80 percent chance, after couple reboot it works

Postby madmax__ » Thu Feb 14, 2019 5:14 am

Hi,

I am trying to add the BNO080 to my application, but having some issues while trying to get the data using esp-idf.
i havetried the sparkfun arduino library which runs smoothly.

while using esp-idf, some of the read/write throws erro 263 04 -1. i have looked at logic trace and many times the read write is happening but it gives xyz values as zero always.

can you please share the snippet for basic read write for bno080, if you have worked with it previously.

Best regards

madmax__
Posts: 2
Joined: Wed Feb 13, 2019 3:51 pm

Re: read from i2c failed 80 percent chance, after couple reboot it works

Postby madmax__ » Thu Feb 14, 2019 10:39 am

FYI,

its working now, bno requires i2c clock stretching and the default value was hard coded in the i2c driver. after increasing the value, it started working.

idahowalker
Posts: 166
Joined: Wed Aug 01, 2018 12:06 pm

Re: read from i2c failed 80 percent chance, after couple reboot it works

Postby idahowalker » Thu Feb 14, 2019 10:54 am

The code I use to read the BMP085 with a ESP32

Code: Select all

#include <Wire.h>
//*************************************************
// scl pin 5, sda pin 4, vcc 3.3
// temperature, pressure, altitude, sealevelpressure
#define BMP085_ADDRESS 0x77  // I2C address of BMP085
#define BMP_Interval 65503
const unsigned char OSS = 0;  // Oversampling Setting
// Calibration values
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
// b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
// so ...Temperature(...) must be called before ...Pressure(...).
long b5;
//*********************************************
const String sSeperator = " ";
//*********************************************

void setup()
{
////
  Wire.begin();
  bmp085Calibration();
  ////
}
////
//******************************************
//      bmp085 functions
//******************************************
// Calculate pressure given up
// calibration values must be known
// b5 is also required so bmp085GetTemperature(...) must be called first.
// Value returned will be pressure in units of Pa.
long bmp085GetPressure(unsigned long up)
{
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;

  b6 = b5 - 4000;
  // Calculate B3
  x1 = (b2 * (b6 * b6) >> 12) >> 11;
  x2 = (ac2 * b6) >> 11;
  x3 = x1 + x2;
  b3 = (((((long)ac1) * 4 + x3) << OSS) + 2) >> 2;

  // Calculate B4
  x1 = (ac3 * b6) >> 13;
  x2 = (b1 * ((b6 * b6) >> 12)) >> 16;
  x3 = ((x1 + x2) + 2) >> 2;
  b4 = (ac4 * (unsigned long)(x3 + 32768)) >> 15;

  b7 = ((unsigned long)(up - b3) * (50000 >> OSS));
  if (b7 < 0x80000000)
    p = (b7 << 1) / b4;
  else
    p = (b7 / b4) << 1;

  x1 = (p >> 8) * (p >> 8);
  x1 = (x1 * 3038) >> 16;
  x2 = (-7357 * p) >> 16;
  p += (x1 + x2 + 3791) >> 4;

  return p;
}
// Calculate temperature given ut.
// Value returned will be in units of 0.1 deg C
short bmp085GetTemperature(unsigned int ut)
{
  long x1, x2;

  x1 = (((long)ut - (long)ac6) * (long)ac5) >> 15;
  x2 = ((long)mc << 11) / (x1 + md);
  b5 = x1 + x2;

  return ((b5 + 8) >> 4);
}
// Read the uncompensated pressure value
unsigned long bmp085ReadUP()
{
  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;

  // Write 0x34+(OSS<<6) into register 0xF4
  // Request a pressure reading w/ oversampling setting
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x4 + (OSS << 6));
  Wire.endTransmission();

  // Wait for conversion, delay time dependent on OSS
  // delay(2 + (3 << OSS));
  vTaskDelay( pdMS_TO_TICKS( 2 + (3 << OSS) ) );
  // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF6);
  Wire.endTransmission();
  Wire.requestFrom(BMP085_ADDRESS, 3);

  // Wait for data to become available
  while (Wire.available() < 3)
    ;
  msb = Wire.read();
  lsb = Wire.read();
  xlsb = Wire.read();
  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8 - OSS);

  return up;
}
// Read the uncompensated temperature value
unsigned int bmp085ReadUT()
{
  unsigned int ut;
  // Write 0x2E into Register 0xF4
  // This requests a temperature reading
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();
  // Wait at least 4.5ms
   vTaskDelay( pdMS_TO_TICKS( 5 ) );
  // delay(5);
  // Read two bytes from registers 0xF6 and 0xF7
  ut = bmp085ReadInt(0xF6);
  return ut;
}
// Stores all of the bmp085's calibration values into global variables
// Calibration values are required to calculate temp and pressure
// This function should be called at the beginning of the program
void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}
// Read 2 bytes from the BMP085
// First byte will be from 'address'
// Second byte will be from 'address'+1
int bmp085ReadInt(unsigned char address)
{
  unsigned char msb, lsb;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 2);
  while (Wire.available() < 2);
  msb = Wire.read();
  lsb = Wire.read();

  return (int) msb << 8 | lsb;
}
// Read 1 byte from the BMP085 at 'address'
char bmp085Read(unsigned char address)
{
  unsigned char data;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(BMP085_ADDRESS, 1);
  while (!Wire.available())
    ;

  return Wire.read();
}
void fCheck_Pressure()
{
  short bmp_temperature;
  long bmp_pressure;

      bmp_temperature = bmp085GetTemperature(bmp085ReadUT());
      bmp_pressure = bmp085GetPressure(bmp085ReadUP());
}


User avatar
fly135
Posts: 606
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: read from i2c failed 80 percent chance, after couple reboot it works

Postby fly135 » Thu Feb 14, 2019 6:17 pm

I just got around to doing a production test program. They wanted it done with Arduino IDE because they are familiar with the environment. I find that the I2C fails frequently right after programming and requires up to a couple resets before it works. I never have this problem with the IDF. Looks like Arduino is more of a toy for the ESP32 right now.

John A

paulvha
Posts: 6
Joined: Thu Dec 27, 2018 2:29 pm

Re: read from i2c failed 80 percent chance, after couple reboot it works

Postby paulvha » Sun Feb 17, 2019 2:27 pm

The issue is clock-stretch as mentioned before.

That is not implemented in the ESP32 with the Arduino IDE as it uses the hardware I2C. I run into the same problem with an SCD30 and could not get it to work. In order to overcome I have taken the I2C from the ESP8266 and made it work on an ESP32. It is part of the package https://github.com/paulvha/scd30 . It is called "softwire" (in the src-directory) and with a call setClockStretchLimit(uint32_t) you can set the clock stretch time needed

trustmiao
Posts: 42
Joined: Mon Aug 06, 2018 5:16 am

Re: read from i2c failed 80 percent chance, after couple reboot it works

Postby trustmiao » Thu May 16, 2019 6:24 am

madmax__ wrote:
Thu Feb 14, 2019 10:39 am
FYI,

its working now, bno requires i2c clock stretching and the default value was hard coded in the i2c driver. after increasing the value, it started working.
As we are still struggling with stable i2c connection, may I ask, which value did you play with

Who is online

Users browsing this forum: Basalt and 55 guests