adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.13k stars 1.22k forks source link

BNO080 reboots/hangs ESP32S3 when accessing it via I2C. #6255

Closed mjs513 closed 1 year ago

mjs513 commented 2 years ago

CircuitPython version

Adafruit CircuitPython 7.3.0-beta.0 on 2022-04-01; ESP32-S3-DevKitC-1-N8 with ESP32S3
Board ID:espressif_esp32s3_devkitc_1_n8

Code/REPL

# SPDX-FileCopyrightText: 2017 Limor Fried for Adafruit Industries
# SPDX-FileCopyrightText: 2017 Limor Fried for Adafruit Industries
#
# SPDX-License-Identifier: MIT

"""CircuitPython I2C Device Address Scan"""
# If you run this and it seems to hang, try manually unlocking
# your I2C bus from the REPL with
#  >>> import board
#  >>> board.I2C().unlock()

import time
import board
import busio

# To use default I2C bus (most boards) scl/sda
i2c = busio.I2C(board.IO10, board.IO11)
i2c1 = busio.I2C(board.IO1, board.IO2)

def i2cportscan():
    print("Wire")
    # Lock the I2C device before we try to scan
    while not i2c.try_lock():
        pass
    # Print the addresses found once
    # print(
    #    "I2C addresses found:", [hex(device_address) for device_address in i2c.scan()]
    # )
    for device_address in i2c.scan():
        print("Device found at address", end=" ")
        print(hex(device_address), end=" (")
        printKnownChips(hex(device_address))
        print(end=")")
        print()
    # Unlock I2C now that we're done scanning.
    i2c.unlock()

def i2cport1scan():
    print("Wire1")
    # Lock the I2C device before we try to scan
    while not i2c1.try_lock():
        pass
    # Print the addresses found once
    for device_address in i2c1.scan():
        print("Device found at address", end=" ")
        print(hex(device_address), end=" (")
        printKnownChips(hex(device_address))
        print(end=")")
        print()
    # Unlock I2C now that we're done scanning.
    i2c1.unlock()

def printKnownChips(address):
    # print("passed address:", address)
    if address == "0x00":
        print("AS3935", end=" ")
        return
    if address == "0x01":
        print("AS3935", end=" ")
        return
    if address == "0x02":
        print("AS3935", end=" ")
        return
    if address == "0x03":
        print("AS3935", end=" ")
        return
    if address == "0x04":
        print("ADAU1966", end=" ")
        return
    if address == "0x0a":
        print("SGTL5000", end=" ")
        return
    if address == "0x0b":
        print("SMBusBattery?", end=" ")
        return
    if address == "0x0c":
        print("AK8963", end=" ")
        return
    if address == "0x10":
        print("CS4272", end=" ")
        return
    if address == "0x11":
        print("Si4713", end=" ")
        return
    if address == "0x13":
        print("VCNL4000,AK4558", end=" ")
        return
    if address == "0x18":
        print("LIS331DLH", end=" ")
        return
    if address == "0x19":
        print("LSM303,LIS331DLH", end=" ")
        return
    if address == "0x1a":
        print("WM8731", end=" ")
        return
    if address == "0x1c":
        print("LIS3MDL", end=" ")
        return
    if address == "0x1d":
        print("LSM303D,LSM9DS0,ADXL345,MMA7455L,LSM9DS1,LIS3DSH", end=" ")
        return
    if address == "0x1e":
        print("LSM303D,HMC5883L,FXOS8700,LIS3DSH", end=" ")
        return
    if address == "0x20":
        print("MCP23017,MCP23008,PCF8574,FXAS21002,SoilMoisture", end=" ")
        return
    if address == "0x21":
        print("MCP23017,MCP23008,PCF8574", end=" ")
        return
    if address == "0x22":
        print("MCP23017,MCP23008,PCF8574", end=" ")
        return
    if address == "0x23":
        print("MCP23017,MCP23008,PCF8574", end=" ")
        return
    if address == "0x24":
        print("MCP23017,MCP23008,PCF8574,ADAU1966,HM01B0", end=" ")
        return
    if address == "0x25":
        print("MCP23017,MCP23008,PCF8574", end=" ")
        return
    if address == "0x26":
        print("MCP23017,MCP23008,PCF8574", end=" ")
        return
    if address == "0x27":
        print("MCP23017,MCP23008,PCF8574,LCD16x2,DigoleDisplay", end=" ")
        return
    if address == "0x28":
        print("BNO055,EM7180,CAP1188", end=" ")
        return
    if address == "0x29":
        print("TSL2561,VL6180,TSL2561,TSL2591,BNO055,CAP1188", end=" ")
        return
    if address == "0x2a":
        print("SGTL5000,CAP1188", end=" ")
        return
    if address == "0x2b":
        print("CAP1188", end=" ")
        return
    if address == "0x2c":
        print("MCP44XX ePot", end=" ")
        return
    if address == "0x2d":
        print("MCP44XX ePot", end=" ")
        return
    if address == "0x2e":
        print("MCP44XX ePot", end=" ")
        return
    if address == "0x2f":
        print("MCP44XX ePot", end=" ")
        return
    if address == "0x30":
        print("Si7210", end=" ")
        return
    if address == "0x31":
        print("Si7210", end=" ")
        return
    if address == "0x32":
        print("Si7210", end=" ")
        return
    if address == "0x33":
        print("MAX11614,MAX11615,Si7210", end=" ")
        return
    if address == "0x34":
        print("MAX11612,MAX11613", end=" ")
        return
    if address == "0x35":
        print("MAX11616,MAX11617", end=" ")
        return
    if address == "0x38":
        print("RA8875,FT6206,MAX98390", end=" ")
        return
    if address == "0x39":
        print("TSL2561, APDS9960", end=" ")
        return
    if address == "0x3c":
        print("SSD1306,DigisparkOLED", end=" ")
        return
    if address == "0x3d":
        print("SSD1306", end=" ")
        return
    if address == "0x40":
        print("PCA9685,Si7021,MS8607", end=" ")
        return
    if address == "0x41":
        print("STMPE610,PCA9685", end=" ")
        return
    if address == "0x42":
        print("PCA9685", end=" ")
        return
    if address == "0x43":
        print("PCA9685", end=" ")
        return
    if address == "0x44":
        print("PCA9685, SHT3X, ADAU1966", end=" ")
        return
    if address == "0x45":
        print("PCA9685, SHT3X", end=" ")
        return
    if address == "0x46":
        print("PCA9685", end=" ")
        return
    if address == "0x47":
        print("PCA9685", end=" ")
        return
    if address == "0x48":
        print("ADS1115,PN532,TMP102,LM75,PCF8591,CS42448", end=" ")
        return
    if address == "0x49":
        print("ADS1115,TSL2561,PCF8591,CS42448", end=" ")
        return
    if address == "0x4a":
        print("ADS1115,Qwiic Keypad,CS42448", end=" ")
        return
    if address == "0x4b":
        print("ADS1115,TMP102,BNO080,Qwiic Keypad,CS42448", end=" ")
        return
    if address == "0x50":
        print("EEPROM,FRAM", end=" ")
        return
    if address == "0x51":
        print("EEPROM", end=" ")
        return
    if address == "0x52":
        print("Nunchuk,EEPROM", end=" ")
        return
    if address == "0x53":
        print("ADXL345,EEPROM", end=" ")
        return
    if address == "0x54":
        print("EEPROM", end=" ")
        return
    if address == "0x55":
        print("EEPROM", end=" ")
        return
    if address == "0x56":
        print("EEPROM", end=" ")
        return
    if address == "0x57":
        print("EEPROM", end=" ")
        return
    if address == "0x58":
        print("TPA2016,MAX21100", end=" ")
        return
    if address == "0x5a":
        print("MPR121", end=" ")
        return
    if address == "0x60":
        print("MPL3115,MCP4725,MCP4728,TEA5767,Si5351", end=" ")
        return
    if address == "0x61":
        print("MCP4725,AtlasEzoDO", end=" ")
        return
    if address == "0x62":
        print("LidarLite,MCP4725,AtlasEzoORP", end=" ")
        return
    if address == "0x63":
        print("MCP4725,AtlasEzoPH", end=" ")
        return
    if address == "0x64":
        print("AtlasEzoEC, ADAU1966", end=" ")
        return
    if address == "0x66":
        print("AtlasEzoRTD", end=" ")
        return
    if address == "0x68":
        print("DS1307/3231,MPU6050/9050,MPU9250,ITG3200/3701,LSM9DS0,L3G4200D", end=" ")
        return
    if address == "0x69":
        print("MPU6050,MPU9050,MPU9250,ITG3701,L3G4200D", end=" ")
        return
    if address == "0x6a":
        print("LSM9DS1", end=" ")
        return
    if address == "0x6b":
        print("LSM9DS0", end=" ")
        return
    if address == "0x6f":
        print("Qwiic Button", end=" ")
        return
    if address == "0x70":
        print("HT16K33,TCA9548A", end=" ")
        return
    if address == "0x71":
        print("SFE7SEG,HT16K33", end=" ")
        return
    if address == "0x72":
        print("HT16K33", end=" ")
        return
    if address == "0x73":
        print("HT16K33", end=" ")
        return
    if address == "0x76":
        print("MS5607,MS5611,MS5637,BMP280", end=" ")
        return
    if address == "0x77":
        print("BMP085,BMA180,BMP280,MS5611", end=" ")
        return
    if address == "0x7c":
        print("FRAM_ID", end=" ")
        return
    print("UNKNOWN DEVICE", end=" ")
    return

i2cportscan()
i2cport1scan()

Behavior

Device found at address 0x3c (SSD1306,DigisparkOLED )
Device found at address 0x50 (EEPROM,FRAM )
Device found at address 0x62 (LidarLite,MCP4725,AtlasEzoORP )
Device found at address 0x6f (Qwiic Button )
Wire1
Device found at address 0x29 (TSL2561,VL6180,TSL2561,TSL2591,BNO055,CAP1188 )
Device found at address 0x68 (DS1307/3231,MPU6050/9050,MPU9250,ITG3200/3701,LSM9DS0,L3G4200D )

Code done running.

When working but if I try to add a BNO080 (Adafruit or Sparkfun) it reboots the ESP32S3 and seems to hang. No error messages

Description

Using a I2c test board that we used for testing the Teens 4.1: Image_20220406_092212

I attached the ESP32S3. All worked well until I tried to add the BNO080 to either I2c or I2c1 bus (Arduino verbiage Wire or Wire1). When I add the BNO080 it reboots the ESP32S3 and seems to hang Mu edit and I have to power cycle to get it running again. No error messages appear.

If I run the same script using CircuitPython on the T4.1 it picks up all devices including the BNO080. I do have a QT PY RP204 on order to test it with that as well.

Additional information

No response

mjs513 commented 2 years ago

As a follow up believe it related to a clock stretching issue with the BNO080: https://github.com/adafruit/Adafruit_CircuitPython_BNO08x/issues/33

Will try a i2c1 = bitbangio.I2C(board.I2C_SCL1, board.I2C_SDA1, timeout = 500) next time I have it set up

jepler commented 2 years ago

There are known problems with esp32-s3 in i2c as well, which we are tracking. But it's true, the BNO chips have some interesting I2C behavior as well.

mjs513 commented 2 years ago

Yeah. Was doing some research this morning and seems to be a known problem. Unfortunately also happening on the RP2040, Teensy Micromod and Teensy 4.1 as well.

Early on in the development of the Teensy 4 we had similar issues with the BNO055 and BNO080 and required a changed to I2C. For ref here was the fix = at least for the teensy in i2c: https://github.com/PaulStoffregen/Wire/pull/16/commits/08d870fc130b741e4fdee38798c64a28949c853d
Maybe a clue for you all to look at

dhalbert commented 2 years ago

Will re-test after pending S3 I2C fixes are added to ESP-IDF v4.4.x.

dhalbert commented 2 years ago

I retested with a BNO055 on Feather ESP32-S3 with the latest build, and it still fails. It works fine on ESP32-S2, and also with bitbangio.I2C(). This may have the same root cause as #6311.

dhalbert commented 2 years ago

Pushing this forward to 8.x.x because I don't see an upstream fix in sight.

dhalbert commented 1 year ago

The BNO0xx sensors are known to violate the I2C bus protocol under certain conditions. I did some testing of the BNO055 here: https://github.com/adafruit/Adafruit_CircuitPython_BNO055/issues/115. I expect similar results with the BNO080. Perhaps we can make the library do some error recovery, but given that the BNO sensors themselves are flaky, I'm not sure we should characterize this as a bug that we expect the ESP-IDF to fix. The ultimate bug is in the BNO sensors themselves.

I will close this as "can't fix" in the core for now. If you disagree let me know. I will add some warnings to the BNO080 learn guide, and have opened this library issue: https://github.com/adafruit/Adafruit_CircuitPython_BNO08x/issues/41

dhalbert commented 1 year ago

I retested after we upgraded to ESP-IDF v5.1 in CircuitPython 9.0.0-alpha.2. BNO055 still does not work. This is not so surprising. I added warnings to the appropriate BNO guides a while ago.