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