LSM6DS3.cpp 26 KB

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