icm20948.cpp 19 KB

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