Hi
I've been able to get the BMX160 setup to update the Acc & Mag at 50Hz.
I followed the setup in the BMX160 datasheet, Table 16. Only difference is the ODR = 0x07 and REPXY and REPZ are set for to the high accuracy preset.
I have enabled Data Ready on INT1 pin.
When I receive an interrupt from INT1, I check the STATUS (0x1B) register and can confirm that both drdy_acc and drdy_mag are set (value=0xB0).
I then do a block ready from DATA_0 to DATA_19 and confirm that the Acc data is still correct.
However the Mag data does not change. I get an initial non-zero measurement, but then nothing changes further.
Why is the Mag data not changing?
Is there some setting I'm missing in the Mag setup?
Thanks
Solved! Go to Solution.
Did you find this article already ?
There is an important note:
/* It is important that the last write to the BMM150 sets the forced mode.
* This is because the BMI160 writes the last value to the auxiliary sensor
* after every read */
bmm.settings.pwr_mode = BMM150_FORCED_MODE;
rslt = bmm150_set_op_mode(&bmm);
@rdehart wrote:
Hi
I've been able to get the BMX160 setup to update the Acc & Mag at 50Hz.
Only difference is the ODR = 0x07 and REPXY and REPZ are set for to the high accuracy preset.
Note that High accuracy preset takes a longer time to sample and maximum datarate is 20Hz in that mode. I recommend to use the "Enhanced regular" preset if you need 50Hz data
Thanks for the tip o_o
Unfortunately I had no success setting the Magenetometer to "Enhanced Regular", "Regular" or "Low Power" presets.
Here is my full initialisation of the sensor.
Any thoughts?
// --------------- Init BMX160 ---------------------
bmi.id = BMI160_I2C_ADDR;
bmi.interface = BMI160_I2C_INTF;
bmi.read = I2C_0_readDataBlock;
bmi.write = performDimWrite;
bmi.delay_ms = delay_miliSec;
bmm.dev_id = BMM150_DEFAULT_I2C_ADDRESS;
bmm.intf = BMM150_I2C_INTF;
bmm.read = bmm150_aux_read;
bmm.write = bmm150_aux_write;
bmm.delay_ms = delay_miliSec;
rslt_ = bmi160_init(&bmi);
printf("bmi160_init:%i\r\n", rslt_);
bmi.aux_cfg.aux_sensor_enable = BMI160_ENABLE;
bmi.aux_cfg.aux_i2c_addr = bmm.dev_id;
bmi.aux_cfg.manual_enable = BMI160_ENABLE;
bmi.aux_cfg.aux_rd_burst_len = BMI160_AUX_READ_LEN_3;
rslt_ = bmi160_aux_init(&bmi);
printf("bmi160_aux_init:%i\r\n", rslt_);
rslt_ = bmm150_init(&bmm);
printf("bmm150_init:%i\r\n", rslt_);
//// --------------- Acc & Gryo ---------------------
//// Configure accel and gyro sensors in normal mode
bmi.accel_cfg.odr = BMI160_ACCEL_ODR_50HZ;
bmi.accel_cfg.range = BMI160_ACCEL_RANGE_4G;
bmi.accel_cfg.bw = BMI160_ACCEL_BW_OSR4_AVG1;
bmi.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
bmi.gyro_cfg.odr = BMI160_GYRO_ODR_50HZ;
bmi.gyro_cfg.range = BMI160_GYRO_RANGE_125_DPS;
bmi.gyro_cfg.bw = BMI160_GYRO_BW_OSR4_MODE;
bmi.gyro_cfg.power = BMI160_GYRO_SUSPEND_MODE;
rslt_ = bmi160_set_sens_conf(&bmi);
printf("bmi160_set_sens_conf:%i\r\n", rslt_);
// Configure sensor interrupt (Data Ready)
/* Select the Interrupt channel/pin */
bmi_int_config.int_channel = BMI160_INT_CHANNEL_1;// Interrupt channel/pin 1
/* Select the Interrupt type */
bmi_int_config.int_type = BMI160_ACC_GYRO_DATA_RDY_INT;// Choosing Data Readay interrupt
/* Select the interrupt channel/pin settings */
bmi_int_config.int_pin_settg.output_en = BMI160_ENABLE;// Enabling interrupt pins to act as output pin
bmi_int_config.int_pin_settg.output_mode = BMI160_DISABLE;// Choosing push-pull mode for interrupt pin
bmi_int_config.int_pin_settg.output_type = BMI160_ENABLE;// Choosing active High output
bmi_int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;// Choosing level triggered output
bmi_int_config.int_pin_settg.input_en = BMI160_DISABLE;// Disabling interrupt pin to act as input
bmi_int_config.int_pin_settg.latch_dur =BMI160_LATCH_DUR_NONE;// non-latched output
/* Set the Data Ready interrupt */
rslt_ = bmi160_set_int_config(&bmi_int_config, &bmi); /* sensor is an instance of the structure bmi160_dev */
printf("bmi160_set_int_config:%i\r\n", rslt_);
// Configure sensor interrupt (Tap)
//printf("Init:Tap\r\n");
/* Select the Interrupt channel/pin */
bmi_int_config.int_channel = BMI160_INT_CHANNEL_2;// Interrupt channel/pin 2
/* Select the Interrupt type: Tap */
bmi_int_config.int_type = BMI160_ACC_SINGLE_TAP_INT;// Choosing Step Detector interrupt
/* Select the interrupt channel/pin settings */
bmi_int_config.int_pin_settg.output_en = BMI160_ENABLE;// Enabling interrupt pins to act as output pin
bmi_int_config.int_pin_settg.output_mode = BMI160_DISABLE;// Choosing push-pull mode for interrupt pin
bmi_int_config.int_pin_settg.output_type = BMI160_ENABLE;// Choosing active High output
bmi_int_config.int_pin_settg.edge_ctrl = BMI160_ENABLE;// Choosing level triggered output
bmi_int_config.int_pin_settg.input_en = BMI160_DISABLE;// Disabling interrupt pin to act as input
bmi_int_config.int_pin_settg.latch_dur = BMI160_LATCH_DUR_NONE;// non-latched output
/* Select the Step Detector interrupt parameters, Kindly use the recommended settings for step detector */
bmi_int_config.int_type_cfg.acc_tap_int.tap_en = BMI160_ENABLE;// 1-enable, 0-disable the detector
bmi_int_config.int_type_cfg.acc_tap_int.tap_data_src=BMI160_ENABLE; // use pre-filter
bmi_int_config.int_type_cfg.acc_tap_int.tap_dur = 0b001;
bmi_int_config.int_type_cfg.acc_tap_int.tap_quiet = BMI160_DISABLE; // 30/20ms
bmi_int_config.int_type_cfg.acc_tap_int.tap_shock = BMI160_DISABLE; // 50/75ms
bmi_int_config.int_type_cfg.acc_tap_int.tap_thr = 0b11111; // 125mg/2 = 62.5mg per bit (4g range)
// Setup INT_TAP[0] correctly
rslt_ = 0b00000111;
performDimWrite(BMI160_I2C_ADDR, BMI160_INT_TAP_0_ADDR, &rslt_, 1 );
// Setup INT_TAP[1] correctly
rslt_ = 0b00001111;
performDimWrite(BMI160_I2C_ADDR, BMI160_INT_TAP_1_ADDR, &rslt_, 1 );
/* Set the Step Detector interrupt */
rslt_ = bmi160_set_int_config(&bmi_int_config, &bmi); /* sensor is an instance of the structure bmi160_dev */
printf("bmi160_set_int_config:%i\r\n", rslt_);
// correct INT channel for Tap. Bug in library
// disable int1_s_tap
I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_MAP_0_ADDR , &rslt_, 1);
rslt_ = rslt_ & 0b11011111;
performDimWrite(BMI160_I2C_ADDR, BMI160_INT_MAP_0_ADDR, &rslt_, 1 );
// enable int2_s_tap
I2C_0_readDataBlock(BMI160_I2C_ADDR, BMI160_INT_MAP_2_ADDR , &rslt_, 1);
rslt_ = rslt_ | 0b00100000;
performDimWrite(BMI160_I2C_ADDR, BMI160_INT_MAP_2_ADDR, &rslt_, 1 );
// --------------- Mag ---------------------
//printf("Init:Mag\r\n");
//// from <a href="https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BMX160-magnetometer-problem/td-p/7628/page/2" target="_blank">https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BMX160-magnetometer-problem/td-p/7628/page/2</a>
// from datasheet p.25
rslt_ = 0x19; performDimWrite(BMI160_I2C_ADDR, BMI160_COMMAND_REG_ADDR, &rslt_, 1 );
_delay_ms(2);
rslt_ = 0x80; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_1_ADDR, &rslt_, 1 );
rslt_ = 0x01; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_3_ADDR, &rslt_, 1 );
rslt_ = 0x4B; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_2_ADDR, &rslt_, 1 );
rslt_ = 0x04; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_3_ADDR, &rslt_, 1 );
rslt_ = 0x51; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_2_ADDR, &rslt_, 1 );
rslt_ = 0x52; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_3_ADDR, &rslt_, 1 );
rslt_ = 0x52; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_2_ADDR, &rslt_, 1 );
rslt_ = 0x02; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_3_ADDR, &rslt_, 1 );
rslt_ = 0x4C; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_2_ADDR, &rslt_, 1 );
rslt_ = 0x42; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_1_ADDR, &rslt_, 1 );
rslt_ = 0x07; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_ODR_ADDR, &rslt_, 1 );
rslt_ = 0x00; performDimWrite(BMI160_I2C_ADDR, BMI160_AUX_IF_1_ADDR, &rslt_, 1 );
rslt_ = 0x19; performDimWrite(BMI160_I2C_ADDR, BMI160_COMMAND_REG_ADDR, &rslt_, 1 );
_delay_ms(2);
bmm.settings.pwr_mode = BMM150_FORCED_MODE;
rslt_ = bmm150_set_op_mode(&bmm);
printf("bmm150_set_op_mode:%i\r\n", rslt_);
and here is my read code:
I2C_0_readDataBlock( BMI160_I2C_ADDR, BMI160_AUX_DATA_ADDR, &raw_data, 20 );
// Convert raw Acc data to "g"
*accX = ACC_CONVERT_TO_G * (float)( raw_data[7] );
*accY = ACC_CONVERT_TO_G * (float)( raw_data[8] );
*accZ = ACC_CONVERT_TO_G * (float)( raw_data[9] );
// Convert raw Mag data to "gauss"
*magX = MAG_CONVERT_TO_GAUSS * (float)( raw_data[0] );
*magY = MAG_CONVERT_TO_GAUSS * (float)( raw_data[1] );
*magZ = MAG_CONVERT_TO_GAUSS * (float)( raw_data[2] );
Thanks
As general rule we try to help our customer to implement the Sensor API, rather than rewriting your own with direct register access. I am not quite sure why your magnetometer data configuration is a hexadecimal blob rather than using the API functions...
Anyhow, you seem to be missing the key function call to start the auxiliary sensor automatic sampling:
From the sample code on our GitHub:
uint8_t bmm150_data_start = BMM150_DATA_X_LSB;
bmi.aux_cfg.aux_odr = BMI160_AUX_ODR_100HZ;
rslt = bmi160_set_aux_auto_mode(&bmm150_data_start, &bmi);
From the forum thread that you pointed in your comment:
bmi.aux_cfg.aux_odr = 8;
bmi160_config_aux_mode(&bmi);
bmi160_set_aux_auto_mode(&aux_addr, &bmi);
One thing that I am curious about is this bit:
// correct INT channel for Tap. Bug in library
// disable int1_s_tap
Can you explain the bug you found in our sensor API ?
o_o
Hi o_o
I added your suggeted code after the datasheet's raw implementation:
uint8_t bmm150_data_start = BMM150_DATA_X_LSB;
bmi.aux_cfg.aux_odr = BMI160_AUX_ODR_100HZ;
rslt = bmi160_set_aux_auto_mode(&bmm150_data_start, &bmi);
The result was that now the AUX data values reads as 0 on all axes. (previously they had a value). Also, the drdy_mag flag was nog being set.
So it seems to be getting "worse".
I understand that you prefer only to support the API. I reverted to the BMX160 datasheet as the API implementation was not producing favourable results.
So I am happy to switch back to the API implementation.
After the TAP detection setup, I have changed the raw hex writing implementation with the following (see the comment about the thread reference to pick up where the code changes)
// --------------- Mag ---------------------
//printf("Init:Mag\r\n");
//// from <a href="https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BMX160-magnetometer-problem/td-p/7628/page/2" target="_blank">https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BMX160-magnetometer-problem/td-p/7628/page/2</a>
bmm.settings.preset_mode = BMM150_PRESETMODE_REGULAR;
rslt_ = bmm150_set_presetmode(&bmm);
printf("bmm150_set_presetmode:%i\r\n", rslt_);
bmm.settings.pwr_mode = BMM150_FORCED_MODE;
rslt_ = bmm150_set_op_mode(&bmm);
printf("bmm150_set_op_mode:%i\r\n", rslt_);
bmi.aux_cfg.aux_odr = BMI160_AUX_ODR_50HZ; // 7; /* Represents polling rate in 50 Hz*/
rslt_ = bmi160_config_aux_mode(&bmi);
printf("bmi160_config_aux_mode:%i\r\n", rslt_);
// set aux/mag to auto mode
rslt_ = bmi160_set_aux_auto_mode(&aux_addr, &bmi);
printf("bmi160_set_aux_auto_mode:%i\r\n", rslt_);
/* Reading data from BMI160 data registers */
rslt_ = bmi160_read_aux_data_auto_mode(mag_data, &bmi);
printf("bmi160_read_aux_data_auto_mode:%i\r\n", rslt_);
The result is the same as before.
No drdy_mag flag being set.
Data reads as 0 on all axes.
I seem to be working backwards 😮
Any thoughts on why I'm getting no data now?
I am under the impression that I am missing something fundamental.
Am I initialising the sensor in the correct order?
I tried to init the DRDY and TAP settings after the MAG init, but no change? Does this order matter?
I don't want to cloudy the waters with other issues, so I have created this separate issue regarding the possible bug in the API.
https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/Possible-bug-in-BMX160-API-for-TAP-setti...