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)