icm20948.cpp 19 KB

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