espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.68k stars 7.42k forks source link

I2C issue with BNO055 from Adafruit #81

Closed hngmihai closed 7 years ago

hngmihai commented 7 years ago

Tried to connect the ESP32 with the sensor BNO055 from adafruit (https://learn.adafruit.com/adafruit-bno055-absolute-orientation-sensor/wiring-and-test).

Used the latest commit of arduino-esp32, downloaded the libraries from adafruit, and used their code as well:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>

Adafruit_BNO055 bno = Adafruit_BNO055(55);

void setup(void) 
{
  Serial.begin(9600);
  Serial.println("Orientation Sensor Test"); Serial.println("");

  /* Initialise the sensor */
  if(!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }

  delay(1000);

  bno.setExtCrystalUse(true);
}

void loop(void) 
{
  /* Get a new sensor event */ 
  sensors_event_t event; 
  bno.getEvent(&event);

  /* Display the floating point data */
  Serial.print("X: ");
  Serial.print(event.orientation.x, 4);
  Serial.print("\tY: ");
  Serial.print(event.orientation.y, 4);
  Serial.print("\tZ: ");
  Serial.print(event.orientation.z, 4);
  Serial.println("");

  delay(100);
}

I get the following error message on serial: "Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!" and if I check the SCL / SDA with the scope I get the following result:

15354241_1473509246009757_1195612445_o

Mention: I double checked the wiring!

I don't know what the issue might be, any help would be great.

me-no-dev commented 7 years ago

it seems as the device is first holding SCL and then SDA (I presume SDA is above) what is the frequency of I2C?

hngmihai commented 7 years ago

Your presumption is right. The frequency is default, I haven't changed it: Wire.h: void begin(int sda=-1, int scl=-1, uint32_t frequency=100000);

Here are two more screens from the scope:

  1. This is when I connect the BNO055 to an Arduino UNO and it works 15369765_1474621799231835_159935084_o

  2. This is when I connect the BNO055 to the ESP32 15387466_1474621479231867_509258048_o

Mention: the same application is loaded on both boards.

me-no-dev commented 7 years ago

Interesting... what is that single clock and data pulses before transmission begins? Other than that you can see the same data being sent to your device, but the device does not release SDA after the last byte in the case of ESP32, so that initial pulse is probably screwing something up... it might be a pinInit pulse, so why not add some delay after Wire.begin?

hngmihai commented 7 years ago

Ok so I've tried what you've suggested, added a delay(100); after Wire.begin(); and that pulse before transmission begin was eliminated but everything else is the same (still not working, the only difference is that the pulse is not present anymore).

Meanwhile I've also stumbled upon this:

  // BNO055 clock stretches for 500us or more!
#ifdef ESP8266
  Wire.setClockStretchLimit(1000); // Allow for 1000us of clock stretching
#endif

Could this be the issue? I tried removing the if instruction so that Wire.setClockStretchLimit(1000); should happend on ESP32 as well but the method is not recognized by the compiler. The method does not exist in the driver.

I also printed on serial the return from the Wire.endTransmission(); which is "3" => that is "I2C_ERROR_TIMEOUT". So the driver error is a timeout on the bus.

Hope all of this will suggest something that leads you to a solution :D.

me-no-dev commented 7 years ago

you are probably correct. I will look for such setting and let you know on what could be done :)

silentviper commented 7 years ago

I'm also trying to get the Sparkfun ESP32 Thing to communicate with the BNO055, I have a saleae logic analyzer as well, and when using the arduino i2c scanner code i receive "No I2C devices found" repeatedly, and the logic analyzer sees the device hunt through only even address devices, while the BNO055 is at address 0x28 by default according to the datasheet, but the ESP32 it still isn't seeing a response on the device. An arduino Uno running the same code successfully sees the device at 0x28. Here's a csv export of the Saleae dump Saleae-export.csv.txt and associated screenshot of the signals screen shot 2016-12-08 at 5 12 35 pm as compared to screen shot 2016-12-08 at 5 13 38 pm which is captured from the Arduino Uno.

I've never used i2c in a project so i'm less than confident in my knowledge but if i had to guess, I think @Devilish1208 is correct that it's related to clock stretching, and setClockStretchLimit is not defined, nor did it seem easy to port to me.

Please let me know if I can be any help in testing/debugging a solution.

andrei-ivanov commented 7 years ago

Maybe this will help? http://esp32.com/viewtopic.php?f=19&t=632&p=2832#p2801

me-no-dev commented 7 years ago

try the latest commit please :)

hngmihai commented 7 years ago

Glad you guys came up with this, it gave me some hope:)) Pulled your latest commit and tried it out, it brings some improvement but something is still not good and I'm also quite confused now.

If I load the application from here: http://playground.arduino.cc/Main/I2cScanner (which scans the I2C bus for devices and outputs on serial the address at which it found it) the ESP32 finds the device at address 0x28 (which is the default address of the BNO055 according to its documentation). So this is the improvement because previously not even the scan was working. This improved because you increased this value: i2c->dev->timeout.tout = 400000;//clocks max=1048575

If I load the example application from adafruit website: https://learn.adafruit.com/adafruit-bno055-absolute-orientation-sensor/wiring-and-test which should output on serial some values from the sensor, it seems that the ESP32 finds the BNO055 (because I don-t get the error message that says not found) but after that it hangs (gets stuck). I've also found out by using Serial.print messages that it might be hanging in the while loop you introduced: while(i2c->dev->fifo_st.tx_fifo_end_addr == fifotail) {}; (not 100% sure about this though).

Some mentions:

  1. In the while loop you introduced shouldn't you compare "fifotail" variable with the start address in the structure? (you are now comparing it with: "fifo_st.tx_fifo_end_addr")
  2. While running the scanner app I scoped the SDA and SCL again and this is what I get (There are some bus conflicts, that half amplitude spike there) 15387529_1478590662168282_1576128350_o

2.2. While running the Adafruit sample app I scoped SDL and SCL again and this is the only thing I get (I don't understand this, some initialisation phase probably): 15419466_1478590542168294_606718898_o

me-no-dev commented 7 years ago

the loop is checking supposedly the last byte address of the fifo and waiting for it to change (increment) after we added the byte. Surely it could be some magic going on... try removing it and see how things are

me-no-dev commented 7 years ago

address was detected probably due to the increased timeout ;)

hngmihai commented 7 years ago

@me-no-dev: I'm gonna try that on monday with a scope near and provide what I find out

tolson2000 commented 7 years ago

I have a mod to the I2Cscanner sketch. There should be something between an beginTransmission and endTransmission, else some devices won't respond. See below snippet.

for(address` = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire2.beginTransmission(address); Wire2.write(0x00); // Really needs this for reliability <<<--------------- error = Wire2.endTransmission();

Mat-Alm commented 7 years ago

I think that I2C drivers have bugs related with fifo! (If we can disable fifo for test )Because when you write only one request to the slave device it only act with behaviour that Devilish1208 show in figure 2.2. Also for read BME280 you need a restart condition after writting request to read the registers and is not done in the current I2C implementation. If we have a better docs on the I2C would be nice!

me-no-dev commented 7 years ago

Please try the latest commit. I tested with 6 devices at the same time. I hope we can close this :)

hngmihai commented 7 years ago

tried it now, still not working with the BNO055. It seems to be even worst than before because running the I2C scanner software prints on serial that it finds devices at several adresses (the BNO is the only device connected). For example if I scan adresses from 30 to 50:for (address = 30; address < 50; address++) { I get the following output:

I2C device found at address 0x1F  !
I2C device found at address 0x21  !
I2C device found at address 0x25  ! 
I2C device found at address 0x27  ! 
I2C device found at address 0x28  !
I2C device found at address 0x2A  !
I2C device found at address 0x2C  !
I2C device found at address 0x2E  ! 
I2C device found at address 0x30  !

This is what I catch on the logic analyzer: 2016-12-14_11h03_48

me-no-dev commented 7 years ago

do you guys have pull up resistors on SDA and SCL? I have 1K on my board and without them I2C will not work

me-no-dev commented 7 years ago

I have 6 devices connected at the same time and I have no problems. Scan is working as expected also

hngmihai commented 7 years ago

The BNO055 breakout has pullups of 10k on it

me-no-dev commented 7 years ago

ok, now what are you doing exactly? are you scanning or are you trying to communicate with that device? if scanning is your answer, have you tried communicating with it with the latest version? If it's locking your bus, you might want to look here

Mat-Alm commented 7 years ago

Hello! I found a solution! for read BME280 it will also works for BNO055! After you issue a read command you need to send a nack after the numbers of read that you done! So you need to mod this line in esp32-hal-i2c.c in (line 270) or the read command field change it to i2cSetCmd(i2c, cmdIdx++, I2C_CMD_READ, willRead, true, false, true); And you will be able work fine with this devices!
Also some times is needed to increase the main stack size on maic.c or you can get only single pulses like in figure 2.2 that Devilish1208 posted!

me-no-dev commented 7 years ago

Holly Cow!!!! What A find! Stack size?

me-no-dev commented 7 years ago

breaks all other devices though :(

hngmihai commented 7 years ago

@me-no-dev I was scanning the bus for I2C devices, tired again with latest commit, same behaviour. If I try to communicate with it, it gets stuck somewhere. @Mat-Alm tried to modify line 270 like you said => It seems to connect to the device because I don't get the error message that BNO055 was not detected but I than get that same value over and over again "from the device" (I'm not sure it really sends anything because this is what I catch on logic analyzer):

2016-12-14_16h44_00

torntrousers commented 7 years ago

FYI I've tried @Mat-Alm 's line 270 change and it gets a BME280 working for me.

me-no-dev commented 7 years ago

but breaks many (all of mine) other I2C devices

Mat-Alm commented 7 years ago

Delvish check if your code / library send the stop conditions right? like Wire.endTransmission(true); Scan works fine to me! I also have 10k pulls near the device.

Mat-Alm commented 7 years ago

me-no-dev but my changes are like I2C specs for read ex: image

me-no-dev commented 7 years ago

@Mat-Alm you just brought an idea in my head... let me see what I can do. Signaling is OK, there is something totally else that is going on.

me-no-dev commented 7 years ago

ok try the commit now

Mat-Alm commented 7 years ago

For my device BME280 it's working! You had changed the behaviour of multiple and single reads? And what about the : `/*

What are exactly ack fields behaviour?

Mat-Alm commented 7 years ago

Tested with tmp006 it also works! But the max30100 does not work and I get only single pulses of death!

me-no-dev commented 7 years ago

ack_val sets the level of the ack bit when you are reading from a slave. If you set it to true, it will actually send NACK. ack_exp sets the level of the ack bit that you are expecting to get when you are writing to a slave ack_check sets wether correct ack level should be checked and error bit set if it fails

silentviper commented 7 years ago

@me-no-dev I just tested on a BNO055, and it works!! Address scanning and data pulling, without any extra pull-up resistors.

1 catch, i'm not entirely sure why sensorapi.ino does not work but bunny.ino does. I didn't dig into it just yet.

Thank you!!

hngmihai commented 7 years ago

@me-no-dev you did your magic good. Seems to work now, first tests. Congrats m8.

me-no-dev commented 7 years ago

that's good news guys! Thank you all for the help! I'll keep this open a bit more because I need to make scanning work better (writing only the address to the bus) and would like you to test the result against your devices to make sure I do not break something along the way :)

me-no-dev commented 7 years ago

alright was chasing ghosts (did not pull the latest change in my working branch) closing this now :) Thank you all for the help!