XIAO BLE Sense (nRF52840) Absolute Wrist TIlt

I am using XIAO BLE Sense nRF52840 which has the inbuilt IMU sensor, LSM6DS3TR-C. In its datasheet I came across the “Absolute Wrist Tilt (AWT)” function which “allows detecting when the angle between a selectable accelerometer semi-axis and the horizontal plane becomes higher than a specific user-selectable value”.
I want to generate an interrupt when the device is tilted by a roll (Y) of 85 to 180 deg, I can’t see anybody use this AWT function unlike free-fall, double tap, etc.
Does anyone know how to enable this?

Hi there,
No you are NOT …LOL :grin:
Yes, Not too difficult You can read the Data-sheet and look at the examples to gain some understanding.
You can generate an interrupt at a certain angle of tilt. AFAIK.
Look at some of the demo’s I posted about the IMU. It’s all about the configuration Register and the values you write to it. There are no High level OUT of the can LIBs, Examples do exist, AFAIK. but I haven’t searched for it.
Also you can use a filter with the RAW floats to get a “YAW” value that also can be utilized.
HTH
GL :slight_smile: PJ :v:

I am unable to find a library that supports this AWT (I am using the Seeed LSM6DS3 library which doesn’t have this, for now).
So, I did try configuring the registers for “tilt detection” and it worked, but I don’t want to stick to the default tilt of 35 degrees… If you could tell me a way to configure this- it would be of great help!

//adapted from the Free Fall example
#include "LSM6DS3.h"
#include "Wire.h"

//Create a instance of class LSM6DS3
LSM6DS3 lsm6ds3(I2C_MODE, 0x6A);    //I2C device address 0x6A
uint16_t detectCount = 0;

void setup() {
    Serial.begin(9600);
    while (!Serial);
    if (lsm6ds3.begin() != 0) {
        Serial.println("Device error");
    } else {
        Serial.println("Device OK!");
    }

    if (0 != config_tilt_detect()) {
        Serial.println("Fail to configure!");
    } else {
        Serial.println("Success to Configure!");
    }
}

void loop() {
    uint8_t readDataByte = 0;
    //Read the wake-up source register
    lsm6ds3.readRegister(&readDataByte, LSM6DS3_ACC_GYRO_FUNC_SRC);
    //Mask off the TILT_IA bit for tilt detection
    readDataByte &= 0x20;
    if (readDataByte) {
        detectCount ++;
        Serial.print("Tilt detected!  ");
        Serial.println(detectCount);
    }
    delay(10);
}

int config_tilt_detect(void) {
    uint8_t error = 0;
    uint8_t dataToWrite = 0;

    dataToWrite |= LSM6DS3_ACC_GYRO_BW_XL_200Hz;
    dataToWrite |= LSM6DS3_ACC_GYRO_FS_XL_2g;
    dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_416Hz;

    error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_CTRL1_XL, dataToWrite); //same
    error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_CTRL10_C, 0x3C); //same
    error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_WAKE_UP_DUR, 0x00);//same
    // error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_FREE_FALL, 0x33);
    error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_MD1_CFG, 0x02); //tilt interrupt on INT1
    error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_MD2_CFG, 0x02); //tilt interrupt on INT2
    error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0xA1); 

    return error;
}

you can configure the LSM6DS3 sensor to generate an interrupt when the roll (Y) axis exceeds the desired angle range. Here’s a basic example of how you might do this :

#include <Wire.h>
#include <SPI.h>
#include <SparkFunLSM6DS3.h>

LSM6DS3 myIMU; // Create an instance of the LSM6DS3 class

void setup() {
  Serial.begin(9600);
  while (!Serial); // Wait for Serial Monitor to open

  if (!myIMU.begin()) {
    Serial.println("Failed to communicate with LSM6DS3.");
    while (1);
  }

  // Set the accelerometer full scale range to +/- 16g
  myIMU.setAccelRange(LSM6DS3_ACC_RANGE_16G);

  // Set the gyroscope full scale range to +/- 2000dps
  myIMU.setGyroRange(LSM6DS3_GYRO_RANGE_2000DPS);

  // Enable the high-pass filter for accelerometer data
  myIMU.enableAccelHPF();

  // Configure the interrupt to trigger when the Y-axis roll angle is between 85 and 180 degrees
  // This assumes you're using the interrupt pin on the LSM6DS3 breakout board
  myIMU.configInt1(gen_int1_route_t::INT1_CTRL_REG_GYRO_XL);

  // Set the angle threshold and duration for the interrupt
  myIMU.setAWTThreshold(LSM6DS3::AWT_THRESHOLD_85_DEG);
  myIMU.setAWTDuration(LSM6DS3::AWT_DURATION_4_SAMPLES);

  // Enable the interrupt
  myIMU.enableAWT();

  Serial.println("LSM6DS3 initialized. Waiting for tilt...");
}

void loop() {
  if (myIMU.readInterrupt(Sensor_Int1)) {
    Serial.println("Tilt detected! Angle exceeded 85 degrees.");
    // You can add additional actions here, such as resetting the sensor or performing specific tasks
    // based on the tilt detection.
  }

  delay(100); // Delay to reduce Serial output rate
}

In this example, the setAWTThreshold function sets the threshold angle for the Absolute Wrist Tilt (AWT) interrupt to 85 degrees, and the setAWTDuration function sets the number of samples required to maintain the threshold before triggering the interrupt. Adjust these values according to your specific requirements.

Also, make sure to refer to the LSM6DS3 datasheet and the SparkFun LSM6DS3 library documentation for more detailed information on how to configure the sensor
Basically it’s this way…

// AWT Config
myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL1_XL, 0x60); // Set accelerometer to 416Hz in low-noise mode
myIMU.writeRegister(LSM6DS3_ACC_GYRO_TILT_CFG, 0x38);  // Enable tilt detection on X and Y axes
myIMU.writeRegister(LSM6DS3_ACC_GYRO_INT_DUR2, 0x04);   // Set duration of tilt event
myIMU.writeRegister(LSM6DS3_ACC_GYRO_WAKE_UP_THS, 0x00); // Disable single tap interrupt
myIMU.writeRegister(LSM6DS3_ACC_GYRO_MD1_CFG, 0x04);     // Enable tilt detection interrupt on INT1

HTH
GL :slight_smile: PJ
I have a example somewhere like the IMU park demo? if I find it I’ll post it here.Here is a great link , that helped me a while back.
How_to_Use_a_Three-Axis_Accelerometer_for_Tilt_Sensing-DFRobot

Thank you so much for the reply- this is exactly what I need! But, the registers and functions used, ex. LSM6DS3_ACC_GYRO_TILT_CFG, enableAWT() are not declared in the LSM6DS3 library I have installed or the SparkFun one. [If I’m not wrong the first one was taken from SparkFun too]
Is there any other library I need to access these functions?

Hi there,
I think so, sparkfun maybe from the LSM6DS3TR, There’s are several LIB’s for it, Tilt. Also it can be derived from the Accelerometer and an The tangent equation as well.
The motion demo with position on here, Shows that turning up the sensitivity and lower the scale can be enough to sense any tilt at all.
HTH
GL :slight_smile: PJ
They are all derived from this one AFAIK;