How to capture gestures and steps with BMI270 using interrupts?

I am trying to capture steps and wrist wakeup (https://github.com/zephyrproject-rtos/zephyr/blob/4c6b1e5a65e752c881183ddb4687fa0231b11cc3/drivers/sensor/bosch/bmi270/bmi270.h#L112) but I don't see how to do this in the sample document. I thought there would be some way to set the call back for the interrupts like you can do with ble.

I read this post which was very helpful (+) BMI270 interrupts seem not to be usable in nRF Connect SDK v2.2.0 with zephyr - Nordic Q&A - Nordic DevZone - Nordic DevZone (nordicsemi.com), but why aren't the interrupts in the overlay? Shouldn't they be handled there?

I have this working:

const struct device *const accl_dev = DEVICE_DT_GET_ONE(bosch_bmi270);
struct sensor_value acc[3], gyr[3];
struct sensor_value full_scale, sampling_freq, oversampling;

int accelerometer_manager_init(void) 
{
    LOG_DBG("Initializing accelerometer manager");
	if (!device_is_ready(accl_dev)) {
		LOG_ERR("Device %s is not ready\n", accl_dev->name);
		return 0;
	}

    full_scale.val1 = 2;            /* G */
	full_scale.val2 = 0;
	sampling_freq.val1 = 100;       /* Hz. Performance mode */
	sampling_freq.val2 = 0;
	oversampling.val1 = 1;          /* Normal mode */
	oversampling.val2 = 0;

	sensor_attr_set(accl_dev, SENSOR_CHAN_ACCEL_XYZ, SENSOR_ATTR_FULL_SCALE, &full_scale);
	sensor_attr_set(accl_dev, SENSOR_CHAN_ACCEL_XYZ, SENSOR_ATTR_OVERSAMPLING, &oversampling);
	/* Set sampling frequency last as this also sets the appropriate
	 * power mode. If already sampling, change to 0.0Hz before changing
	 * other attributes
	 */
	sensor_attr_set(accl_dev, SENSOR_CHAN_ACCEL_XYZ, SENSOR_ATTR_SAMPLING_FREQUENCY,&sampling_freq);

	/* Setting scale in degrees/s to match the sensor scale */
	full_scale.val1 = 500;          /* dps */
	full_scale.val2 = 0;
	sampling_freq.val1 = 100;       /* Hz. Performance mode */
	sampling_freq.val2 = 0;
	oversampling.val1 = 1;          /* Normal mode */
	oversampling.val2 = 0;

	sensor_attr_set(accl_dev, SENSOR_CHAN_GYRO_XYZ, SENSOR_ATTR_FULL_SCALE, &full_scale);
	sensor_attr_set(accl_dev, SENSOR_CHAN_GYRO_XYZ, SENSOR_ATTR_OVERSAMPLING, &oversampling);
	/* Set sampling frequency last as this also sets the appropriate
	 * power mode. If already sampling, change sampling frequency to
	 * 0.0Hz before changing other attributes
	 */
	sensor_attr_set(accl_dev, SENSOR_CHAN_GYRO_XYZ,SENSOR_ATTR_SAMPLING_FREQUENCY,&sampling_freq);

    return 0;
}

And I can get data by polling this:

void accelerometer_manager_fetch(void) 
{

	sensor_sample_fetch(accl_dev);

	sensor_channel_get(accl_dev, SENSOR_CHAN_ACCEL_XYZ, acc);
	sensor_channel_get(accl_dev, SENSOR_CHAN_GYRO_XYZ, gyr);

    LOG_DBG("AX: %d.%06d; AY: %d.%06d; AZ: %d.%06d; "
		        "GX: %d.%06d; GY: %d.%06d; GZ: %d.%06d;",
	            acc[0].val1, acc[0].val2,
		        acc[1].val1, acc[1].val2,
		        acc[2].val1, acc[2].val2,
		        gyr[0].val1, gyr[0].val2,
		        gyr[1].val1, gyr[1].val2,
		        gyr[2].val1, gyr[2].val2);

}

But getting messages from the senor on a detected activity through a callback was what I was hoping for.

I tried adding this before the return in the first code block:

    struct sensor_trigger trig;
    trig.type = SENSOR_TRIG_DATA_READY;
    trig.chan = SENSOR_CHAN_ACCEL_XYZ;

    if (sensor_trigger_set(accl_dev, &trig, accelerometer_mangager_trigger_handler) < 0) {
        printk("Could not set trigger\n");
        return;
    }

and this above the init:

void accelerometer_mangager_trigger_handler(const struct device *dev, struct sensor_trigger *trigger)
{
    struct sensor_value accel[3];
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_XYZ, accel);
    printk("Accel X: %d.%06d, Y: %d.%06d, Z: %d.%06d\n",
           accel[0].val1, accel[0].val2,
           accel[1].val1, accel[1].val2,
           accel[2].val1, accel[2].val2);
}

but get this in the console:

Could not set trigger

I have this in my overlay:

    bmi270@68 {
            compatible = "bosch,bmi270";
            irq-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>, <&gpio1 15 GPIO_ACTIVE_HIGH>;
            reg = <0x68>;
    };	

I can fetch the data, but I want to use the interrupt and identify gestures and count steps.

I got it functioning with this in the prj.conf:

CONFIG_BMI270_TRIGGER_GLOBAL_THREAD=y

and this in the code:

    trig.type = SENSOR_TRIG_DATA_READY;    //this works and spits tons of data
	//trig.type = SENSOR_TRIG_DELTA;			//didn't initialize the trigger, caused an eeror on the set command
	//trig.type = SENSOR_TRIG_MOTION;			//passed the set command but not triggering
    trig.chan = SENSOR_CHAN_ACCEL_XYZ;

	int rc;
	rc = sensor_trigger_set(accl_dev, &trig, accelerometer_mangager_trigger_handler);
    if (rc < 0) {
        LOG_ERR("Could not set accelerometer trigger");
        return;
    }


But I still don't understand how to access a trigger or triggers for:

Activity change recognition:

  • Still
  • Walking
  • Running

Wrist gestures:

  • Push arm down
  • Pivot up
  • Wrist shake jiggle
  • Flick in
  • Flick out
  • Wrist wear wake up

BMI270 Context

  • Step counter and Step detector (Pedometer)
  • Activity change recognition
  • Still
  • Walking
  • Running

All supported by the sensor:

boschsensortec/BMI270_SensorAPI: This respository contains Bosch Sensortec's BMI270 inertial measurement unit's sensor API. To report issues, go to https://community.bosch-sensortec.com/t5/Bosch-Sensortec-Community/ct-p/bst_community (github.com)


They seem to be supported in Zephyr:
zephyr/drivers/sensor/bosch/bmi270/bmi270_trigger.c at 23eca6362dce63e52fcf6825f772e7ee7ae5226e · zephyrproject-rtos/zephyr (github.com)

Parents Reply Children
No Data
Related