LSM6DS3.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. /******************************************************************************
  2. SparkFunLSM6DS3.cpp
  3. LSM6DS3 Arduino and Teensy Driver
  4. Marshall Taylor @ SparkFun Electronics
  5. May 20, 2015
  6. https://github.com/sparkfun/LSM6DS3_Breakout
  7. https://github.com/sparkfun/SparkFun_LSM6DS3_Arduino_Library
  8. Resources:
  9. Uses Wire.h for i2c operation
  10. Uses SPI.h for SPI operation
  11. Either can be omitted if not used
  12. Development environment specifics:
  13. Arduino IDE 1.6.4
  14. Teensy loader 1.23
  15. This code is released under the [MIT License](http://opensource.org/licenses/MIT).
  16. Please review the LICENSE.md file included with this example. If you have any questions
  17. or concerns with licensing, please contact techsupport@sparkfun.com.
  18. Distributed as-is; no warranty is given.
  19. ******************************************************************************/
  20. //See SparkFunLSM6DS3.h for additional topology notes.
  21. #include "LSM6DS3.h"
  22. #include "stdint.h"
  23. #include "Wire.h"
  24. #include "SPI.h"
  25. #if defined(TARGET_SEEED_XIAO_NRF52840_SENSE) || defined(TARGET_SEEED_XIAO_NRF52840_SENSE_PLUS)
  26. #define Wire Wire1
  27. #endif
  28. #if defined(ARDUINO_XIAO_MG24)
  29. #define Wire Wire1
  30. #define PIN_LSM6DS3TR_C_POWER PD5
  31. #endif
  32. //****************************************************************************//
  33. //
  34. // LSM6DS3Core functions.
  35. //
  36. // Construction arguments:
  37. // ( uint8_t busType, uint8_t inputArg ),
  38. //
  39. // where inputArg is address for I2C_MODE and chip select pin
  40. // number for SPI_MODE
  41. //
  42. // For SPI, construct LSM6DS3Core myIMU(SPI_MODE, 10);
  43. // For I2C, construct LSM6DS3Core myIMU(I2C_MODE, 0x6B);
  44. //
  45. // Default construction is I2C mode, address 0x6B.
  46. //
  47. //****************************************************************************//
  48. LSM6DS3Core::LSM6DS3Core(uint8_t busType, uint8_t inputArg) : commInterface(I2C_MODE), I2CAddress(0x6B),
  49. chipSelectPin(10) {
  50. commInterface = busType;
  51. if (commInterface == I2C_MODE) {
  52. I2CAddress = inputArg;
  53. }
  54. if (commInterface == SPI_MODE) {
  55. chipSelectPin = inputArg;
  56. }
  57. }
  58. status_t LSM6DS3Core::beginCore(void) {
  59. status_t returnError = IMU_SUCCESS;
  60. #ifdef PIN_LSM6DS3TR_C_POWER
  61. pinMode(PIN_LSM6DS3TR_C_POWER, OUTPUT);
  62. #if defined(NRF52840_XXAA)
  63. NRF_P1->PIN_CNF[8] = ((uint32_t)NRF_GPIO_PIN_DIR_OUTPUT << GPIO_PIN_CNF_DIR_Pos)
  64. | ((uint32_t)NRF_GPIO_PIN_INPUT_DISCONNECT << GPIO_PIN_CNF_INPUT_Pos)
  65. | ((uint32_t)NRF_GPIO_PIN_NOPULL << GPIO_PIN_CNF_PULL_Pos)
  66. | ((uint32_t)NRF_GPIO_PIN_H0H1 << GPIO_PIN_CNF_DRIVE_Pos)
  67. | ((uint32_t)NRF_GPIO_PIN_NOSENSE << GPIO_PIN_CNF_SENSE_Pos);
  68. #endif
  69. digitalWrite(PIN_LSM6DS3TR_C_POWER, HIGH);
  70. delay(10);
  71. #endif
  72. switch (commInterface) {
  73. case I2C_MODE:
  74. Wire.begin();
  75. break;
  76. case SPI_MODE:
  77. #if defined(NRF52840_XXAA)
  78. // start the SPI library:
  79. SPI.begin();
  80. // Maximum SPI frequency is 10MHz, could divide by 2 here:
  81. #if defined(ARDUINO_XIAO_RA4M1) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_ARCH_RP2350)
  82. SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  83. #elif defined(ARDUINO_XIAO_MG24)
  84. // SPI.setClockDivider(SPI_CLOCK_DIV4);
  85. SPI.setClockDivider(4);
  86. #endif
  87. // Data is read and written MSb first.
  88. #ifdef ESP32
  89. SPI.setBitOrder(SPI_MSBFIRST);
  90. #elif defined(ARDUINO_XIAO_RA4M1) || defined(ARDUINO_ARCH_MBED)
  91. // MbedSPI and XIAO_RA4M1 don't support setBitOrder - use SPISettings instead
  92. #else
  93. SPI.setBitOrder(MSBFIRST);
  94. #endif
  95. // Data is captured on rising edge of clock (CPHA = 0)
  96. // Base value of the clock is HIGH (CPOL = 1)
  97. // MODE3 for 328p operation
  98. #if defined(__AVR__) && !defined(ARDUINO_ARCH_MBED)
  99. SPI.setDataMode(SPI_MODE3);
  100. #endif
  101. // MODE0 for Teensy 3.1 operation
  102. #if defined(__MK20DX256__) && !defined(ARDUINO_ARCH_MBED)
  103. SPI.setDataMode(SPI_MODE0);
  104. #endif
  105. // initalize the data ready and chip select pins:
  106. pinMode(chipSelectPin, OUTPUT);
  107. digitalWrite(chipSelectPin, HIGH);
  108. #endif
  109. break;
  110. default:
  111. break;
  112. }
  113. //Spin for a few ms
  114. volatile uint8_t temp = 0;
  115. for (uint16_t i = 0; i < 10000; i++) {
  116. temp++;
  117. }
  118. //Check the ID register to determine if the operation was a success.
  119. uint8_t readCheck;
  120. readRegister(&readCheck, LSM6DS3_ACC_GYRO_WHO_AM_I_REG);
  121. if (!(readCheck == LSM6DS3_ACC_GYRO_WHO_AM_I || readCheck == LSM6DS3_C_ACC_GYRO_WHO_AM_I)) {
  122. returnError = IMU_HW_ERROR;
  123. }
  124. return returnError;
  125. }
  126. //****************************************************************************//
  127. //
  128. // ReadRegisterRegion
  129. //
  130. // Parameters:
  131. // *outputPointer -- Pass &variable (base address of) to save read data to
  132. // offset -- register to read
  133. // length -- number of bytes to read
  134. //
  135. // Note: Does not know if the target memory space is an array or not, or
  136. // if there is the array is big enough. if the variable passed is only
  137. // two bytes long and 3 bytes are requested, this will over-write some
  138. // other memory!
  139. //
  140. //****************************************************************************//
  141. status_t LSM6DS3Core::readRegisterRegion(uint8_t* outputPointer, uint8_t offset, uint8_t length) {
  142. status_t returnError = IMU_SUCCESS;
  143. //define pointer that will point to the external space
  144. uint8_t i = 0;
  145. uint8_t c = 0;
  146. #if defined(NRF52840_XXAA)
  147. uint8_t tempFFCounter = 0;
  148. #endif
  149. switch (commInterface) {
  150. case I2C_MODE:
  151. Wire.beginTransmission(I2CAddress);
  152. Wire.write(offset);
  153. if (Wire.endTransmission() != 0) {
  154. returnError = IMU_HW_ERROR;
  155. } else { //OK, all worked, keep going
  156. // request 6 bytes from slave device
  157. Wire.requestFrom(I2CAddress, length);
  158. while ((Wire.available()) && (i < length)) { // slave may send less than requested
  159. c = Wire.read(); // receive a byte as character
  160. *outputPointer = c;
  161. outputPointer++;
  162. i++;
  163. }
  164. }
  165. break;
  166. case SPI_MODE:
  167. #if defined(NRF52840_XXAA)
  168. // take the chip select low to select the device:
  169. digitalWrite(chipSelectPin, LOW);
  170. // send the device the register you want to read:
  171. SPI.transfer(offset | 0x80); //Ored with "read request" bit
  172. while (i < length) { // slave may send less than requested
  173. c = SPI.transfer(0x00); // receive a byte as character
  174. if (c == 0xFF) {
  175. //May have problem
  176. tempFFCounter++;
  177. }
  178. *outputPointer = c;
  179. outputPointer++;
  180. i++;
  181. }
  182. if (tempFFCounter == i) {
  183. //Ok, we've recieved all ones, report
  184. returnError = IMU_ALL_ONES_WARNING;
  185. }
  186. // take the chip select high to de-select:
  187. digitalWrite(chipSelectPin, HIGH);
  188. #endif
  189. break;
  190. default:
  191. break;
  192. }
  193. return returnError;
  194. }
  195. //****************************************************************************//
  196. //
  197. // ReadRegister
  198. //
  199. // Parameters:
  200. // *outputPointer -- Pass &variable (address of) to save read data to
  201. // offset -- register to read
  202. //
  203. //****************************************************************************//
  204. status_t LSM6DS3Core::readRegister(uint8_t* outputPointer, uint8_t offset) {
  205. //Return value
  206. uint8_t result = 0;
  207. uint8_t numBytes = 1;
  208. status_t returnError = IMU_SUCCESS;
  209. switch (commInterface) {
  210. case I2C_MODE:
  211. Wire.beginTransmission(I2CAddress);
  212. Wire.write(offset);
  213. if (Wire.endTransmission() != 0) {
  214. returnError = IMU_HW_ERROR;
  215. }
  216. Wire.requestFrom(I2CAddress, numBytes);
  217. while (Wire.available()) { // slave may send less than requested
  218. result = Wire.read(); // receive a byte as a proper uint8_t
  219. }
  220. break;
  221. case SPI_MODE:
  222. #if defined(NRF52840_XXAA)
  223. // take the chip select low to select the device:
  224. digitalWrite(chipSelectPin, LOW);
  225. // send the device the register you want to read:
  226. SPI.transfer(offset | 0x80); //Ored with "read request" bit
  227. // send a value of 0 to read the first byte returned:
  228. result = SPI.transfer(0x00);
  229. // take the chip select high to de-select:
  230. digitalWrite(chipSelectPin, HIGH);
  231. if (result == 0xFF) {
  232. //we've recieved all ones, report
  233. returnError = IMU_ALL_ONES_WARNING;
  234. }
  235. #endif
  236. break;
  237. default:
  238. break;
  239. }
  240. *outputPointer = result;
  241. return returnError;
  242. }
  243. //****************************************************************************//
  244. //
  245. // readRegisterInt16
  246. //
  247. // Parameters:
  248. // *outputPointer -- Pass &variable (base address of) to save read data to
  249. // offset -- register to read
  250. //
  251. //****************************************************************************//
  252. status_t LSM6DS3Core::readRegisterInt16(int16_t* outputPointer, uint8_t offset) {
  253. uint8_t myBuffer[2] = {0, 0};
  254. status_t returnError = readRegisterRegion(myBuffer, offset, 2); //Does memory transfer
  255. int16_t output = (int16_t)myBuffer[0] | int16_t(myBuffer[1] << 8);
  256. *outputPointer = output;
  257. return returnError;
  258. }
  259. //****************************************************************************//
  260. //
  261. // writeRegister
  262. //
  263. // Parameters:
  264. // offset -- register to write
  265. // dataToWrite -- 8 bit data to write to register
  266. //
  267. //****************************************************************************//
  268. status_t LSM6DS3Core::writeRegister(uint8_t offset, uint8_t dataToWrite) {
  269. status_t returnError = IMU_SUCCESS;
  270. switch (commInterface) {
  271. case I2C_MODE:
  272. //Write the byte
  273. Wire.beginTransmission(I2CAddress);
  274. Wire.write(offset);
  275. Wire.write(dataToWrite);
  276. if (Wire.endTransmission() != 0) {
  277. returnError = IMU_HW_ERROR;
  278. }
  279. break;
  280. case SPI_MODE:
  281. #if defined(NRF52840_XXAA)
  282. // take the chip select low to select the device:
  283. digitalWrite(chipSelectPin, LOW);
  284. // send the device the register you want to read:
  285. SPI.transfer(offset);
  286. // send a value of 0 to read the first byte returned:
  287. SPI.transfer(dataToWrite);
  288. // decrement the number of bytes left to read:
  289. // take the chip select high to de-select:
  290. digitalWrite(chipSelectPin, HIGH);
  291. #endif
  292. break;
  293. //No way to check error on this write (Except to read back but that's not reliable)
  294. default:
  295. break;
  296. }
  297. return returnError;
  298. }
  299. status_t LSM6DS3Core::embeddedPage(void) {
  300. status_t returnError = writeRegister(LSM6DS3_ACC_GYRO_RAM_ACCESS, 0x80);
  301. return returnError;
  302. }
  303. status_t LSM6DS3Core::basePage(void) {
  304. status_t returnError = writeRegister(LSM6DS3_ACC_GYRO_RAM_ACCESS, 0x00);
  305. return returnError;
  306. }
  307. //****************************************************************************//
  308. //
  309. // Main user class -- wrapper for the core class + maths
  310. //
  311. // Construct with same rules as the core ( uint8_t busType, uint8_t inputArg )
  312. //
  313. //****************************************************************************//
  314. LSM6DS3::LSM6DS3(uint8_t busType, uint8_t inputArg) : LSM6DS3Core(busType, inputArg) {
  315. //Construct with these default settings
  316. settings.gyroEnabled = 1; //Can be 0 or 1
  317. settings.gyroRange = 2000; //Max deg/s. Can be: 125, 245, 500, 1000, 2000
  318. settings.gyroSampleRate = 416; //Hz. Can be: 13, 26, 52, 104, 208, 416, 833, 1666
  319. settings.gyroBandWidth = 400; //Hz. Can be: 50, 100, 200, 400;
  320. settings.gyroFifoEnabled = 1; //Set to include gyro in FIFO
  321. settings.gyroFifoDecimation = 1; //set 1 for on /1
  322. settings.accelEnabled = 1;
  323. settings.accelODROff = 1;
  324. settings.accelRange = 16; //Max G force readable. Can be: 2, 4, 8, 16
  325. settings.accelSampleRate = 416; //Hz. Can be: 13, 26, 52, 104, 208, 416, 833, 1666, 3332, 6664, 13330
  326. settings.accelBandWidth = 100; //Hz. Can be: 50, 100, 200, 400;
  327. settings.accelFifoEnabled = 1; //Set to include accelerometer in the FIFO
  328. settings.accelFifoDecimation = 1; //set 1 for on /1
  329. settings.tempEnabled = 1;
  330. //Select interface mode
  331. settings.commMode = 1; //Can be modes 1, 2 or 3
  332. //FIFO control data
  333. settings.fifoThreshold = 2047; //Can be 0 to 2047 (11 bits)
  334. settings.fifoSampleRate = 10; //default 10Hz
  335. settings.fifoModeWord = 0; //Default off
  336. allOnesCounter = 0;
  337. nonSuccessCounter = 0;
  338. }
  339. //****************************************************************************//
  340. //
  341. // Configuration section
  342. //
  343. // This uses the stored SensorSettings to start the IMU
  344. // Use statements such as "myIMU.settings.commInterface = SPI_MODE;" or
  345. // "myIMU.settings.accelEnabled = 1;" to configure before calling .begin();
  346. //
  347. //****************************************************************************//
  348. status_t LSM6DS3::begin() {
  349. //Check the settings structure values to determine how to setup the device
  350. uint8_t dataToWrite = 0; //Temporary variable
  351. //Begin the inherited core. This gets the physical wires connected
  352. status_t returnError = beginCore();
  353. //Setup the accelerometer******************************
  354. dataToWrite = 0; //Start Fresh!
  355. if (settings.accelEnabled == 1) {
  356. //Build config reg
  357. //First patch in filter bandwidth
  358. switch (settings.accelBandWidth) {
  359. case 50:
  360. dataToWrite |= LSM6DS3_ACC_GYRO_BW_XL_50Hz;
  361. break;
  362. case 100:
  363. dataToWrite |= LSM6DS3_ACC_GYRO_BW_XL_100Hz;
  364. break;
  365. case 200:
  366. dataToWrite |= LSM6DS3_ACC_GYRO_BW_XL_200Hz;
  367. break;
  368. default: //set default case to max passthrough
  369. case 400:
  370. dataToWrite |= LSM6DS3_ACC_GYRO_BW_XL_400Hz;
  371. break;
  372. }
  373. //Next, patch in full scale
  374. switch (settings.accelRange) {
  375. case 2:
  376. dataToWrite |= LSM6DS3_ACC_GYRO_FS_XL_2g;
  377. break;
  378. case 4:
  379. dataToWrite |= LSM6DS3_ACC_GYRO_FS_XL_4g;
  380. break;
  381. case 8:
  382. dataToWrite |= LSM6DS3_ACC_GYRO_FS_XL_8g;
  383. break;
  384. default: //set default case to 16(max)
  385. case 16:
  386. dataToWrite |= LSM6DS3_ACC_GYRO_FS_XL_16g;
  387. break;
  388. }
  389. //Lastly, patch in accelerometer ODR
  390. switch (settings.accelSampleRate) {
  391. case 13:
  392. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_13Hz;
  393. break;
  394. case 26:
  395. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_26Hz;
  396. break;
  397. case 52:
  398. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_52Hz;
  399. break;
  400. default: //Set default to 104
  401. case 104:
  402. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_104Hz;
  403. break;
  404. case 208:
  405. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_208Hz;
  406. break;
  407. case 416:
  408. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_416Hz;
  409. break;
  410. case 833:
  411. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_833Hz;
  412. break;
  413. case 1660:
  414. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_1660Hz;
  415. break;
  416. case 3330:
  417. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_3330Hz;
  418. break;
  419. case 6660:
  420. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_6660Hz;
  421. break;
  422. case 13330:
  423. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_13330Hz;
  424. break;
  425. }
  426. } else {
  427. //dataToWrite already = 0 (powerdown);
  428. }
  429. //Now, write the patched together data
  430. writeRegister(LSM6DS3_ACC_GYRO_CTRL1_XL, dataToWrite);
  431. //Set the ODR bit
  432. readRegister(&dataToWrite, LSM6DS3_ACC_GYRO_CTRL4_C);
  433. dataToWrite &= ~((uint8_t)LSM6DS3_ACC_GYRO_BW_SCAL_ODR_ENABLED);
  434. if (settings.accelODROff == 1) {
  435. dataToWrite |= LSM6DS3_ACC_GYRO_BW_SCAL_ODR_ENABLED;
  436. }
  437. writeRegister(LSM6DS3_ACC_GYRO_CTRL4_C, dataToWrite);
  438. //Setup the gyroscope**********************************************
  439. dataToWrite = 0; //Start Fresh!
  440. if (settings.gyroEnabled == 1) {
  441. //Build config reg
  442. //First, patch in full scale
  443. switch (settings.gyroRange) {
  444. case 125:
  445. dataToWrite |= LSM6DS3_ACC_GYRO_FS_125_ENABLED;
  446. break;
  447. case 245:
  448. dataToWrite |= LSM6DS3_ACC_GYRO_FS_G_245dps;
  449. break;
  450. case 500:
  451. dataToWrite |= LSM6DS3_ACC_GYRO_FS_G_500dps;
  452. break;
  453. case 1000:
  454. dataToWrite |= LSM6DS3_ACC_GYRO_FS_G_1000dps;
  455. break;
  456. default: //Default to full 2000DPS range
  457. case 2000:
  458. dataToWrite |= LSM6DS3_ACC_GYRO_FS_G_2000dps;
  459. break;
  460. }
  461. //Lastly, patch in gyro ODR
  462. switch (settings.gyroSampleRate) {
  463. case 13:
  464. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_G_13Hz;
  465. break;
  466. case 26:
  467. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_G_26Hz;
  468. break;
  469. case 52:
  470. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_G_52Hz;
  471. break;
  472. default: //Set default to 104
  473. case 104:
  474. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_G_104Hz;
  475. break;
  476. case 208:
  477. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_G_208Hz;
  478. break;
  479. case 416:
  480. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_G_416Hz;
  481. break;
  482. case 833:
  483. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_G_833Hz;
  484. break;
  485. case 1660:
  486. dataToWrite |= LSM6DS3_ACC_GYRO_ODR_G_1660Hz;
  487. break;
  488. }
  489. } else {
  490. //dataToWrite already = 0 (powerdown);
  491. }
  492. //Write the byte
  493. writeRegister(LSM6DS3_ACC_GYRO_CTRL2_G, dataToWrite);
  494. //Return WHO AM I reg //Not no mo!
  495. uint8_t result;
  496. readRegister(&result, LSM6DS3_ACC_GYRO_WHO_AM_I_REG);
  497. //Setup the internal temperature sensor
  498. if (settings.tempEnabled == 1) {
  499. if (result == LSM6DS3_ACC_GYRO_WHO_AM_I) { //0x69 LSM6DS3
  500. settings.tempSensitivity = 16; // Sensitivity to scale 16
  501. } else if (result == LSM6DS3_C_ACC_GYRO_WHO_AM_I) { //0x6A LSM6dS3-C
  502. settings.tempSensitivity = 256; // Sensitivity to scale 256
  503. }
  504. }
  505. if (settings.timestampEnabled) {
  506. // Enable the timestamp counter (CTRL10_C寄存器)
  507. uint8_t ctrl10_c;
  508. readRegister(&ctrl10_c, LSM6DS3_ACC_GYRO_CTRL10_C);
  509. ctrl10_c |= LSM6DS3_ACC_GYRO_ZEN_G_ENABLED; // set TIMER_EN
  510. writeRegister(LSM6DS3_ACC_GYRO_CTRL10_C, ctrl10_c);
  511. }
  512. return returnError;
  513. }
  514. //****************************************************************************//
  515. //
  516. // Accelerometer section
  517. //
  518. //****************************************************************************//
  519. int16_t LSM6DS3::readRawAccelX(void) {
  520. int16_t output;
  521. status_t errorLevel = readRegisterInt16(&output, LSM6DS3_ACC_GYRO_OUTX_L_XL);
  522. if (errorLevel != IMU_SUCCESS) {
  523. if (errorLevel == IMU_ALL_ONES_WARNING) {
  524. allOnesCounter++;
  525. } else {
  526. nonSuccessCounter++;
  527. }
  528. }
  529. return output;
  530. }
  531. float LSM6DS3::readFloatAccelX(void) {
  532. float output = calcAccel(readRawAccelX());
  533. return output;
  534. }
  535. int16_t LSM6DS3::readRawAccelY(void) {
  536. int16_t output;
  537. status_t errorLevel = readRegisterInt16(&output, LSM6DS3_ACC_GYRO_OUTY_L_XL);
  538. if (errorLevel != IMU_SUCCESS) {
  539. if (errorLevel == IMU_ALL_ONES_WARNING) {
  540. allOnesCounter++;
  541. } else {
  542. nonSuccessCounter++;
  543. }
  544. }
  545. return output;
  546. }
  547. float LSM6DS3::readFloatAccelY(void) {
  548. float output = calcAccel(readRawAccelY());
  549. return output;
  550. }
  551. int16_t LSM6DS3::readRawAccelZ(void) {
  552. int16_t output;
  553. status_t errorLevel = readRegisterInt16(&output, LSM6DS3_ACC_GYRO_OUTZ_L_XL);
  554. if (errorLevel != IMU_SUCCESS) {
  555. if (errorLevel == IMU_ALL_ONES_WARNING) {
  556. allOnesCounter++;
  557. } else {
  558. nonSuccessCounter++;
  559. }
  560. }
  561. return output;
  562. }
  563. float LSM6DS3::readFloatAccelZ(void) {
  564. float output = calcAccel(readRawAccelZ());
  565. return output;
  566. }
  567. float LSM6DS3::calcAccel(int16_t input) {
  568. float output = (float)input * 0.061 * (settings.accelRange >> 1) / 1000;
  569. return output;
  570. }
  571. //****************************************************************************//
  572. //
  573. // Gyroscope section
  574. //
  575. //****************************************************************************//
  576. int16_t LSM6DS3::readRawGyroX(void) {
  577. int16_t output;
  578. status_t errorLevel = readRegisterInt16(&output, LSM6DS3_ACC_GYRO_OUTX_L_G);
  579. if (errorLevel != IMU_SUCCESS) {
  580. if (errorLevel == IMU_ALL_ONES_WARNING) {
  581. allOnesCounter++;
  582. } else {
  583. nonSuccessCounter++;
  584. }
  585. }
  586. return output;
  587. }
  588. float LSM6DS3::readFloatGyroX(void) {
  589. float output = calcGyro(readRawGyroX());
  590. return output;
  591. }
  592. int16_t LSM6DS3::readRawGyroY(void) {
  593. int16_t output;
  594. status_t errorLevel = readRegisterInt16(&output, LSM6DS3_ACC_GYRO_OUTY_L_G);
  595. if (errorLevel != IMU_SUCCESS) {
  596. if (errorLevel == IMU_ALL_ONES_WARNING) {
  597. allOnesCounter++;
  598. } else {
  599. nonSuccessCounter++;
  600. }
  601. }
  602. return output;
  603. }
  604. float LSM6DS3::readFloatGyroY(void) {
  605. float output = calcGyro(readRawGyroY());
  606. return output;
  607. }
  608. int16_t LSM6DS3::readRawGyroZ(void) {
  609. int16_t output;
  610. status_t errorLevel = readRegisterInt16(&output, LSM6DS3_ACC_GYRO_OUTZ_L_G);
  611. if (errorLevel != IMU_SUCCESS) {
  612. if (errorLevel == IMU_ALL_ONES_WARNING) {
  613. allOnesCounter++;
  614. } else {
  615. nonSuccessCounter++;
  616. }
  617. }
  618. return output;
  619. }
  620. float LSM6DS3::readFloatGyroZ(void) {
  621. float output = calcGyro(readRawGyroZ());
  622. return output;
  623. }
  624. float LSM6DS3::calcGyro(int16_t input) {
  625. uint8_t gyroRangeDivisor = settings.gyroRange / 125;
  626. if (settings.gyroRange == 245) {
  627. gyroRangeDivisor = 2;
  628. }
  629. float output = (float)input * 4.375 * (gyroRangeDivisor) / 1000;
  630. return output;
  631. }
  632. //****************************************************************************//
  633. //
  634. // Temperature section
  635. //
  636. //****************************************************************************//
  637. int16_t LSM6DS3::readRawTemp(void) {
  638. int16_t output;
  639. readRegisterInt16(&output, LSM6DS3_ACC_GYRO_OUT_TEMP_L);
  640. return output;
  641. }
  642. float LSM6DS3::readTempC(void) {
  643. float output = (float)readRawTemp() / settings.tempSensitivity; //divide by tempSensitivity to scale
  644. output += 25; //Add 25 degrees to remove offset
  645. return output;
  646. }
  647. float LSM6DS3::readTempF(void) {
  648. float output = (float)readRawTemp() / settings.tempSensitivity; //divide by tempSensitivity to scale
  649. output += 25; //Add 25 degrees to remove offset
  650. output = (output * 9) / 5 + 32;
  651. return output;
  652. }
  653. //****************************************************************************//
  654. //
  655. // Timestamp section
  656. //
  657. //****************************************************************************//
  658. uint32_t LSM6DS3::fifoTimestamp() {
  659. uint8_t data[6];
  660. status_t error = readRegisterRegion(data, LSM6DS3_ACC_GYRO_FIFO_DATA_OUT_L, 3*sizeof(uint16_t));
  661. if (error == IMU_SUCCESS) {
  662. return (data[1] << 16) | (data[0] << 8) | data[3];
  663. }
  664. return 0;
  665. }
  666. //****************************************************************************//
  667. //
  668. // FIFO section
  669. //
  670. //****************************************************************************//
  671. void LSM6DS3::fifoBegin(void) {
  672. //CONFIGURE THE VARIOUS FIFO SETTINGS
  673. //
  674. //
  675. //This section first builds a bunch of config words, then goes through
  676. //and writes them all.
  677. //Split and mask the threshold
  678. uint8_t thresholdLByte = settings.fifoThreshold & 0x00FF;
  679. uint8_t thresholdHByte = (settings.fifoThreshold & 0x0F00) >> 8;
  680. //Pedo bits not configured (ctl2)
  681. // CONFIGURE FIFO_CTRL2
  682. uint8_t tempFIFO_CTRL2 = 0;
  683. readRegister(&tempFIFO_CTRL2, LSM6DS3_ACC_GYRO_FIFO_CTRL2);
  684. if (settings.timestampFifoEnabled == 1) {
  685. // Write timestamp data to the FIFO.
  686. tempFIFO_CTRL2 |= LSM6DS3_ACC_GYRO_TIM_PEDO_FIFO_EN_ENABLED; // FIFO_CTRL2(07H)->TIMER_PEDO_FIFO_EN
  687. // translates to "Set timestamp resolution
  688. uint8_t tap_cfg;
  689. readRegister(&tap_cfg, LSM6DS3_ACC_GYRO_WAKE_UP_DUR);
  690. tap_cfg &= ~(1 << 4);
  691. // timestampResolution
  692. // 0: 6.4ms
  693. // 1: 25us
  694. tap_cfg |= (settings.timestampResolution & 0x01) << 4;
  695. writeRegister(LSM6DS3_ACC_GYRO_WAKE_UP_DUR, tap_cfg);
  696. }
  697. // Adding thresholdHByte to FIFO_CTRL2 register
  698. tempFIFO_CTRL2 &= 0xF0;
  699. tempFIFO_CTRL2 |= (thresholdHByte & 0x0F);
  700. //CONFIGURE FIFO_CTRL3
  701. uint8_t tempFIFO_CTRL3 = 0;
  702. if (settings.gyroFifoEnabled == 1) {
  703. //Set up gyro stuff
  704. //Build on FIFO_CTRL3
  705. //Set decimation
  706. tempFIFO_CTRL3 |= (settings.gyroFifoDecimation & 0x07) << 3;
  707. }
  708. if (settings.accelFifoEnabled == 1) {
  709. //Set up accelerometer stuff
  710. //Build on FIFO_CTRL3
  711. //Set decimation
  712. tempFIFO_CTRL3 |= (settings.accelFifoDecimation & 0x07);
  713. }
  714. // CONFIGURE FIFO_CTRL4
  715. // Select the decimation factor for the 4th FIFO dataset by configuring the DEC_DS4_FIFO[2:0] field in the FIFO_CTRL4 register.
  716. //If you don't need the third and fourth datasets, this value can be set to 0
  717. uint8_t tempFIFO_CTRL4 = 0x09;
  718. //CONFIGURE FIFO_CTRL5
  719. uint8_t tempFIFO_CTRL5 = 0;
  720. switch (settings.fifoSampleRate) {
  721. default: //set default case to 10Hz(slowest)
  722. case 10:
  723. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_10Hz;
  724. break;
  725. case 25:
  726. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_25Hz;
  727. break;
  728. case 50:
  729. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_50Hz;
  730. break;
  731. case 100:
  732. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_100Hz;
  733. break;
  734. case 200:
  735. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_200Hz;
  736. break;
  737. case 400:
  738. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_400Hz;
  739. break;
  740. case 800:
  741. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_800Hz;
  742. break;
  743. case 1600:
  744. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_1600Hz;
  745. break;
  746. case 3300:
  747. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_3300Hz;
  748. break;
  749. case 6600:
  750. tempFIFO_CTRL5 |= LSM6DS3_ACC_GYRO_ODR_FIFO_6600Hz;
  751. break;
  752. }
  753. //Hard code the fifo mode here:
  754. tempFIFO_CTRL5 |= settings.fifoModeWord = 6; //set mode:
  755. //Write the data
  756. writeRegister(LSM6DS3_ACC_GYRO_FIFO_CTRL1, thresholdLByte);
  757. writeRegister(LSM6DS3_ACC_GYRO_FIFO_CTRL2, tempFIFO_CTRL2);
  758. writeRegister(LSM6DS3_ACC_GYRO_FIFO_CTRL3, tempFIFO_CTRL3);
  759. writeRegister(LSM6DS3_ACC_GYRO_FIFO_CTRL4, tempFIFO_CTRL4);
  760. writeRegister(LSM6DS3_ACC_GYRO_FIFO_CTRL5, tempFIFO_CTRL5);
  761. }
  762. void LSM6DS3::fifoClear(void) {
  763. //Drain the fifo data and dump it
  764. while ((fifoGetStatus() & 0x1000) == 0) {
  765. fifoRead();
  766. }
  767. }
  768. int16_t LSM6DS3::fifoRead(void) {
  769. //Pull the last data from the fifo
  770. uint8_t tempReadByte = 0;
  771. uint16_t tempAccumulator = 0;
  772. readRegister(&tempReadByte, LSM6DS3_ACC_GYRO_FIFO_DATA_OUT_L);
  773. tempAccumulator = tempReadByte;
  774. readRegister(&tempReadByte, LSM6DS3_ACC_GYRO_FIFO_DATA_OUT_H);
  775. tempAccumulator |= ((uint16_t)tempReadByte << 8);
  776. return tempAccumulator;
  777. }
  778. uint16_t LSM6DS3::fifoGetStatus(void) {
  779. //Return some data on the state of the fifo
  780. uint8_t tempReadByte = 0;
  781. uint16_t tempAccumulator = 0;
  782. readRegister(&tempReadByte, LSM6DS3_ACC_GYRO_FIFO_STATUS1);
  783. tempAccumulator = tempReadByte;
  784. readRegister(&tempReadByte, LSM6DS3_ACC_GYRO_FIFO_STATUS2);
  785. tempAccumulator |= (tempReadByte << 8);
  786. return tempAccumulator;
  787. }
  788. void LSM6DS3::fifoEnd(void) {
  789. // turn off the fifo
  790. writeRegister(LSM6DS3_ACC_GYRO_FIFO_STATUS1, 0x00); //Disable
  791. }