espressif / arduino-esp32

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

How do I use HSPI for communicating with LSM6DS3 (6-DoF IMU) #3370

Closed amoghskulkarni closed 4 years ago

amoghskulkarni commented 4 years ago

Hardware:

Board: ESP32-DevKitC Core Installation version: 1.11.0 IDE name: Platform.io Flash Frequency: 40Mhz PSRAM enabled: Not sure Upload Speed: 115200 Computer OS: Windows 10

Description:

I am trying to connect to LSM6DS3 via SPI using this library. The library works as expected if I connect the sensor to VSPI, but connecting the sensor to HSPI runs into multiple problems -

  1. Uploading the sketch fails with following error
    
    Chip is ESP32D0WDQ6 (revision 1)
    Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
    MAC: a4:cf:12:0a:69:b8
    Uploading stub...
    *** [upload] Error 2
    Running stub...
    Stub running...
    Changing baud rate to 460800
    Changed.
    Configuring flash size...
    Warning: Could not auto-detect Flash size (FlashID=0xffffff, SizeID=0xff), defaulting to 4MB
    Compressed 15872 bytes to 10319...

A fatal error occurred: Timed out waiting for packet content =============================================================================================================================== [FAILED] Took 11.08 seconds ===============================================================================================================================
The terminal process terminated with exit code: 1


If I disconnect the sensor while uploading the sketch, it doesn't run into the error.

2. When I try to boot, it runs into an error loop as follows (without completing the boot sequence) - 

rst:0x10 (RTCWDT_RTC_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT) flash read err, 1000 ets_main.c 371
ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT) flash read err, 1000 ets_main.c 371
ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT) flash read err, 1000 ets_main.c 371
ets Jun 8 2016 00:22:57



Sorry I wouldn't be able to provide any sketch here, as it is quite large - but the problem is not with the business logic of the sketch anyway. When I replace VSPI with HSPI, the problem starts occurring, so something tells me that the problem might be related to the bootloader and/or SPI flash config. I'm new to ESP32 and not quite sure how flash is connected to SPI h/w internally. 

P.S. I have used other sensors with HSPI earlier, and they work ok - so, I'm not able to locate the problem correctly. 
me-no-dev commented 4 years ago

which pins are you using? how do you init the SPI? please show some code :)

lbernstone commented 4 years ago

I still have this in my copy buffer from the last issue :smile: https://github.com/espressif/esp-idf/tree/master/examples/storage/sd_card#note-about-gpio12

amoghskulkarni commented 4 years ago

@me-no-dev

please show some code :)

Alright, here are a few snippets (but I'm not sure if they will be any helpful).

SPIClass* hspi = NULL;
SPIClass* vspi = NULL;
LSM6DS3* lsm_sensor_object = NULL;
// Some more declarations and unrelated stuff //

void setup() {
    // Setup serial
    Serial.begin(115200);

    // Setup SPI
    hspi = new SPIClass(HSPI);
    hspi->begin();

    vspi = new SPIClass(VSPI);
    vspi->begin();

    // Create and init LSM6DS3 Sensor object
    Serial.println("Starting LSM6DS3 Init");
    lsm_sensor_object = new LSM6DS3(SPI_MODE, 4, vspi);    // Please see the note down below
    if (lsm_sensor_object->begin() != 0) {
        Serial.println("Error in LSM6DS3 Init");
    }
    Serial.println("LSM6DS3 Init successful");

    // --- Remaining code which uses LSM6DS3 sensor object to read values --- // 
}

Note that I changed the library code very slightly so that it accepts a pointer to the instance of an SPI object, instead of letting it rely on the default SPI, declared in SPI.h (seen here).

So my library functions look something like this (compared to this) -

LSM6DS3Core::LSM6DS3Core( uint8_t busType, uint8_t inputArg, SPIClass* spi ) : commInterface(I2C_MODE), I2CAddress(0x6B), chipSelectPin(10), SPIBus(NULL)
{
    commInterface = busType;
    if( commInterface == I2C_MODE )
    {
        I2CAddress = inputArg;
    }
    if( commInterface == SPI_MODE )
    {
        chipSelectPin = inputArg;
        SPIBus = spi;
    }

}

status_t LSM6DS3Core::beginCore(void)
{
    status_t returnError = IMU_SUCCESS;

    switch (commInterface) {

    case I2C_MODE:
        Wire.begin();
        break;

    case SPI_MODE:
        // start the SPI library:
        SPIBus->begin();
        // Maximum SPI frequency is 10MHz, could divide by 2 here:
        SPIBus->setClockDivider(SPI_CLOCK_DIV4);
        // Data is read and written MSb first.
#ifdef ESP32
        SPIBus->setBitOrder(SPI_MSBFIRST);
#elif ESP8266
        SPI.setBitOrder(SPI_MSBFIRST);
#else
        SPI.setBitOrder(MSBFIRST);
#endif
        // Data is captured on rising edge of clock (CPHA = 0)
        // Base value of the clock is HIGH (CPOL = 1)

// --- Remaining code is almost the same as the original library --- //

The line Serial.println("Starting LSM6DS3 Init"); doesn't get executed, which tells me that the problem should not be related to any of the changes that I made in the library, because library is not in the picture yet.

As far as the pins are concerned, I am using following pin mapping -

GPIO14 => HSPI CLK
GPIO12 => HSPI MISO
GPIO13 => HSPI MOSI 
GPIO25 => HSPI CS

GPIO18 => VSPI CLK
GPIO19 => VSPI MISO
GPIO23 => VSPI MOSI
GPIO4   => VSPI CS
amoghskulkarni commented 4 years ago

@lbernstone Thanks for the reply, this seems relevant. Can I directly short the 3v3 pin and GPIO12 pin, or should I use a resistor in between them? Also, I use platform.io for programming, and not sure how I can program efuses (is there a config file which esptool.py uses?).

lbernstone commented 4 years ago

If you cannot guarantee that gpio12 will be low at boot, you need to burn the efuse. espefuse.py is a command line tool available as part of esptool

amoghskulkarni commented 4 years ago

@lbernstone The fuse bit was indeed the issue and after I burned it, it worked perfectly! Thanks a ton!

Just one final question - In case I don't want to burn the fuse, does GPIO12 need to be low throughout the operation, or just during the boot sequence for HSPI to work?

lbernstone commented 4 years ago

Just during boot or other resets. If you are using modules, it really doesn't hurt much to burn that particular fuse.