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 Reply Children
  • 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

Related