10-06-2019 03:19 PM
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.
10-07-2019 12:51 PM
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
10-07-2019 09:25 PM
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
10-08-2019 11:17 AM - edited 10-08-2019 11:17 AM
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
10-08-2019 09:29 PM
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...