Unable to get gpio interrupt from LSM6DS3TR_C to nRF52840 in the Seeed Studio Xiao Ble Sense

static void IMU_config(void)
{
  uint8_t error=0;
  //Set the Accelerometer control register to work at 6.6kHz Hz,Full Scale 16g
  error+= i2c_reg_write_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_CTRL1_XL,0x90);
  //Set ODR/4
  error+= i2c_reg_write_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_CTRL8_XL,0x1C);
  error +=i2c_reg_write_byte(lsm6ds3tr_c,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_CTRL9_XL,0x34);
  // A wake up threshold of 5042 mg
  error+= i2c_reg_write_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_WAKE_UP_THS,0x0F);
  // Wake up duration is in ms therefore value has to be set to 0x00
  error+= i2c_reg_write_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_WAKE_UP_DUR,0x60);
  // Enables Interrupts
  error+= i2c_reg_write_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_TAP_CFG,0xB1);
  //Routing of Wake up event
  error+= i2c_reg_write_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_MD1_CFG,0x20);
  error+= i2c_reg_write_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_INT1_CTRL,0x43);
  error+= i2c_reg_write_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_MD2_CFG,0x20);
  error+= i2c_reg_write_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_INT2_CTRL,0x03);
}
static void IMU_Sensor(){
   //Rd reg
   i2c_reg_read_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_OUTX_L_XL,&xAccelL);
   i2c_reg_read_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_OUTY_L_XL,&yAccelL);
   i2c_reg_read_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_OUTZ_L_XL,&zAccelL);

   i2c_reg_read_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_OUTX_H_XL,&xAccelH);
   i2c_reg_read_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_OUTY_H_XL,&yAccelH);
   i2c_reg_read_byte(lsm6ds3trc,LSM6DSL_VAL_WHO_AM_I,LSM6DSL_REG_OUTZ_H_XL,&zAccelH);

    x_accRaw = ((int16_t)(xAccelH<<8))|(xAccelL & 0xFF);
    y_accRaw = ((int16_t)(yAccelH<<8))|(yAccelL & 0xFF);
    z_accRaw = ((int16_t)(zAccelH<<8))|(zAccelL & 0xFF);

    x_accRaw = (x_accRaw*0.061)/15;
    y_accRaw = (y_accRaw*0.061)/15;
    z_accRaw = (z_accRaw*0.061)/15;
}
void sleep_handler(nrfx_power_sleep_evt_t current_state )
{
  switch (current_state)
  {
  case NRFX_POWER_SLEEP_EVT_ENTER:
       printf("System sleep\n");
       NRF_POWER->INTENSET=1;//Enables Interrupt
       NRF_POWER->EVENTS_SLEEPENTER=1;// CPU enters wait for WFI/WFE
    break;
  case NRFX_POWER_SLEEP_EVT_EXIT:
       NRF_POWER->EVENTS_SLEEPEXIT=1;//CPU Exits WFI/WFE
        IMU_config();
        IMU_Sensor();
        err = i2c_reg_read_byte(lsm6ds3trc, LSM6DSL_VAL_WHO_AM_I, LSM6DSL_REG_WAKE_UP_SRC, &wkp);
    if (err)
    {
    printf("Failed to read wake-up source.");
    }  
    if(wkp && 0x0F){
       printk("Exceeded Threshold----------------------->\n");
            // Read timestamp
            err = i2c_reg_read_byte(lsm6ds3trc, LSM6DSL_VAL_WHO_AM_I, LSM6DSL_REG_TIMESTAMP0, &timestamp0);
            err = i2c_reg_read_byte(lsm6ds3trc, LSM6DSL_VAL_WHO_AM_I, LSM6DSL_REG_TIMESTAMP1, &timestamp1);
            err = i2c_reg_read_byte(lsm6ds3trc, LSM6DSL_VAL_WHO_AM_I, LSM6DSL_REG_TIMESTAMP2, &timestamp2);
            timestamp = ((uint32_t)timestamp2 << 16) | ((uint16_t)timestamp1 << 8) | timestamp0;
           
                // Calculate acceleration
                pAc = sqrt(sqr(x_accRaw) + sqr(y_accRaw) + sqr(z_accRaw));
                snprintf(X1, sizeof(X1), "Peak %d\n", pAc);
                printk("Acceleration=%s\n", X1);
                // Check if pAc is greater than 4500
                if (pAc > 900)
                {
                ret=gpio_pin_configure_dt(&led_2,GPIO_OUTPUT_ACTIVE);
                bt_ready();
                k_sleep(K_SECONDS(10)); // Delay for 10 seconds
                bt_disable();
                ret=gpio_pin_configure_dt(&led_2,GPIO_OUTPUT_INACTIVE);
               }
                 else
                  {
                   printk("No fall detected\n");
                  }
    }
    else
    {
       printf("No wake up in LSM6DS3.\n");
    }
   
  default:
       //NRF_POWER->TASKS_LOWPWR=1;//Low power mode
    break;
  }
}
// Interrupt Call back function
void lsm6ds3trc_irq_callback(const struct device *port,struct gpio_callback *cb,gpio_port_pins_t pins)
{      
        current_state = NRFX_POWER_SLEEP_EVT_EXIT;
         sleep_handler(current_state);
         printf("Successful Interrupt\n");
         NRFX_DELAY_US(100000);
         current_state=NRFX_POWER_SLEEP_EVT_ENTER;
         sleep_handler(current_state);
}
static struct gpio_callback interrupt_callback={
  .handler=lsm6ds3trc_irq_callback,
};

int main(void)
{
    int err;
   
    if(!device_is_ready(lsm6ds3trc))
    {
      printk("LSM6DS3 device not ready\n");
    }
    IMU_config();
    IMU_Sensor();
    printf("IMU Configured and Sensed\n");
    err=gpio_pin_configure_dt(&irq_pin,GPIO_INPUT);
    if(err!=0){
       printf("Pin not configured\n");
    }
    err=gpio_pin_interrupt_configure_dt(&irq_pin,GPIO_INT_EDGE_RISING);
    if(err!=0){
      printf("Interrupt not configured\n");
    }
    nrf_gpio_cfg_input(irq_pin.pin,NRFX_GPIOTE_DEFAULT_PULL_CONFIG);
    nrf_gpio_cfg_sense_set(irq_pin.pin,NRFX_GPIOTE_ENABLED);
    err = i2c_reg_read_byte(lsm6ds3trc, LSM6DSL_VAL_WHO_AM_I, LSM6DSL_REG_WAKE_UP_SRC, &wkp);
    if (err)
    {
    printf("Failed to read wake-up source.");
    }  
   
    if(wkp && 0x0F){
    gpio_init_callback(&interrupt_callback,lsm6ds3trc_irq_callback,BIT(irq_pin.pin));
    gpio_add_callback(irq_pin.port,&interrupt_callback);
    }
    else
    {
      printf("Wake up threshold not exceeded\n");
    }
    current_state=NRFX_POWER_SLEEP_EVT_ENTER;
    sleep_handler(current_state);
    k_sleep(K_MSEC(100));    
   return 0;
}This the program that I use to make the nRF52840 to go sleep and wake up when an interrupt arrives from lsm6ds3tr_c due to FREE_FALL bit . But it seems like it is not waking up. The same program when used by replacing an external gpio button instead of lsm6ds3tr_c works fine. Could anyone please tell me to find a solution for this.
#define LED2_NODE DT_ALIAS(led2) //BLUE colour LED
#define I2C_NODE DT_NODELABEL(i2c0)
#define INT_NODE DT_NODELABEL(lsm6ds3tr_c)

// Declaration I2C connection of LSM6DS3TRC
static const struct device *lsm6ds3trc = DEVICE_DT_GET(I2C_NODE);
// Declaration of GPIO for pin interrupt
static const struct gpio_dt_spec irq_pin = GPIO_DT_SPEC_GET(INT_NODE,irq_gpios);
// LED declaration
static const struct gpio_dt_spec led_2 = GPIO_DT_SPEC_GET(LED2_NODE, gpios); these are the user defined macros
Parents
  • Hi

    Which version of NCS are you using? Can you also share your prj.conf

    When you say sleep, which power mode is it? If it is in system of then you need an external event to wake it up, either on a GPIO or NFC

    Regards

    Runar

  • The NCS version I used is 2.6.1 and the prj.conf of the program is 

    CONFIG_GPIO=y
    # Increased stack due to settings API usage
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

    CONFIG_BT=y
    CONFIG_LOG=y
    CONFIG_BT_SMP=y
    CONFIG_BT_SIGNING=y
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_DIS=y
    CONFIG_BT_ATT_PREPARE_COUNT=5
    CONFIG_BT_BAS=y
    CONFIG_BT_PRIVACY=y
    CONFIG_BT_DEVICE_NAME="VFP"
    CONFIG_BT_DEVICE_APPEARANCE=833
    CONFIG_BT_DEVICE_NAME_DYNAMIC=y
    CONFIG_BT_DEVICE_NAME_MAX=65
    CONFIG_BT_KEYS_OVERWRITE_OLDEST=y
    CONFIG_BT_SETTINGS=y
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    CONFIG_EVENTS=y
    CONFIG_GPIO_NRFX_INTERRUPT=y
    CONFIG_NRFX_GPIOTE_NUM_OF_EVT_HANDLERS=1
    CONFIG_NRFX_POWER=y 
    I used this header file 
    #include <nrfx_power.h> for power management.
  • Thank you. 

    Is that your entire prj,conf? I see no reference to the sensor there. Is there a reason why you are not using the Zephyr driver?

    Also please upload your overlay. 

    Regards

    Runar

  • This is the prj.conf completely and the device tree is already provided when you select the board xiao ble sense it looks like this 


    /dts-v1/;
    #include "xiao_ble_common.dtsi"
    #include <zephyr/dt-bindings/i2c/i2c.h>
    #include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>

    / {
        model = "Seeed XIAO BLE Sense";
        compatible = "seeed,xiao-ble", "seeed,xiao-ble-sense";

        lsm6ds3tr-c-en {
            compatible = "regulator-fixed-sync", "regulator-fixed";
            enable-gpios = <&gpio1 8 (NRF_GPIO_DRIVE_S0H1 | GPIO_ACTIVE_HIGH)>;
            regulator-name = "LSM6DS3TR_C_EN";
            regulator-boot-on;
            startup-delay-us = <3000>;
        };
    };

    &i2c0 {
        compatible = "nordic,nrf-twim";
        /* Cannot be used together with spi0. */
        status = "okay";
        pinctrl-0 = <&i2c0_default>;
        pinctrl-1 = <&i2c0_sleep>;
        pinctrl-names = "default", "sleep";
        clock-frequency = <I2C_BITRATE_FAST>;

        lsm6ds3tr_c: lsm6ds3tr-c@6a {
            compatible = "st,lsm6dsl";
            reg = <0x6a>;
            irq-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
            status = "okay";
        };
    };
    I am not familiar with zephyr drivers I am using nRF connect extension available in VS code
  • Thank you

    So just as you might be aware with NCS we are using an RTOS names Zephyr. With Zephyr there is a number of different sensors supported so that you don't need to write your own driver. I would recommend that you use the zephyr driver and the sensor api instead of trying to write your own. I would recommend by starting with the LSM6DSL sample

    Regards

    Runar

  • But it is mentioned device tree of Seeed Xiao Ble sense that the sensor lsm6dstrc inside it is compatible with LSM6DSL

  • Hi 
    I think we are talking a bit past each other. Just so that we don't have any misunderstandings. Have you worked with Zephyr before? If not I would recommend that you at least have a look at our NCS Fundamentals course
    I see that your prj.conf you have not enabled CONFIG_LSM6DSL or any other Kconfig which should be enabled when working with peripherals. I would again advice that you at least take a look at the sample I mentioned in my last reply where you can see how to use the sensor api and the driver that is already in Zephyr

    Regards

    Runar

Reply
  • Hi 
    I think we are talking a bit past each other. Just so that we don't have any misunderstandings. Have you worked with Zephyr before? If not I would recommend that you at least have a look at our NCS Fundamentals course
    I see that your prj.conf you have not enabled CONFIG_LSM6DSL or any other Kconfig which should be enabled when working with peripherals. I would again advice that you at least take a look at the sample I mentioned in my last reply where you can see how to use the sensor api and the driver that is already in Zephyr

    Regards

    Runar

Children
Related