04-23-2020 10:29 AM
Hi everyone,
I am trying to integrate the BSXlite with the BMX160. Before the integration, I used BMI160_driver as well as the BMM150 sensor API and the THIS guide of how to use an auxiliary sensor or magnetometer with the BMI160.
So far so good, I am able to read meaningful results from all the three sensors. Then I started the integration with the BSXlite. I followed the BSXlite Library Integration Guideline provided with the software but I am not able to read offsets or Euler angles...
1. Included all the header files as well as the precompiled static library .a (libalgobsx3_CortexM4F in my case as I am using the nRF52)
2. Create four arrays holding the accel/gyro/mag settings for the library as well as usecase_config
3. Initialize the BSX & set the working mode
//Initialize BSX
void BSX_init() {
s_input.accelspec = str_accelspec;
s_input.gyrospec = str_gyrospec;
s_input.magspec = str_magspec;
s_input.usecase = str_usecaseconfig;
init_status = bsx_init(&s_input);
if (init_status == BSX_STATE_OK) {
NRF_LOG_INFO("BSX Initialized\n");
} else {
NRF_LOG_INFO("BSX Initialization Failed...\n");
}
s_workingmodes.opMode = BSX_WORKINGMODE_NDOF_GEORV_FMC_OFF; // na - Assign the working mode to the opMode member
bsx_set_workingmode(&s_workingmodes); // na - Set the working mode
bsx_get_hwdependency(s_workingmodes, &HWsensorSwitchList); // na - Get the list of sensors required for the set working mode
}
4. Finally, I fed the raw data to the library - Here is the problem
When I try to read for example the accel offset or the accel offset in mg the results are all 0s
When I try to read Euler angles the results are garbage and does not update every one second (I have a delay of 1s to get data on the serial monitor)
static void read_sensor_data() {
m_xfer_done = false;
libraryinput_t libraryInput_ts; // na - variable to hold sensors data and data stamps
// na - Read raw data frm accel, gyro, mag
bmi160_get_sensor_data((BMI160_ACCEL_SEL | BMI160_GYRO_SEL | BMI160_TIME_SEL), &s_accel, &s_gyro, &sensor);
bmi160_read_aux_data_auto_mode(mag_data, &sensor);
bmm150_aux_mag_data(mag_data, &bmm150);
// na - fed the raw data to the library
// na - accel data and time stamp
libraryInput_ts.acc.data.x = s_accel.x;
libraryInput_ts.acc.data.y = s_accel.y;
libraryInput_ts.acc.data.z = s_accel.z;
libraryInput_ts.acc.time_stamp = s_accel.sensortime; // na - you have to pass the timestamp, otherwise it won't work
// na - gyro data and time stamp
libraryInput_ts.gyro.data.x = s_gyro.x;
libraryInput_ts.gyro.data.y = s_gyro.y;
libraryInput_ts.gyro.data.z = s_gyro.z;
libraryInput_ts.gyro.time_stamp = s_gyro.sensortime;
// na - mag data and time stamp
libraryInput_ts.mag.data.x = bmm150.data.x;
libraryInput_ts.mag.data.y = bmm150.data.y;
libraryInput_ts.mag.data.z = bmm150.data.z;
libraryInput_ts.mag.time_stamp = s_accel.sensortime;
bsx_dostep(&libraryInput_ts);
ts_dataxyzf32 accRawData, gyroRawData_rps, magRawRata;
ts_dataxyzf32 accCorData;
ts_dataxyzf32 accOffSet;
ts_dataxyzs32 accOffSetMG;
ts_dataquatf32 orientQuat;
ts_dataeulerf32 eulerDataRad;
bsx_get_accoffset(&accOffSet); // na - Get the acc offset
NRF_LOG_INFO("ACC_off X: " NRF_LOG_FLOAT_MARKER "\r", NRF_LOG_FLOAT(accOffSet.x)); // na - print acc offset X value
NRF_LOG_INFO("ACC_off Y: " NRF_LOG_FLOAT_MARKER "\r", NRF_LOG_FLOAT(accOffSet.y)); // na - print acc offset Y value
NRF_LOG_INFO("ACC_off Z: " NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(accOffSet.z)); // na - print acc offset Z value
bsx_get_accoffsets_mg(&accOffSetMG); // na - Get the acc offset in mg
NRF_LOG_INFO("ACC_off_mg X: %d" ,accOffSet.x); // na - print acc offset X value in mg
NRF_LOG_INFO("ACC_off_mg Y: %d" ,accOffSet.y); // na - print acc offset Y value in mg
NRF_LOG_INFO("ACC_off_mg Z: %d" ,accOffSet.z); // na - print acc offset Z value in mg
bsx_get_orientdata_euler_rad(&eulerDataRad); // na - Euler angles (x=pitch , y=yaw , z=roll)
NRF_LOG_INFO("Pitch X: " NRF_LOG_FLOAT_MARKER "\r", NRF_LOG_FLOAT(eulerDataRad.p)); // na - print pitch X value in rad
NRF_LOG_INFO("Yaw Y: " NRF_LOG_FLOAT_MARKER "\r", NRF_LOG_FLOAT(eulerDataRad.y)); // na - print yaw Y value in rad
NRF_LOG_INFO("Roll Z: " NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(eulerDataRad.r)); // na - print roll Z value in rad
NRF_LOG_INFO("Time:%d , AccelX:%d , AccelY:%d , AccelZ:%d", s_accel.sensortime, s_accel.x, s_accel.y, s_accel.z);
NRF_LOG_INFO("Time:%d , GyroX:%d , GyroY:%d , GyroZ:%d", s_gyro.sensortime, s_gyro.x, s_gyro.y, s_gyro.z);
NRF_LOG_INFO("Time:%d , MagX:%d , MagY:%d , MagZ:%d", s_accel.sensortime, bmm150.data.x, bmm150.data.y, bmm150.data.z);
}
These are the results. Also are you can see the time stamp for accel and gyro is the same. I this normal?
Lastly, these are the setting for the BMI160 and BMM150
sensor.accel_cfg.odr = BMI160_ACCEL_ODR_100HZ;
sensor.accel_cfg.range = BMI160_ACCEL_RANGE_2G;
sensor.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
sensor.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
sensor.gyro_cfg.odr = BMI160_GYRO_ODR_100HZ;
sensor.gyro_cfg.range = BMI160_GYRO_RANGE_500_DPS;
sensor.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
sensor.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
rslt = bmi160_set_sens_conf(&sensor);
APP_ERROR_CHECK(rslt);
bmm150.settings.preset_mode = BMM150_PRESETMODE_REGULAR;
rslt = bmm150_set_presetmode(&bmm150);
APP_ERROR_CHECK(rslt);
bmm150.settings.pwr_mode = BMM150_FORCED_MODE;
rslt = bmm150_set_op_mode(&bmm150);
sensor.aux_cfg.aux_odr = 6; //8
bmi160_config_aux_mode(&sensor);
bmi160_set_aux_auto_mode(&aux_addr, &sensor);
I know that something is missing but I cannot figure out what is it...
Thanks in advance
Nick
04-25-2020 03:06 AM
Here is one working example of BSX lite integration on MCU side.
You can take reference of that example.
One more hint: magnetic sensor data rate supported in BSX lite is only 25Hz. In your code, you use same as accel time stamp as input time stamp of magnetic sensor which is not correct.
04-27-2020 03:57 PM
Hi Vincent
Thank you for your support. I am coming with feedback and some more questions.
Following the example you provide me I am now able to read correct data from all axes, also I performed calibration (reaching status 3 to all sensors). After calibration, the offset values were not 0 anymore. Furthermore, I printed the raw data and the data after the calibration and I confirm that readings are fine with adequate accuracy. Also, I printed the Euler angles and they are correct as well. Here a screenshot with the data.
However, I have some questions if you could to answer
1. When I rotate the sensor, yaw changes instantly but there is a huge delay on pitch and roll. For example, when I pitch or roll the sensor from zero to 90 degrees it needs around 5-6 seconds to reach the 90degrees on the serial monitor (it raises gradually). It is like it cannot respond immediately to rapid changes. This is not happening on yaw (it is responding immediately)
2. You said that the magnetic sensor data rate supported in BSX lite is only 25Hz (40ms). Indeed, looking at the example you provide the mag_sample_interval is 25Hz. However, the bsxlite_odr = 100Hz (10ms). This is what I do not understand... The frequency that you're calling the bsx_dostep() (100Hz) is four times faster than the sampling rate of the magnetometer (25Hz)... I cannot understand how this works... I mean, bsx_dostep() will read the same mag value before I read mag value again?
3. When you update libraryInput_ts with sensor data, some of the data have a negative sign (such as -acc_y, -gyr_y, -mag_x, -mag_z ). Why are you doing this? Should I take care of it?
4. There are functions such as bsx_get_gyrooffset_dps() , bsx_get_gyrorawdata_dps, bsx_get_gyrocordata_dps where the compiler return the error of undefined reference. For all these functions returning that kind error mean that they cannot be used with the lite version?
Sorry for asking so many questions 🙂
Thanks in advance
Nick
05-04-2020 07:48 PM
Could someone from the moderators answer the questions?