icm20948.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. /*
  2. * @file icm20948.c
  3. *
  4. * Created on: Dec 26, 2020
  5. * Author: mokhwasomssi (ANSII C version)
  6. *
  7. * Modified: Juraj Dudak (C++ version)
  8. * Date: 30.12.2022
  9. */
  10. #include "icm20948.h"
  11. uint16_t ACCEL_SampleRate_Table[15] = {
  12. 1,
  13. 3,
  14. 5,
  15. 7,
  16. 10,
  17. 15,
  18. 22,
  19. 31,
  20. 34,
  21. 127,
  22. 255,
  23. 513,
  24. 1022,
  25. 2044,
  26. 4095,
  27. };
  28. Icm20948::Icm20948(SpiManager *spi, icm20948_Config *config){
  29. _activeDevice = spi->addSlave(config->pinCS);
  30. _spi = spi;
  31. _sensor_ready = false;
  32. accSensor = new SensorAccel(spi, _activeDevice);
  33. gyroSensor = new SensorGyro(spi, _activeDevice);
  34. magSensor = new SensorMag(spi, _activeDevice);
  35. _is_present = this->icm20948_who_am_i();
  36. if (_is_present == false){
  37. return;
  38. }
  39. // while(!this->icm20948_who_am_i());
  40. this->accSensor->data.type = ICM20948_ACCEL; // + _activeDevice;
  41. this->gyroSensor->data.type = ICM20948_GYRO; // + _activeDevice;
  42. this->magSensor->data.type = ICM20948_MAG; // + _activeDevice;
  43. this->Reset();
  44. this->Wakeup();
  45. this->SetInterruptSource(config->int_source);
  46. this->gyroSensor->SetLowPassFilter(config->gyro.low_pass_filter);
  47. this->accSensor->SetLowPassFilter(config->accel.low_pass_filter);
  48. this->gyroSensor->SetSampleRate(config->gyro.sample_rate);
  49. this->accSensor->SetSampleRate(config->accel.sample_rate);
  50. this->accSensor->SetRange(config->accel.full_scale);
  51. this->gyroSensor->SetRange(config->gyro.full_scale);
  52. this->ak09916_init(&config->mag);
  53. _sensor_ready = true;
  54. }
  55. uint8_t Icm20948::IsPresent(void){
  56. return (int)_is_present;
  57. }
  58. void Icm20948::Calibrate(icm20948_Config *config)
  59. {
  60. this->SetInterruptSource(config->int_source);
  61. this->accSensor->Calibrate();
  62. this->gyroSensor->Calibrate();
  63. this->gyroSensor->SetLowPassFilter(config->gyro.low_pass_filter);
  64. this->accSensor->SetLowPassFilter(config->accel.low_pass_filter);
  65. this->gyroSensor->SetSampleRate(config->gyro.sample_rate);
  66. this->accSensor->SetSampleRate(config->accel.sample_rate);
  67. this->accSensor->SetRange(config->accel.full_scale);
  68. this->gyroSensor->SetRange(config->gyro.full_scale);
  69. this->ak09916_init(&config->mag);
  70. }
  71. bool Icm20948::icm20948_who_am_i()
  72. {
  73. uint8_t icm20948_id = _spi->read_single_reg(_activeDevice, ub_0, B0_WHO_AM_I);
  74. if(icm20948_id == ICM20948_ID)
  75. return true;
  76. else
  77. return false;
  78. }
  79. void Icm20948::Reset(void)
  80. {
  81. ASSERT_SENSOR;
  82. _spi->write_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_1, 0xC1); // reset - 0x80, sleep 0x40, source PLL auto 0x01
  83. HAL_Delay(100);
  84. this->Wakeup();
  85. this->icm20948_clock_source(1);
  86. this->icm20948_odr_align_enable();
  87. this->icm20948_spi_slave_enable();
  88. }
  89. void Icm20948::Wakeup(void)
  90. {
  91. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_1);
  92. new_val &= 0xBF;
  93. _spi->write_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_1, new_val);
  94. HAL_Delay(50);
  95. }
  96. uint8_t Icm20948::IsSleep(void)
  97. {
  98. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_1);
  99. return new_val & 0x40;
  100. }
  101. bool Icm20948::IsReady(void)
  102. {
  103. return _sensor_ready;
  104. }
  105. void Icm20948::Stop(void)
  106. {
  107. // _spi->write_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_2, 0x3F); // vypne vsetky senzory
  108. _spi->write_single_reg(_activeDevice, ub_0, B0_INT_ENABLE_1, 0x0);
  109. _sensor_ready = false;
  110. }
  111. void Icm20948::Start(void)
  112. {
  113. // _spi->write_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_2, 0x0);
  114. _spi->write_single_reg(_activeDevice, ub_0, B0_INT_ENABLE_1, 0x1);
  115. _sensor_ready = true;
  116. }
  117. void Icm20948::Sleep(void)
  118. {
  119. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_1);
  120. new_val |= 0x40;
  121. _spi->write_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_1, new_val);
  122. HAL_Delay(100);
  123. }
  124. void Icm20948::icm20948_spi_slave_enable()
  125. {
  126. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_0, B0_USER_CTRL);
  127. new_val |= 0x10;
  128. _spi->write_single_reg(_activeDevice, ub_0, B0_USER_CTRL, new_val);
  129. }
  130. void Icm20948::icm20948_i2c_master_reset()
  131. {
  132. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_0, B0_USER_CTRL);
  133. new_val |= 0x02;
  134. _spi->write_single_reg(_activeDevice, ub_0, B0_USER_CTRL, new_val);
  135. }
  136. void Icm20948::icm20948_i2c_master_enable()
  137. {
  138. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_0, B0_USER_CTRL);
  139. new_val |= 0x20;
  140. _spi->write_single_reg(_activeDevice, ub_0, B0_USER_CTRL, new_val);
  141. HAL_Delay(100);
  142. }
  143. void Icm20948::icm20948_i2c_master_clk_frq(uint8_t config)
  144. {
  145. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_3, B3_I2C_MST_CTRL);
  146. new_val |= config;
  147. _spi->write_single_reg(_activeDevice, ub_3, B3_I2C_MST_CTRL, new_val);
  148. }
  149. void Icm20948::icm20948_clock_source(uint8_t source)
  150. {
  151. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_1);
  152. new_val |= source;
  153. _spi->write_single_reg(_activeDevice, ub_0, B0_PWR_MGMT_1, new_val);
  154. }
  155. void Icm20948::icm20948_odr_align_enable()
  156. {
  157. _spi->write_single_reg(_activeDevice, ub_2, B2_ODR_ALIGN_EN, 0x01);
  158. }
  159. void Icm20948::SetInterruptSource(interrupt_source_enum int_source)
  160. {
  161. _spi->write_single_reg(_activeDevice, ub_0, B0_INT_PIN_CFG, (INT_PIN_CFG_2CLEAR)); // ( INT_PIN_CFG_LATCH | ...
  162. uint8_t source1 = (uint8_t)(int_source & 0xFF);
  163. uint8_t source2 = (uint8_t)((int_source >> 8) & 0xFF);
  164. _spi->write_single_reg(_activeDevice, ub_0, B0_INT_ENABLE, source1);
  165. _spi->write_single_reg(_activeDevice, ub_0, B0_INT_ENABLE_1, source2);
  166. }
  167. void Icm20948::Read(void)
  168. {
  169. uint8_t* temp =_spi->read_multiple_reg(_activeDevice, ub_0, B0_ACCEL_XOUT_H, 12);
  170. this->accSensor->data.x = (int16_t)(temp[0] << 8 | temp[1]);
  171. this->accSensor->data.y = (int16_t)(temp[2] << 8 | temp[3]);
  172. this->accSensor->data.z = (int16_t)(temp[4] << 8 | temp[5]) + this->accSensor->_scaleFactor;
  173. // Add scale factor because calibration function offset gravity acceleration.
  174. this->gyroSensor->data.x = (int16_t)(temp[6] << 8 | temp[7]);
  175. this->gyroSensor->data.y = (int16_t)(temp[8] << 8 | temp[9]);
  176. this->gyroSensor->data.z = (int16_t)(temp[10] << 8 | temp[11]);
  177. if(this->_ak09916_enable){
  178. if(this->magSensor->Read(&this->magSensor->data) == false){
  179. this->magSensor->data.x = 0;
  180. this->magSensor->data.y = 0;
  181. this->magSensor->data.z = 0;
  182. }
  183. }
  184. }
  185. uint8_t Icm20948::GetDataStatus(void)
  186. {
  187. // same register for ACC and GYRO sensor
  188. return this->accSensor->GetDataStatus();
  189. }
  190. /// ---------------------- MAGNETOEMTER -----------------------------------
  191. void Icm20948::ak09916_init(Config_Mag_t *config)
  192. {
  193. this->icm20948_i2c_master_reset();
  194. this->icm20948_i2c_master_enable();
  195. this->icm20948_i2c_master_clk_frq(7);
  196. this->_ak09916_enable = false;
  197. if(this->ak09916_who_am_i()){
  198. this->_ak09916_enable = true;
  199. }
  200. if(this->_ak09916_enable == true){
  201. this->ak09916_soft_reset();
  202. this->ak09916_operation_mode_setting(config->mode);
  203. if (config->mode == mag_mode_power_down) {
  204. this->_ak09916_enable = false;
  205. } else {
  206. this->_ak09916_enable = true;
  207. }
  208. }
  209. }
  210. void Icm20948::ak09916_soft_reset()
  211. {
  212. _spi->write_single_external_reg(_activeDevice, MAG_CNTL3, 0x01);
  213. HAL_Delay(100);
  214. }
  215. bool Icm20948::ak09916_who_am_i()
  216. {
  217. uint8_t ak09916_id = _spi->read_single_external_reg(_activeDevice, MAG_WIA2);
  218. if(ak09916_id == AK09916_ID)
  219. return true;
  220. else
  221. return false;
  222. }
  223. void Icm20948::ak09916_operation_mode_setting(AK09916_operation_mode mode)
  224. {
  225. _spi->write_single_external_reg(_activeDevice, MAG_CNTL2, mode);
  226. HAL_Delay(100);
  227. }
  228. uint8_t Icm20948::GetIndexZeroBased(void)
  229. {
  230. return this->_activeDevice;
  231. }
  232. uint8_t Icm20948::GetIndex(void)
  233. {
  234. return this->_activeDevice + 1;
  235. }
  236. /* ----------------- SENSORS --------------------
  237. * 1) Sensor Accel
  238. * 2) Sensor Gyro
  239. * 3) Sensor Mag
  240. * ---------------------------------------------- */
  241. Sensor::Sensor(SpiManager *spi, int8_t activeDevice){
  242. _spi = spi;
  243. _activeDevice = activeDevice;
  244. _scaleFactor = 1.0f;
  245. offset_x = 0;
  246. offset_y = 0;
  247. offset_z = 0;
  248. }
  249. /**
  250. * @brief Interrupt status regiter - INT_STATUS_1
  251. * @return 1 – Sensor Register Raw Data, from all sensors, is updated and ready to be read.
  252. */
  253. uint8_t Sensor::GetDataStatus(void)
  254. {
  255. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_0, B0_INT_STATUS_1);
  256. return new_val & 0x01;
  257. }
  258. bool Sensor::_read_without_scale_factor(axises* data)
  259. {
  260. return this->Read(data);
  261. }
  262. SensorGyro::SensorGyro(SpiManager *spi, int8_t activeDevice):Sensor(spi, activeDevice){
  263. }
  264. SensorAccel::SensorAccel(SpiManager *spi, int8_t activeDevice):Sensor(spi, activeDevice){
  265. }
  266. SensorMag::SensorMag(SpiManager *spi, int8_t activeDevice):Sensor(spi, activeDevice){
  267. }
  268. void Sensor::SetScaleFactor(float sf){
  269. _scaleFactor = sf;
  270. }
  271. uint8_t Sensor::GetLowPassFilter(void){
  272. return 0xFF;
  273. }
  274. uint8_t Sensor::GetSampleRate(void)
  275. {
  276. return 0xFF;
  277. }
  278. uint8_t Sensor::GetRange(void){
  279. return 0;
  280. }
  281. bool SensorGyro::Read(axises* data)
  282. {
  283. uint8_t* temp = this->_spi->read_multiple_reg(this->_activeDevice, ub_0, B0_GYRO_XOUT_H, 6);
  284. data->x = (int16_t)(temp[0] << 8 | temp[1]);
  285. data->y = (int16_t)(temp[2] << 8 | temp[3]);
  286. data->z = (int16_t)(temp[4] << 8 | temp[5]);
  287. return true;
  288. }
  289. bool SensorAccel::Read(axises* data)
  290. {
  291. uint8_t* temp = this->_spi->read_multiple_reg(this->_activeDevice, ub_0, B0_ACCEL_XOUT_H, 6);
  292. data->x = (int16_t)(temp[0] << 8 | temp[1]);
  293. data->y = (int16_t)(temp[2] << 8 | temp[3]);
  294. data->z = (int16_t)(temp[4] << 8 | temp[5]) + this->_scaleFactor;
  295. // Add scale factor because calibraiton function offset gravity acceleration.
  296. return true;
  297. }
  298. /**
  299. * Do not use this function to read final data. It is only for calibration of sensor.
  300. */
  301. bool SensorAccel::_read_without_scale_factor(axises* data)
  302. {
  303. uint8_t* temp = this->_spi->read_multiple_reg(this->_activeDevice, ub_0, B0_ACCEL_XOUT_H, 6);
  304. data->x = (int16_t)(temp[0] << 8 | temp[1]);
  305. data->y = (int16_t)(temp[2] << 8 | temp[3]);
  306. data->z = (int16_t)(temp[4] << 8 | temp[5]);
  307. // Add scale factor because calibraiton function offset gravity acceleration.
  308. return true;
  309. }
  310. bool SensorMag::Read(axises* data)
  311. {
  312. uint8_t* temp;
  313. uint8_t drdy; // data ready
  314. uint8_t hofl; // overflow
  315. drdy = this->_spi->read_single_external_reg(this->_activeDevice, MAG_ST1) & 0x01;
  316. if(!drdy) return false;
  317. temp = this->_spi->read_multiple_external_reg(this->_activeDevice, MAG_HXL, 6);
  318. hofl = this->_spi->read_single_external_reg(this->_activeDevice, MAG_ST2) & 0x08;
  319. if(hofl) return false;
  320. data->x = (int16_t)(temp[1] << 8 | temp[0]);
  321. data->y = (int16_t)(temp[3] << 8 | temp[2]);
  322. data->z = (int16_t)(temp[5] << 8 | temp[4]);
  323. return true;
  324. }
  325. bool SensorGyro::ReadUnit(axises* data)
  326. {
  327. this->Read(data);
  328. data->x /= this->_scaleFactor;
  329. data->y /= this->_scaleFactor;
  330. data->z /= this->_scaleFactor;
  331. return true;
  332. }
  333. bool SensorAccel::ReadUnit(axises* data)
  334. {
  335. this->Read(data);
  336. data->x /= this->_scaleFactor;
  337. data->y /= this->_scaleFactor;
  338. data->z /= this->_scaleFactor;
  339. return true;
  340. }
  341. bool SensorMag::ReadUnit(axises* data)
  342. {
  343. axises temp;
  344. bool new_data = this->Read(&temp);
  345. if(!new_data) return false;
  346. data->x = (float)(temp.x * 0.15);
  347. data->y = (float)(temp.y * 0.15);
  348. data->z = (float)(temp.z * 0.15);
  349. return true;
  350. }
  351. axises *SensorAccel::GetData()
  352. {
  353. return &this->data;
  354. }
  355. axises *SensorGyro::GetData()
  356. {
  357. return &this->data;
  358. }
  359. axises *SensorMag::GetData()
  360. {
  361. return &this->data;
  362. }
  363. void SensorAccel::SetRange(accel_full_scale full_scale)
  364. {
  365. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_2, B2_ACCEL_CONFIG);
  366. new_val = new_val & 0xF9; // remova ACCEL_FS_SEL bites [1-2]
  367. float accel_scale_factor;
  368. switch(full_scale)
  369. {
  370. case _2g :
  371. new_val |= 0x00;
  372. accel_scale_factor = 16384;
  373. break;
  374. case _4g :
  375. new_val |= 0x02;
  376. accel_scale_factor = 8192;
  377. break;
  378. case _8g :
  379. new_val |= 0x04;
  380. accel_scale_factor = 4096;
  381. break;
  382. case _16g :
  383. new_val |= 0x06;
  384. accel_scale_factor = 2048;
  385. break;
  386. }
  387. this->SetScaleFactor(accel_scale_factor);
  388. _spi->write_single_reg(_activeDevice, ub_2, B2_ACCEL_CONFIG, new_val);
  389. }
  390. void SensorGyro::SetRange(gyro_full_scale full_scale)
  391. {
  392. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_2, B2_GYRO_CONFIG_1);
  393. new_val &= 0xF9; /// mask: xxxx x00x
  394. float gyro_scale_factor = 1;
  395. switch(full_scale)
  396. {
  397. case _250dps :
  398. new_val |= 0x00;
  399. gyro_scale_factor = 131.0;
  400. break;
  401. case _500dps :
  402. new_val |= 0x02;
  403. gyro_scale_factor = 65.5;
  404. break;
  405. case _1000dps :
  406. new_val |= 0x04;
  407. gyro_scale_factor = 32.8;
  408. break;
  409. case _2000dps :
  410. new_val |= 0x06;
  411. gyro_scale_factor = 16.4;
  412. break;
  413. }
  414. this->SetScaleFactor(gyro_scale_factor);
  415. _spi->write_single_reg(_activeDevice, ub_2, B2_GYRO_CONFIG_1, new_val);
  416. }
  417. uint8_t SensorGyro::GetLowPassFilter(void)
  418. {
  419. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_2, B2_GYRO_CONFIG_1);
  420. if( (new_val & 0x01) == 0x01)
  421. {
  422. return (new_val>>3) & 0x07;
  423. }
  424. return 0xFE;
  425. }
  426. void SensorGyro::SetLowPassFilter(gyro_dlp_cfg config)
  427. {
  428. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_2, B2_GYRO_CONFIG_1);
  429. uint8_t gyro_fchoice = 1;
  430. uint8_t config_val = (uint8_t)config;
  431. uint8_t mask = 0xC7;
  432. if (config == GYRO_low_pass_OFF){
  433. gyro_fchoice = 0;
  434. config_val = 0;
  435. mask = 0xC6;
  436. }
  437. new_val = (new_val & mask) | (config_val<<3) | gyro_fchoice; // mask Gyro range settings
  438. _spi->write_single_reg(_activeDevice, ub_2, B2_GYRO_CONFIG_1, new_val);
  439. }
  440. uint8_t SensorAccel::CheckLowPassInputValue(uint8_t value)
  441. {
  442. uint8_t valid = 0;
  443. switch(value) {
  444. case ACCEL_lpf_246Hz:
  445. case ACCEL_lpf_114_4Hz:
  446. case ACCEL_lpf_050_4Hz:
  447. case ACCEL_lpf_023_9Hz:
  448. case ACCEL_lpf_011_5Hz:
  449. case ACCEL_lpf_005_7Hz:
  450. case ACCEL_lpf_473Hz:
  451. case ACCEL_lpf_OFF:
  452. valid = 1;
  453. break;
  454. default:
  455. valid = 0;
  456. };
  457. return valid;
  458. }
  459. uint8_t SensorGyro::CheckLowPassInputValue(uint8_t value)
  460. {
  461. uint8_t valid = 0;
  462. switch(value) {
  463. case GYRO_low_pass_OFF:
  464. case GYRO_lpf_005_7Hz:
  465. case GYRO_lpf_011_6Hz:
  466. case GYRO_lpf_023_9Hz:
  467. case GYRO_lpf_051_2Hz:
  468. case GYRO_lpf_119_5Hz:
  469. case GYRO_lpf_151_8Hz:
  470. case GYRO_lpf_196_6Hz:
  471. case GYRO_lpf_361_4Hz:
  472. valid = 1;
  473. break;
  474. default:
  475. valid = 0;
  476. };
  477. return valid;
  478. }
  479. /**
  480. * @brief Configure Low-pass filter:
  481. * @param config:
  482. */
  483. void SensorAccel::SetLowPassFilter(accel_dlp_cfg config)
  484. {
  485. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_2, B2_ACCEL_CONFIG);
  486. uint8_t accel_fchoice = 1;
  487. uint8_t mask = 0xC7;
  488. // uint8_t config_val = (uint8_t)config;
  489. if (config == ACCEL_lpf_OFF){
  490. accel_fchoice = 0;
  491. // config_val = 0;
  492. mask = 0xC6;
  493. }
  494. new_val = (new_val & mask) | (config<<3) | accel_fchoice; // mask Accel range settings
  495. _spi->write_single_reg(_activeDevice, ub_2, B2_ACCEL_CONFIG, new_val);
  496. }
  497. uint8_t SensorAccel::GetLowPassFilter(void)
  498. {
  499. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_2, B2_ACCEL_CONFIG);
  500. if((new_val & 0x01) == 0){
  501. //LPF is OFF
  502. return 0xFE;
  503. }
  504. new_val = (new_val>>3) & 0x07;
  505. if(new_val == 0){ // cofig value 0 and 1 has same LPF frequency: 246Hz
  506. new_val = 1;
  507. }
  508. return new_val;
  509. }
  510. uint8_t SensorGyro::SetSampleRate(gyro_samplerate divider)
  511. {
  512. _spi->write_single_reg(_activeDevice, ub_2, B2_GYRO_SMPLRT_DIV, divider);
  513. return 1;
  514. }
  515. uint8_t SensorGyro::GetSampleRate(void)
  516. {
  517. uint8_t value = _spi->read_single_reg(_activeDevice, ub_2, B2_GYRO_SMPLRT_DIV);
  518. return value;
  519. }
  520. uint8_t SensorAccel::SetSampleRate(accel_samplerate smplrt)
  521. {
  522. if(smplrt < 0 || smplrt >= 15){
  523. return 0;
  524. }
  525. uint16_t sr = ACCEL_SampleRate_Table[smplrt];
  526. uint8_t data[2] = {(uint8_t)((sr>> 8) & 0x0F), (uint8_t)(sr & 0xFF)}; // MSB, LSB
  527. _spi->write_multiple_reg(_activeDevice, ub_2, B2_ACCEL_SMPLRT_DIV_1, data, 2);
  528. return 1;
  529. }
  530. uint8_t SensorAccel::GetSampleRate(void)
  531. {
  532. uint8_t d1 = _spi->read_single_reg(_activeDevice, ub_2, B2_ACCEL_SMPLRT_DIV_1);
  533. uint8_t d2 = _spi->read_single_reg(_activeDevice, ub_2, B2_ACCEL_SMPLRT_DIV_2);
  534. uint16_t value = (d1<<8 | d2);
  535. uint8_t sr_index = 0;
  536. for(uint8_t i=0 ; i < 15 ; i++){
  537. if(value == ACCEL_SampleRate_Table[i]){
  538. sr_index = i;
  539. }
  540. }
  541. return sr_index;
  542. }
  543. uint8_t SensorAccel::GetRange(void){
  544. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_2, B2_ACCEL_CONFIG);
  545. return (new_val >> 1) & 0x03;
  546. }
  547. uint8_t SensorGyro::GetRange(void){
  548. uint8_t new_val = _spi->read_single_reg(_activeDevice, ub_2, B2_GYRO_CONFIG_1);
  549. return (new_val >> 1) & 0x03;
  550. }
  551. void SensorGyro::Calibrate(void)
  552. {
  553. axises temp;
  554. int32_t gyro_bias[3] = {0};
  555. for(int i = 0; i < 100; i++)
  556. {
  557. while(this->GetDataStatus() == 0);
  558. this->Read(&temp);
  559. gyro_bias[0] += temp.x;
  560. gyro_bias[1] += temp.y;
  561. gyro_bias[2] += temp.z;
  562. }
  563. gyro_bias[0] /= 100;
  564. gyro_bias[1] /= 100;
  565. gyro_bias[2] /= 100;
  566. this->offset_x = gyro_bias[0];
  567. this->offset_y = gyro_bias[1];
  568. this->offset_z = gyro_bias[2];
  569. this->SaveOffset();
  570. }
  571. void SensorGyro::SaveOffset(void)
  572. {
  573. if((this->offset_x+this->offset_y+this->offset_z)==0)
  574. {
  575. return;
  576. }
  577. uint8_t gyro_offset[6] = {0};
  578. // Construct the gyro biases for push to the hardware gyro bias registers,
  579. // which are reset to zero upon device startup.
  580. // Divide by 4 to get 32.9 LSB per deg/s to conform to expected bias input format.
  581. // Biases are additive, so change sign on calculated average gyro biases
  582. gyro_offset[0] = (-this->offset_x / 4 >> 8) & 0xFF;
  583. gyro_offset[1] = (-this->offset_x / 4) & 0xFF;
  584. gyro_offset[2] = (-this->offset_y / 4 >> 8) & 0xFF;
  585. gyro_offset[3] = (-this->offset_y / 4) & 0xFF;
  586. gyro_offset[4] = (-this->offset_z / 4 >> 8) & 0xFF;
  587. gyro_offset[5] = (-this->offset_z / 4) & 0xFF;
  588. _spi->write_multiple_reg(_activeDevice, ub_2, B2_XG_OFFS_USRH, gyro_offset, 6);
  589. }
  590. void SensorAccel::Calibrate()
  591. {
  592. axises temp;
  593. uint8_t* temp2;
  594. uint8_t* temp3;
  595. uint8_t* temp4;
  596. int32_t accel_bias[3] = {0};
  597. int32_t accel_bias_reg[3] = {0};
  598. for(int q = 0; q < 3; q++)
  599. {
  600. for(int i = 0; i < 100; i++)
  601. {
  602. while(this->GetDataStatus() == 0);
  603. this->_read_without_scale_factor(&temp);
  604. accel_bias[0] += temp.x;
  605. accel_bias[1] += temp.y;
  606. accel_bias[2] += temp.z;
  607. }
  608. HAL_Delay(25);
  609. }
  610. accel_bias[0] /= 300;
  611. accel_bias[1] /= 300;
  612. accel_bias[2] /= 300;
  613. temp2 = _spi->read_multiple_reg(_activeDevice, ub_1, B1_XA_OFFS_H, 2);
  614. accel_bias_reg[0] = (int32_t)(temp2[0] << 8 | temp2[1]);
  615. temp3 = _spi->read_multiple_reg(_activeDevice, ub_1, B1_YA_OFFS_H, 2);
  616. accel_bias_reg[1] = (int32_t)(temp3[0] << 8 | temp3[1]);
  617. temp4 = _spi->read_multiple_reg(_activeDevice, ub_1, B1_ZA_OFFS_H, 2);
  618. accel_bias_reg[2] = (int32_t)(temp4[0] << 8 | temp4[1]);
  619. accel_bias_reg[0] -= (accel_bias[0]/8 );
  620. accel_bias_reg[1] -= (accel_bias[1]/8 );
  621. accel_bias_reg[2] -= (accel_bias[2]/8 ); // (accel_bias[2]/8)
  622. this->offset_x = accel_bias_reg[0];
  623. this->offset_y = accel_bias_reg[1];
  624. this->offset_z = accel_bias_reg[2];
  625. this->SaveOffset();
  626. }
  627. void SensorAccel::SaveOffset(void)
  628. {
  629. if((this->offset_x+this->offset_y+this->offset_z)==0)
  630. {
  631. return;
  632. }
  633. uint8_t accel_offset[6] = {0};
  634. accel_offset[0] = (this->offset_x >> 8) & 0xFF;
  635. accel_offset[1] = (this->offset_x) & 0xFE;
  636. accel_offset[2] = (this->offset_y >> 8) & 0xFF;
  637. accel_offset[3] = (this->offset_y) & 0xFE;
  638. accel_offset[4] = (this->offset_z >> 8) & 0xFF;
  639. accel_offset[5] = (this->offset_z) & 0xFE;
  640. _spi->write_multiple_reg(_activeDevice, ub_1, B1_XA_OFFS_H, &accel_offset[0], 2);
  641. _spi->write_multiple_reg(_activeDevice, ub_1, B1_YA_OFFS_H, &accel_offset[2], 2);
  642. _spi->write_multiple_reg(_activeDevice, ub_1, B1_ZA_OFFS_H, &accel_offset[4], 2);
  643. }