Christian Dupaty 03/2021 Library and demo for BMM150 see datasheet here : https://www.bosch-sensortec.com/products/motion-sensors/magnetometers-bmm150/ Adaptation of BOSCH driver https://github.com/BoschSensortec/BMM150-Sensor-API for ARM MBED and tested on NUCLEO-L073RZ and GEOMAGNETIC CLICK https://www.mikroe.com/geomagnetic-click
Dependents: BMM150_HelloWorld2
bmm150.cpp
00001 /* 00002 Christian Dupaty 03/2021 00003 Library and demo for BMM150 see datasheet here : https://www.bosch-sensortec.com/products/motion-sensors/magnetometers-bmm150/ 00004 Adaptation of BOSCH driver https://github.com/BoschSensortec/BMM150-Sensor-API 00005 for ARM MBED and tested on NUCLEO-L073RZ and GEOMAGNETIC CLICK 00006 https://www.mikroe.com/geomagnetic-click 00007 */ 00008 00009 #include "mbed.h" 00010 #include "bmm150.h" 00011 00012 BMM150::BMM150(PinName sda, PinName scl) 00013 { 00014 //I2C *i2c; 00015 i2c = new I2C(sda, scl); 00016 //100KHz, as specified by the datasheet. 00017 i2c ->frequency(100000); 00018 } 00019 00020 int8_t BMM150::initialize(void) 00021 { 00022 // i2c.begin(); 00023 00024 /* Power up the sensor from suspend to sleep mode */ 00025 set_op_mode(BMM150_SLEEP_MODE); 00026 wait_ms(BMM150_START_UP_TIME); 00027 00028 /* Check chip ID */ 00029 uint8_t id = i2c_read(BMM150_CHIP_ID_ADDR); 00030 if (id != BMM150_CHIP_ID) { 00031 return BMM150_E_ID_NOT_CONFORM; 00032 } 00033 00034 /* Function to update trim values */ 00035 read_trim_registers(); 00036 00037 /* Setting the power mode as normal */ 00038 set_op_mode(BMM150_NORMAL_MODE); 00039 00040 /* Setting the preset mode as Low power mode 00041 i.e. data rate = 10Hz XY-rep = 1 Z-rep = 2*/ 00042 set_presetmode(BMM150_PRESETMODE_LOWPOWER); 00043 // set_presetmode(BMM150_HIGHACCURACY_REPZ); 00044 00045 return BMM150_OK; 00046 } 00047 00048 void BMM150::read_mag_data() { 00049 int16_t msb_data; 00050 int8_t reg_data[BMM150_XYZR_DATA_LEN] = {0}; 00051 00052 i2c_read(BMM150_DATA_X_LSB, reg_data, BMM150_XYZR_DATA_LEN); 00053 00054 /* Mag X axis data */ 00055 reg_data[0] = BMM150_GET_BITS(reg_data[0], BMM150_DATA_X); 00056 /* Shift the MSB data to left by 5 bits */ 00057 /* Multiply by 32 to get the shift left by 5 value */ 00058 msb_data = ((int16_t)((char)reg_data[1])) * 32; 00059 /* Raw mag X axis data */ 00060 raw_mag_data.raw_datax = (int16_t)(msb_data | reg_data[0]); 00061 /* Mag Y axis data */ 00062 reg_data[2] = BMM150_GET_BITS(reg_data[2], BMM150_DATA_Y); 00063 /* Shift the MSB data to left by 5 bits */ 00064 /* Multiply by 32 to get the shift left by 5 value */ 00065 msb_data = ((int16_t)((char)reg_data[3])) * 32; 00066 /* Raw mag Y axis data */ 00067 raw_mag_data.raw_datay = (int16_t)(msb_data | reg_data[2]); 00068 /* Mag Z axis data */ 00069 reg_data[4] = BMM150_GET_BITS(reg_data[4], BMM150_DATA_Z); 00070 /* Shift the MSB data to left by 7 bits */ 00071 /* Multiply by 128 to get the shift left by 7 value */ 00072 msb_data = ((int16_t)((char)reg_data[5])) * 128; 00073 /* Raw mag Z axis data */ 00074 raw_mag_data.raw_dataz = (int16_t)(msb_data | reg_data[4]); 00075 /* Mag R-HALL data */ 00076 reg_data[6] = BMM150_GET_BITS(reg_data[6], BMM150_DATA_RHALL); 00077 raw_mag_data.raw_data_r = (uint16_t)(((uint16_t)reg_data[7] << 6) | reg_data[6]); 00078 00079 /* Compensated Mag X data in int16_t format */ 00080 mag_data.x = compensate_x(raw_mag_data.raw_datax, raw_mag_data.raw_data_r); 00081 /* Compensated Mag Y data in int16_t format */ 00082 mag_data.y = compensate_y(raw_mag_data.raw_datay, raw_mag_data.raw_data_r); 00083 /* Compensated Mag Z data in int16_t format */ 00084 mag_data.z = compensate_z(raw_mag_data.raw_dataz, raw_mag_data.raw_data_r); 00085 } 00086 00087 /* 00088 @brief This internal API is used to obtain the compensated 00089 magnetometer X axis data(micro-tesla) in int16_t. 00090 */ 00091 int16_t BMM150::compensate_x(int16_t mag_data_x, uint16_t data_rhall) 00092 { 00093 int16_t retval; 00094 uint16_t process_comp_x0 = 0; 00095 int32_t process_comp_x1; 00096 uint16_t process_comp_x2; 00097 int32_t process_comp_x3; 00098 int32_t process_comp_x4; 00099 int32_t process_comp_x5; 00100 int32_t process_comp_x6; 00101 int32_t process_comp_x7; 00102 int32_t process_comp_x8; 00103 int32_t process_comp_x9; 00104 int32_t process_comp_x10; 00105 00106 /* Overflow condition check */ 00107 if (mag_data_x != BMM150_XYAXES_FLIP_OVERFLOW_ADCVAL) { 00108 if (data_rhall != 0) { 00109 /* Availability of valid data*/ 00110 process_comp_x0 = data_rhall; 00111 } else if (trim_data.dig_xyz1 != 0) { 00112 process_comp_x0 = trim_data.dig_xyz1 ; 00113 } else { 00114 process_comp_x0 = 0; 00115 } 00116 if (process_comp_x0 != 0) { 00117 /* Processing compensation equations*/ 00118 process_comp_x1 = ((int32_t)trim_data.dig_xyz1 ) * 16384; 00119 process_comp_x2 = ((uint16_t)(process_comp_x1 / process_comp_x0)) - ((uint16_t)0x4000); 00120 retval = ((int16_t)process_comp_x2); 00121 process_comp_x3 = (((int32_t)retval) * ((int32_t)retval)); 00122 process_comp_x4 = (((int32_t)trim_data.dig_xy2 ) * (process_comp_x3 / 128)); 00123 process_comp_x5 = (int32_t)(((int16_t)trim_data.dig_xy1 ) * 128); 00124 process_comp_x6 = ((int32_t)retval) * process_comp_x5; 00125 process_comp_x7 = (((process_comp_x4 + process_comp_x6) / 512) + ((int32_t)0x100000)); 00126 process_comp_x8 = ((int32_t)(((int16_t)trim_data.dig_x2 ) + ((int16_t)0xA0))); 00127 process_comp_x9 = ((process_comp_x7 * process_comp_x8) / 4096); 00128 process_comp_x10 = ((int32_t)mag_data_x) * process_comp_x9; 00129 retval = ((int16_t)(process_comp_x10 / 8192)); 00130 retval = (retval + (((int16_t)trim_data.dig_x1 ) * 8)) / 16; 00131 } else { 00132 retval = BMM150_OVERFLOW_OUTPUT; 00133 } 00134 } else { 00135 /* Overflow condition */ 00136 retval = BMM150_OVERFLOW_OUTPUT; 00137 } 00138 00139 return retval; 00140 } 00141 00142 /* 00143 @brief This internal API is used to obtain the compensated 00144 magnetometer Y axis data(micro-tesla) in int16_t. 00145 */ 00146 int16_t BMM150::compensate_y(int16_t mag_data_y, uint16_t data_rhall) { 00147 int16_t retval; 00148 uint16_t process_comp_y0 = 0; 00149 int32_t process_comp_y1; 00150 uint16_t process_comp_y2; 00151 int32_t process_comp_y3; 00152 int32_t process_comp_y4; 00153 int32_t process_comp_y5; 00154 int32_t process_comp_y6; 00155 int32_t process_comp_y7; 00156 int32_t process_comp_y8; 00157 int32_t process_comp_y9; 00158 00159 /* Overflow condition check */ 00160 if (mag_data_y != BMM150_XYAXES_FLIP_OVERFLOW_ADCVAL) { 00161 if (data_rhall != 0) { 00162 /* Availability of valid data*/ 00163 process_comp_y0 = data_rhall; 00164 } else if (trim_data.dig_xyz1 != 0) { 00165 process_comp_y0 = trim_data.dig_xyz1 ; 00166 } else { 00167 process_comp_y0 = 0; 00168 } 00169 if (process_comp_y0 != 0) { 00170 /*Processing compensation equations*/ 00171 process_comp_y1 = (((int32_t)trim_data.dig_xyz1 ) * 16384) / process_comp_y0; 00172 process_comp_y2 = ((uint16_t)process_comp_y1) - ((uint16_t)0x4000); 00173 retval = ((int16_t)process_comp_y2); 00174 process_comp_y3 = ((int32_t) retval) * ((int32_t)retval); 00175 process_comp_y4 = ((int32_t)trim_data.dig_xy2 ) * (process_comp_y3 / 128); 00176 process_comp_y5 = ((int32_t)(((int16_t)trim_data.dig_xy1 ) * 128)); 00177 process_comp_y6 = ((process_comp_y4 + (((int32_t)retval) * process_comp_y5)) / 512); 00178 process_comp_y7 = ((int32_t)(((int16_t)trim_data.dig_y2 ) + ((int16_t)0xA0))); 00179 process_comp_y8 = (((process_comp_y6 + ((int32_t)0x100000)) * process_comp_y7) / 4096); 00180 process_comp_y9 = (((int32_t)mag_data_y) * process_comp_y8); 00181 retval = (int16_t)(process_comp_y9 / 8192); 00182 retval = (retval + (((int16_t)trim_data.dig_y1 ) * 8)) / 16; 00183 } else { 00184 retval = BMM150_OVERFLOW_OUTPUT; 00185 } 00186 } else { 00187 /* Overflow condition*/ 00188 retval = BMM150_OVERFLOW_OUTPUT; 00189 } 00190 00191 return retval; 00192 } 00193 00194 /* 00195 @brief This internal API is used to obtain the compensated 00196 magnetometer Z axis data(micro-tesla) in int16_t. 00197 */ 00198 int16_t BMM150::compensate_z(int16_t mag_data_z, uint16_t data_rhall) { 00199 int32_t retval; 00200 int16_t process_comp_z0; 00201 int32_t process_comp_z1; 00202 int32_t process_comp_z2; 00203 int32_t process_comp_z3; 00204 int16_t process_comp_z4; 00205 00206 if (mag_data_z != BMM150_ZAXIS_HALL_OVERFLOW_ADCVAL) { 00207 if ((trim_data.dig_z2 != 0) && (trim_data.dig_z1 != 0) 00208 && (data_rhall != 0) && (trim_data.dig_xyz1 != 0)) { 00209 /*Processing compensation equations*/ 00210 process_comp_z0 = ((int16_t)data_rhall) - ((int16_t) trim_data.dig_xyz1 ); 00211 process_comp_z1 = (((int32_t)trim_data.dig_z3 ) * ((int32_t)(process_comp_z0))) / 4; 00212 process_comp_z2 = (((int32_t)(mag_data_z - trim_data.dig_z4 )) * 32768); 00213 process_comp_z3 = ((int32_t)trim_data.dig_z1 ) * (((int16_t)data_rhall) * 2); 00214 process_comp_z4 = (int16_t)((process_comp_z3 + (32768)) / 65536); 00215 retval = ((process_comp_z2 - process_comp_z1) / (trim_data.dig_z2 + process_comp_z4)); 00216 00217 /* saturate result to +/- 2 micro-tesla */ 00218 if (retval > BMM150_POSITIVE_SATURATION_Z) { 00219 retval = BMM150_POSITIVE_SATURATION_Z; 00220 } else { 00221 if (retval < BMM150_NEGATIVE_SATURATION_Z) { 00222 retval = BMM150_NEGATIVE_SATURATION_Z; 00223 } 00224 } 00225 /* Conversion of LSB to micro-tesla*/ 00226 retval = retval / 16; 00227 } else { 00228 retval = BMM150_OVERFLOW_OUTPUT; 00229 00230 } 00231 } else { 00232 /* Overflow condition*/ 00233 retval = BMM150_OVERFLOW_OUTPUT; 00234 } 00235 00236 return (int16_t)retval; 00237 } 00238 00239 void BMM150::set_presetmode(uint8_t preset_mode) { 00240 switch (preset_mode) { 00241 case BMM150_PRESETMODE_LOWPOWER: 00242 /* Set the data rate x,y,z repetition 00243 for Low Power mode */ 00244 settings.data_rate = BMM150_DATA_RATE_10HZ; 00245 settings.xy_rep = BMM150_LOWPOWER_REPXY; 00246 settings.z_rep = BMM150_LOWPOWER_REPZ; 00247 set_odr_xyz_rep(settings); 00248 break; 00249 case BMM150_PRESETMODE_REGULAR: 00250 /* Set the data rate x,y,z repetition 00251 for Regular mode */ 00252 settings.data_rate = BMM150_DATA_RATE_10HZ; 00253 settings.xy_rep = BMM150_REGULAR_REPXY; 00254 settings.z_rep = BMM150_REGULAR_REPZ; 00255 set_odr_xyz_rep(settings); 00256 break; 00257 case BMM150_PRESETMODE_HIGHACCURACY: 00258 /* Set the data rate x,y,z repetition 00259 for High Accuracy mode */ 00260 settings.data_rate = BMM150_DATA_RATE_20HZ; 00261 settings.xy_rep = BMM150_HIGHACCURACY_REPXY; 00262 settings.z_rep = BMM150_HIGHACCURACY_REPZ; 00263 set_odr_xyz_rep(settings); 00264 break; 00265 case BMM150_PRESETMODE_ENHANCED: 00266 /* Set the data rate x,y,z repetition 00267 for Enhanced Accuracy mode */ 00268 settings.data_rate = BMM150_DATA_RATE_10HZ; 00269 settings.xy_rep = BMM150_ENHANCED_REPXY; 00270 settings.z_rep = BMM150_ENHANCED_REPZ; 00271 set_odr_xyz_rep(settings); 00272 break; 00273 default: 00274 break; 00275 } 00276 } 00277 00278 void BMM150::set_odr_xyz_rep(struct bmm150_settings settings) { 00279 /* Set the ODR */ 00280 set_odr(settings); 00281 /* Set the XY-repetitions number */ 00282 set_xy_rep(settings); 00283 /* Set the Z-repetitions number */ 00284 set_z_rep(settings); 00285 } 00286 00287 void BMM150::set_xy_rep(struct bmm150_settings settings) { 00288 uint8_t rep_xy; 00289 rep_xy = settings.xy_rep ; 00290 i2c_write(BMM150_REP_XY_ADDR, rep_xy); 00291 00292 } 00293 00294 void BMM150::set_z_rep(struct bmm150_settings settings) { 00295 uint8_t rep_z; 00296 rep_z = settings.z_rep ; 00297 i2c_write(BMM150_REP_Z_ADDR, rep_z); 00298 } 00299 00300 00301 void BMM150::soft_reset() 00302 { 00303 uint8_t reg_data; 00304 00305 reg_data = i2c_read(BMM150_POWER_CONTROL_ADDR); 00306 reg_data = reg_data | BMM150_SET_SOFT_RESET; 00307 i2c_write(BMM150_POWER_CONTROL_ADDR, reg_data); 00308 wait_ms(BMM150_SOFT_RESET_wait_ms); 00309 } 00310 00311 00312 void BMM150::set_odr(struct bmm150_settings settings) 00313 { 00314 uint8_t reg_data; 00315 00316 reg_data = i2c_read(BMM150_OP_MODE_ADDR); 00317 /*Set the ODR value */ 00318 reg_data = BMM150_SET_BITS(reg_data, BMM150_ODR, settings.data_rate ); 00319 i2c_write(BMM150_OP_MODE_ADDR, reg_data); 00320 } 00321 00322 void BMM150::i2c_write(short address, short data) 00323 { 00324 char temp[2]; 00325 temp[0]=address; 00326 temp[1]=data; 00327 i2c->write(BMM150_I2C_Address,temp,2); 00328 } 00329 00330 void BMM150::i2c_write(short address) 00331 { 00332 char temp[1]; 00333 temp[0]=address; 00334 i2c->write(BMM150_I2C_Address,temp,1); 00335 } 00336 00337 void BMM150::i2c_read(short address, uint8_t* buffer, short length) 00338 { 00339 i2c_write(address); 00340 i2c->read(BMM150_I2C_Address+1,(char *)buffer,length); 00341 } 00342 00343 00344 void BMM150::i2c_read(short address, int8_t* buffer, short length) 00345 { 00346 i2c_write(address); 00347 i2c->read(BMM150_I2C_Address+1,(char *)buffer,length); 00348 } 00349 00350 uint8_t BMM150::i2c_read(short address) 00351 { 00352 char temp[1]; 00353 i2c_write(address); 00354 i2c->read(BMM150_I2C_Address+1,temp,1); 00355 return temp[0]; 00356 } 00357 00358 00359 // char* BMM150::getErrorText(short errorCode); 00360 // { 00361 // if(ERRORCODE_1_NUM == 1) 00362 // return ERRORCODE_1; 00363 00364 // return "Error not defined."; 00365 // } 00366 00367 void BMM150::set_op_mode(uint8_t pwr_mode) { 00368 /* Select the power mode to set */ 00369 switch (pwr_mode) { 00370 case BMM150_NORMAL_MODE: 00371 /* If the sensor is in suspend mode 00372 put the device to sleep mode */ 00373 suspend_to_sleep_mode(); 00374 /* write the op mode */ 00375 write_op_mode(pwr_mode); 00376 break; 00377 case BMM150_FORCED_MODE: 00378 /* If the sensor is in suspend mode 00379 put the device to sleep mode */ 00380 suspend_to_sleep_mode(); 00381 /* write the op mode */ 00382 write_op_mode(pwr_mode); 00383 break; 00384 case BMM150_SLEEP_MODE: 00385 /* If the sensor is in suspend mode 00386 put the device to sleep mode */ 00387 suspend_to_sleep_mode(); 00388 /* write the op mode */ 00389 write_op_mode(pwr_mode); 00390 break; 00391 case BMM150_SUSPEND_MODE: 00392 /* Set the power control bit to zero */ 00393 set_power_control_bit(BMM150_POWER_CNTRL_DISABLE); 00394 break; 00395 default: 00396 break; 00397 } 00398 } 00399 00400 void BMM150::suspend_to_sleep_mode(void) { 00401 set_power_control_bit(BMM150_POWER_CNTRL_ENABLE); 00402 /* Start-up time wait_ms of 3ms*/ 00403 wait_ms(3); 00404 } 00405 00406 00407 void BMM150::read_trim_registers() { 00408 uint8_t trim_x1y1[2] = {0}; 00409 uint8_t trim_xyz_data[4] = {0}; 00410 uint8_t trim_xy1xy2[10] = {0}; 00411 uint16_t temp_msb = 0; 00412 00413 /* Trim register value is read */ 00414 i2c_read(BMM150_DIG_X1, trim_x1y1, 2); 00415 i2c_read(BMM150_DIG_Z4_LSB, trim_xyz_data, 4); 00416 i2c_read(BMM150_DIG_Z2_LSB, trim_xy1xy2, 10); 00417 /* Trim data which is read is updated 00418 in the device structure */ 00419 trim_data.dig_x1 = (char)trim_x1y1[0]; 00420 trim_data.dig_y1 = (char)trim_x1y1[1]; 00421 trim_data.dig_x2 = (char)trim_xyz_data[2]; 00422 trim_data.dig_y2 = (char)trim_xyz_data[3]; 00423 temp_msb = ((uint16_t)trim_xy1xy2[3]) << 8; 00424 trim_data.dig_z1 = (uint16_t)(temp_msb | trim_xy1xy2[2]); 00425 temp_msb = ((uint16_t)trim_xy1xy2[1]) << 8; 00426 trim_data.dig_z2 = (int16_t)(temp_msb | trim_xy1xy2[0]); 00427 temp_msb = ((uint16_t)trim_xy1xy2[7]) << 8; 00428 trim_data.dig_z3 = (int16_t)(temp_msb | trim_xy1xy2[6]); 00429 temp_msb = ((uint16_t)trim_xyz_data[1]) << 8; 00430 trim_data.dig_z4 = (int16_t)(temp_msb | trim_xyz_data[0]); 00431 trim_data.dig_xy1 = trim_xy1xy2[9]; 00432 trim_data.dig_xy2 = (char)trim_xy1xy2[8]; 00433 temp_msb = ((uint16_t)(trim_xy1xy2[5] & 0x7F)) << 8; 00434 trim_data.dig_xyz1 = (uint16_t)(temp_msb | trim_xy1xy2[4]); 00435 00436 } 00437 00438 void BMM150::write_op_mode(uint8_t op_mode) { 00439 uint8_t reg_data = 0; 00440 reg_data = i2c_read(BMM150_OP_MODE_ADDR); 00441 /* Set the op_mode value in Opmode bits of 0x4C */ 00442 reg_data = BMM150_SET_BITS(reg_data, BMM150_OP_MODE, op_mode); 00443 i2c_write(BMM150_OP_MODE_ADDR, reg_data); 00444 } 00445 00446 void BMM150::set_power_control_bit(uint8_t pwrcntrl_bit) { 00447 uint8_t reg_data = 0; 00448 /* Power control register 0x4B is read */ 00449 reg_data = i2c_read(BMM150_POWER_CONTROL_ADDR); 00450 /* Sets the value of power control bit */ 00451 reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_PWR_CNTRL, pwrcntrl_bit); 00452 i2c_write(BMM150_POWER_CONTROL_ADDR, reg_data); 00453 } 00454 00455 00456 // /*! 00457 // * @brief This API is used to perform the complete self test 00458 // * (both normal and advanced) for the BMM150 sensor 00459 // */ 00460 // char BMM150::perform_self_test(uint8_t self_test_mode) 00461 // { 00462 // char rslt; 00463 // char self_test_rslt = 0; 00464 00465 // switch (self_test_mode) { 00466 // case BMM150_NORMAL_SELF_TEST: 00467 // /* Set the sensor in sleep mode */ 00468 // settings.pwr_mode = BMM150_SLEEP_MODE; 00469 // set_op_mode(BMM150_SLEEP_MODE); 00470 // /* Perform the normal self test */ 00471 // rslt = perform_normal_self_test(); 00472 // break; 00473 00474 // case BMM150_ADVANCED_SELF_TEST: 00475 // /* Perform the advanced self test */ 00476 // rslt = perform_adv_self_test(); 00477 // /* Check to ensure bus error does not occur */ 00478 // if (rslt >= BMM150_OK) { 00479 // /* Store the status of self test result */ 00480 // self_test_rslt = rslt; 00481 // /* Perform soft reset */ 00482 // soft_reset(); 00483 // } 00484 // rslt = self_test_rslt; 00485 // break; 00486 // default: 00487 // rslt = BMM150_E_INVALID_CONFIG; 00488 // break; 00489 // } 00490 00491 // return rslt; 00492 // } 00493 00494 // /* 00495 // * @brief This internal API is used to perform the normal self test 00496 // * of the sensor and return the self test result as return value 00497 // */ 00498 // char BMM150::perform_normal_self_test() 00499 // { 00500 // char rslt; 00501 // uint8_t self_test_bit; 00502 00503 // /* Triggers the start of normal self test */ 00504 // enable_normal_self_test(&self_test_bit); 00505 // /* Check for self test completion status */ 00506 // if (self_test_bit == 0) { 00507 // /* Validates the self test results for all 3 axes */ 00508 // rslt = validate_normal_self_test(); 00509 // } 00510 00511 // return rslt; 00512 // } 00513 00514 // /*! 00515 // * @brief This internal API is used to enable the normal self test by setting 00516 // * the Self Test bit (bit0) of the 0x4C register, 00517 // * which triggers the start of self test 00518 // */ 00519 // void BMM150::enable_normal_self_test(uint8_t *self_test_enable) 00520 // { 00521 // uint8_t reg_data; 00522 // uint8_t self_test_val; 00523 00524 // /* Read the data from register 0x4C */ 00525 // reg_data = i2c->read(BMM150_OP_MODE_ADDR); 00526 // /* Set the Self Test bit(bit0) of the 0x4C register */ 00527 // self_test_val = 1; 00528 // reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_SELF_TEST, self_test_val); 00529 // /* Write the data to 0x4C register to trigger self test */ 00530 // i2c_write(BMM150_OP_MODE_ADDR, reg_data); 00531 // wait_ms(BMM150_NORMAL_SELF_TEST_wait_ms); 00532 // /* Read the data from register 0x4C */ 00533 // reg_data = i2c->read(BMM150_OP_MODE_ADDR); 00534 // /* Self Test bit(bit0) is stored in self_test_enable, 00535 // It will be reset to zero after the self test is over */ 00536 // *self_test_enable = BMM150_GET_BITS_POS_0(reg_data, BMM150_SELF_TEST); 00537 // } 00538 00539 // /*! 00540 // * @brief This internal API is used to validate the results of normal self test 00541 // * by using the self test status available in the bit0 of registers 0x42,0x44 00542 // * and 0x46. 00543 // */ 00544 // char BMM150::validate_normal_self_test() 00545 // { 00546 // char rslt; 00547 // uint8_t status; 00548 // uint8_t self_test_rslt[5]; 00549 00550 // /* Read the data from register 0x42 to 0x46 */ 00551 // i2c->read(BMM150_DATA_X_LSB, self_test_rslt, BMM150_SELF_TEST_LEN); 00552 // /* Parse and get the self test status bits */ 00553 // /* X-Self-Test (bit0) of 0x42 register is stored*/ 00554 // self_test_rslt[0] = BMM150_GET_BITS_POS_0(self_test_rslt[0], BMM150_SELF_TEST); 00555 // /* Y-Self-Test (bit0) of 0x44 register is stored */ 00556 // self_test_rslt[2] = BMM150_GET_BITS_POS_0(self_test_rslt[2], BMM150_SELF_TEST); 00557 // /* Z-Self-Test (bit0) of 0x46 register is stored */ 00558 // self_test_rslt[4] = BMM150_GET_BITS_POS_0(self_test_rslt[4], BMM150_SELF_TEST); 00559 // /* Combine the self test status and store it in the first 00560 // 3 bits of the status variable for processing*/ 00561 // status = (uint8_t)((self_test_rslt[4] << 2) | (self_test_rslt[2] << 1) | self_test_rslt[0]); 00562 // /* Validate status and store Self test result in "rslt" */ 00563 // if (status == BMM150_SELF_TEST_STATUS_SUCCESS) { 00564 // /* Self test is success when all status bits are set */ 00565 // rslt = BMM150_OK; 00566 // } else { 00567 // if (status == BMM150_SELF_TEST_STATUS_XYZ_FAIL) { 00568 // /* Self test - all axis fail condition */ 00569 // rslt = BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL; 00570 // } else { 00571 // /* Self test - some axis fail condition */ 00572 // rslt = (char)status; 00573 // } 00574 // } 00575 00576 // return rslt; 00577 // } 00578 00579 // /*! 00580 // * @brief This internal API is used to perform advanced self test for Z axis 00581 // */ 00582 // char BMM150::perform_adv_self_test() 00583 // { 00584 // uint8_t self_test_current; 00585 // int16_t positive_data_z; 00586 // int16_t negative_data_z; 00587 // char rslt; 00588 00589 // /* Set the desired power mode ,axes control and repetition settings */ 00590 // adv_self_test_settings(); 00591 // /* Measure the Z axes data with positive self-test current */ 00592 // self_test_current = BMM150_ENABLE_POSITIVE_CURRENT; 00593 // adv_self_test_measurement(self_test_current, &positive_data_z); 00594 // /* Measure the Z axes data with 00595 // negative self-test current */ 00596 // self_test_current = BMM150_ENABLE_NEGATIVE_CURRENT; 00597 // adv_self_test_measurement(self_test_current, &negative_data_z); 00598 // /* Disable self-test current */ 00599 // self_test_current = BMM150_DISABLE_SELF_TEST_CURRENT; 00600 // set_adv_self_test_current(self_test_current); 00601 // /* Validate the advanced self test */ 00602 // rslt = validate_adv_self_test(positive_data_z, negative_data_z); 00603 00604 // return rslt; 00605 // } 00606 00607 // /*! 00608 // * @brief This internal API is used to set the desired power mode , 00609 // * axes control and repetition settings for advanced self test 00610 // */ 00611 // void BMM150::adv_self_test_settings() 00612 // { 00613 // /* Set the power mode as sleep mode */ 00614 // settings.pwr_mode = BMM150_SLEEP_MODE; 00615 // set_op_mode(BMM150_SLEEP_MODE); 00616 // /* Disable XY-axis measurement */ 00617 // settings.xyz_axes_control = BMM150_DISABLE_XY_AXIS; 00618 // set_control_measurement_xyz(settings); 00619 // /* Repetition value is set as 0x04 */ 00620 // settings.z_rep = BMM150_SELF_TEST_REP_Z; 00621 // set_z_rep(settings); 00622 // } 00623 00624 // /*! 00625 // * @brief This internal API is used to set the positive or negative value of 00626 // * self-test current and obtain the corresponding magnetometer z axis data 00627 // */ 00628 // void BMM150::adv_self_test_measurement(uint8_t self_test_current, int16_t *data_z) 00629 // { 00630 // /* Set the advanced self test current as positive or 00631 // negative based on the value of parameter "self_test_current" */ 00632 // set_adv_self_test_current(self_test_current); 00633 // /* Set the device in forced mode*/ 00634 // settings.pwr_mode = BMM150_FORCED_MODE; 00635 // set_op_mode(BMM150_FORCED_MODE); 00636 // /* wait_ms to ensure measurement is complete */ 00637 // wait_ms(4); 00638 // /* Read Mag data and store the value of Z axis data */ 00639 // read_mag_data(); 00640 // /* Mag Z axis data is stored */ 00641 // *data_z = mag_data.z; 00642 // } 00643 00644 // /*! 00645 // * @brief This internal API is used to get the difference between the 00646 // * Z axis mag data obtained by positive and negative self-test current 00647 // * and validate whether the advanced self test is done successfully or not. 00648 // */ 00649 // char BMM150::validate_adv_self_test(int16_t positive_data_z, int16_t negative_data_z) 00650 // { 00651 // int32_t adv_self_test_rslt; 00652 // char rslt; 00653 00654 // /* Advanced self test difference between the Z axis mag data 00655 // obtained by the positive and negative self-test current */ 00656 // adv_self_test_rslt = positive_data_z - negative_data_z; 00657 // /* Advanced self test validation */ 00658 // /*Value of adv_self_test_rslt should be in between 180-240 micro-tesla*/ 00659 // if ((adv_self_test_rslt > 180) && (adv_self_test_rslt < 240)) { 00660 // /* Advanced self test success */ 00661 // rslt = BMM150_OK; 00662 // } else { 00663 // /* Advanced self test fail */ 00664 // rslt = BMM150_W_ADV_SELF_TEST_FAIL; 00665 // } 00666 00667 // return rslt; 00668 // } 00669 00670 // /* 00671 // * @brief This internal API is used to set the self test current value in 00672 // * the Adv. ST bits (bit6 and bit7) of 0x4C register 00673 // */ 00674 // void BMM150::set_adv_self_test_current(uint8_t self_test_current) 00675 // { 00676 // uint8_t reg_data; 00677 00678 // /* Read the 0x4C register */ 00679 // reg_data = i2c->read(BMM150_OP_MODE_ADDR); 00680 // /* Set the self test current value in the Adv. ST bits 00681 // (bit6 and bit7) of 0x4c register */ 00682 // reg_data = BMM150_SET_BITS(reg_data, BMM150_ADV_SELF_TEST, self_test_current); 00683 // i2c_write(BMM150_OP_MODE_ADDR, reg_data); 00684 00685 // } 00686 00687 // /* 00688 // * @brief This internal API is used to enable or disable the magnetic 00689 // * measurement of x,y,z axes based on the value of xyz_axes_control. 00690 // */ 00691 // void BMM150::set_control_measurement_xyz(struct bmm150_settings settings) 00692 // { 00693 // uint8_t reg_data; 00694 00695 // reg_data = i2c->read(BMM150_AXES_ENABLE_ADDR); 00696 // /* Set the axes to be enabled/disabled*/ 00697 // reg_data = BMM150_SET_BITS(reg_data, BMM150_CONTROL_MEASURE, settings.xyz_axes_control); 00698 // i2c_write(BMM150_AXES_ENABLE_ADDR, reg_data); 00699 // }
Generated on Sat Jul 16 2022 16:40:58 by 1.7.2