AP_InertialSensor_LSM9DS1.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. /*
  2. * This program is free software
  3. */
  4. #include <AP_HAL/AP_HAL.h>
  5. #include "AP_InertialSensor_LSM9DS1.h"
  6. #include <utility>
  7. #include <AP_HAL/GPIO.h>
  8. extern const AP_HAL::HAL& hal;
  9. #define WHO_AM_I 0x68
  10. #define WHO_AM_I_M 0x3D
  11. #define LSM9DS1_DRY_XG_PIN -1
  12. /*
  13. * Accelerometer and Gyroscope registers
  14. */
  15. #define LSM9DS1XG_ACT_THS 0x04
  16. # define LSM9DS1XG_ACT_THS_SLEEP_ON (0x1 << 7)
  17. #define LSM9DS1XG_ACT_DUR 0x05
  18. #define LSM9DS1XG_INT_GEN_CFG_XL 0x06
  19. # define LSM9DS1XG_INT_GEN_CFG_XL_AOI_XL (0x1 << 7)
  20. # define LSM9DS1XG_INT_GEN_CFG_XL_6D (0x1 << 6)
  21. # define LSM9DS1XG_INT_GEN_CFG_XL_ZHIE_XL (0x1 << 5)
  22. # define LSM9DS1XG_INT_GEN_CFG_XL_ZLIE_XL (0x1 << 4)
  23. # define LSM9DS1XG_INT_GEN_CFG_XL_YHIE_XL (0x1 << 3)
  24. # define LSM9DS1XG_INT_GEN_CFG_XL_YLIE_XL (0x1 << 2)
  25. # define LSM9DS1XG_INT_GEN_CFG_XL_XHIE_XL (0x1 << 1)
  26. # define LSM9DS1XG_INT_GEN_CFG_XL_XLIE_XL (0x1 << 0)
  27. #define LSM9DS1XG_INT_GEN_THS_X_XL 0x07
  28. #define LSM9DS1XG_INT_GEN_THS_Y_XL 0x08
  29. #define LSM9DS1XG_INT_GEN_THS_Z_XL 0x09
  30. #define LSM9DS1XG_INT_GEN_DUR_XL 0x0A
  31. # define LSM9DS1XG_INT_GEN_DUR_XL_WAIT_XL (0x1 << 7)
  32. #define LSM9DS1XG_REFERENCE_G 0x0B
  33. #define LSM9DS1XG_INT1_CTRL 0x0C
  34. # define LSM9DS1XG_INT1_CTRL_INT1_IG_G (0x1 << 7)
  35. # define LSM9DS1XG_INT1_CTRL_INT_IG_XL (0x1 << 6)
  36. # define LSM9DS1XG_INT1_CTRL_INT_FSS5 (0x1 << 5)
  37. # define LSM9DS1XG_INT1_CTRL_INT_OVR (0x1 << 4)
  38. # define LSM9DS1XG_INT1_CTRL_INT_FTH (0x1 << 3)
  39. # define LSM9DS1XG_INT1_CTRL_INT_Boot (0x1 << 2)
  40. # define LSM9DS1XG_INT1_CTRL_INT_DRDY_G (0x1 << 1)
  41. # define LSM9DS1XG_INT1_CTRL_INT_DRDY_XL (0x1 << 0)
  42. #define LSM9DS1XG_INT2_CTRL 0x0D
  43. # define LSM9DS1XG_INT2_CTRL_INT2_INACT (0x1 << 7)
  44. # define LSM9DS1XG_INT2_CTRL_INT2_FSS5 (0x1 << 5)
  45. # define LSM9DS1XG_INT2_CTRL_INT2_OVR (0x1 << 4)
  46. # define LSM9DS1XG_INT2_CTRL_INT2_FTH (0x1 << 3)
  47. # define LSM9DS1XG_INT2_CTRL_INT2_DRDY_TEMP (0x1 << 2)
  48. # define LSM9DS1XG_INT2_CTRL_INT2_DRDY_G (0x1 << 1)
  49. # define LSM9DS1XG_INT2_CTRL_INT2_DRDY_XL (0x1 << 0)
  50. #define LSM9DS1XG_WHO_AM_I 0x0F
  51. #define LSM9DS1XG_CTRL_REG1_G 0x10
  52. # define LSM9DS1XG_CTRL_REG1_G_ODR_G_14900mHz (0x1 << 5)
  53. # define LSM9DS1XG_CTRL_REG1_G_ODR_G_59500mHz (0x2 << 5)
  54. # define LSM9DS1XG_CTRL_REG1_G_ODR_G_119Hz (0x3 << 5)
  55. # define LSM9DS1XG_CTRL_REG1_G_ODR_G_238Hz (0x4 << 5)
  56. # define LSM9DS1XG_CTRL_REG1_G_ODR_G_476Hz (0x5 << 5)
  57. # define LSM9DS1XG_CTRL_REG1_G_ODR_G_952Hz (0x6 << 5)
  58. # define LSM9DS1XG_CTRL_REG1_FS_G_245DPS (0x0 << 3)
  59. # define LSM9DS1XG_CTRL_REG1_FS_G_500DPS (0x1 << 3)
  60. # define LSM9DS1XG_CTRL_REG1_FS_G_2000DPS (0x3 << 3)
  61. #define LSM9DS1XG_CTRL_REG2_G 0x11
  62. # define LSM9DS1XG_CTRL_REG2_G_INT_SEL_00 (0x0 << 2)
  63. # define LSM9DS1XG_CTRL_REG2_G_INT_SEL_01 (0x1 << 2)
  64. # define LSM9DS1XG_CTRL_REG2_G_INT_SEL_10 (0x2 << 2)
  65. # define LSM9DS1XG_CTRL_REG2_G_INT_SEL_11 (0x3 << 2)
  66. # define LSM9DS1XG_CTRL_REG2_G_OUT_SEL_00 (0x0 << 0)
  67. # define LSM9DS1XG_CTRL_REG2_G_OUT_SEL_01 (0x1 << 0)
  68. # define LSM9DS1XG_CTRL_REG2_G_OUT_SEL_10 (0x2 << 0)
  69. # define LSM9DS1XG_CTRL_REG2_G_OUT_SEL_11 (0x3 << 0)
  70. #define LSM9DS1XG_CTRL_REG3_G 0x12
  71. # define LSM9DS1XG_CTRL_REG3_G_LP_MODE (0x1 << 7)
  72. # define LSM9DS1XG_CTRL_REG3_G_HP_EN (0x1 << 6)
  73. #define LSM9DS1XG_ORIENT_CFG_G 0x13
  74. #define LSM9DS1XG_INT_GEN_SRC_G 0x14
  75. # define LSM9DS1XG_INT_GEN_SRC_G_IA_G (0x1 << 6)
  76. # define LSM9DS1XG_INT_GEN_SRC_G_ZH_G (0x1 << 5)
  77. # define LSM9DS1XG_INT_GEN_SRC_G_ZL_G (0x1 << 4)
  78. # define LSM9DS1XG_INT_GEN_SRC_G_YH_G (0x1 << 3)
  79. # define LSM9DS1XG_INT_GEN_SRC_G_YL_G (0x1 << 2)
  80. # define LSM9DS1XG_INT_GEN_SRC_G_XH_G (0x1 << 1)
  81. # define LSM9DS1XG_INT_GEN_SRC_G_XL_G (0x1 << 0)
  82. #define LSM9DS1XG_OUT_TEMP_L 0x15
  83. #define LSM9DS1XG_OUT_TEMP_H 0x16
  84. #define LSM9DS1XG_STATUS_REG 0x17
  85. # define LSM9DS1XG_STATUS_REG_IG_XL (0x1 << 6)
  86. # define LSM9DS1XG_STATUS_REG_IG_G (0x1 << 5)
  87. # define LSM9DS1XG_STATUS_REG_INACT (0x1 << 4)
  88. # define LSM9DS1XG_STATUS_REG_BOOT_STATUS (0x1 << 3)
  89. # define LSM9DS1XG_STATUS_REG_TDA (0x1 << 2)
  90. # define LSM9DS1XG_STATUS_REG_GDA (0x1 << 1)
  91. # define LSM9DS1XG_STATUS_REG_XLDA (0x1 << 0)
  92. #define LSM9DS1XG_OUT_X_L_G 0x18
  93. #define LSM9DS1XG_OUT_X_H_G 0x19
  94. #define LSM9DS1XG_OUT_Y_L_G 0x1A
  95. #define LSM9DS1XG_OUT_Y_H_G 0x1B
  96. #define LSM9DS1XG_OUT_Z_L_G 0x1C
  97. #define LSM9DS1XG_OUT_Z_H_G 0x1D
  98. #define LSM9DS1XG_CTRL_REG4 0x1E
  99. # define LSM9DS1XG_CTRL_REG4_Zen_G (0x1 << 5)
  100. # define LSM9DS1XG_CTRL_REG4_Yen_G (0x1 << 4)
  101. # define LSM9DS1XG_CTRL_REG4_Xen_G (0x1 << 3)
  102. # define LSM9DS1XG_CTRL_REG4_LIR_XL1 (0x1 << 1)
  103. # define LSM9DS1XG_CTRL_REG4_4D_XL1 (0x1 << 0)
  104. #define LSM9DS1XG_CTRL_REG5_XL 0x1F
  105. # define LSM9DS1XG_CTRL_REG5_XL_Zen_XL (0x1 << 5)
  106. # define LSM9DS1XG_CTRL_REG5_XL_Yen_XL (0x1 << 4)
  107. # define LSM9DS1XG_CTRL_REG5_XL_Xen_XL (0x1 << 3)
  108. #define LSM9DS1XG_CTRL_REG6_XL 0x20
  109. # define LSM9DS1XG_CTRL_REG6_XL_ODR_XL_10Hz (0x1 << 5)
  110. # define LSM9DS1XG_CTRL_REG6_XL_ODR_XL_50Hz (0x2 << 5)
  111. # define LSM9DS1XG_CTRL_REG6_XL_ODR_XL_119Hz (0x3 << 5)
  112. # define LSM9DS1XG_CTRL_REG6_XL_ODR_XL_238Hz (0x4 << 5)
  113. # define LSM9DS1XG_CTRL_REG6_XL_ODR_XL_476Hz (0x5 << 5)
  114. # define LSM9DS1XG_CTRL_REG6_XL_ODR_XL_952Hz (0x6 << 5)
  115. # define LSM9DS1XG_CTRL_REG6_XL_FS_XL_2G (0x0 << 3)
  116. # define LSM9DS1XG_CTRL_REG6_XL_FS_XL_16G (0x1 << 3)
  117. # define LSM9DS1XG_CTRL_REG6_XL_FS_XL_4G (0x2 << 3)
  118. # define LSM9DS1XG_CTRL_REG6_XL_FS_XL_8G (0x3 << 3)
  119. # define LSM9DS1XG_CTRL_REG6_XL_BW_SCAL_ODR (0x1 << 2)
  120. # define LSM9DS1XG_CTRL_REG6_XL_BW_XL_408Hz (0x0 << 0)
  121. # define LSM9DS1XG_CTRL_REG6_XL_BW_XL_211Hz (0x1 << 0)
  122. # define LSM9DS1XG_CTRL_REG6_XL_BW_XL_105Hz (0x2 << 0)
  123. # define LSM9DS1XG_CTRL_REG6_XL_BW_XL_50Hz (0x3 << 0)
  124. #define LSM9DS1XG_CTRL_REG7_XL 0x21
  125. # define LSM9DS1XG_CTRL_REG7_XL_FDS (0x1 << 2)
  126. # define LSM9DS1XG_CTRL_REG7_XL_HPIS1 (0x1 << 0)
  127. #define LSM9DS1XG_CTRL_REG8 0x22
  128. # define LSM9DS1XG_CTRL_REG8_BOOT (0x1 << 7)
  129. # define LSM9DS1XG_CTRL_REG8_BDU (0x1 << 6)
  130. # define LSM9DS1XG_CTRL_REG8_H_LACTIVE (0x1 << 5)
  131. # define LSM9DS1XG_CTRL_REG8_PP_OD (0x1 << 4)
  132. # define LSM9DS1XG_CTRL_REG8_SIM (0x1 << 3)
  133. # define LSM9DS1XG_CTRL_REG8_IF_ADD_INC (0x1 << 2)
  134. # define LSM9DS1XG_CTRL_REG8_BLE (0x1 << 1)
  135. # define LSM9DS1XG_CTRL_REG8_SW_RESET (0x1 << 0)
  136. #define LSM9DS1XG_CTRL_REG9 0x23
  137. # define LSM9DS1XG_CTRL_REG9_SLEEP_G (0x1 << 6)
  138. # define LSM9DS1XG_CTRL_REG9_FIFO_TEMP_EN (0x1 << 4)
  139. # define LSM9DS1XG_CTRL_REG9_DRDY_mask_bit (0x1 << 3)
  140. # define LSM9DS1XG_CTRL_REG9_I2C_DISABLE (0x1 << 2)
  141. # define LSM9DS1XG_CTRL_REG9_FIFO_EN (0x1 << 1)
  142. # define LSM9DS1XG_CTRL_REG9_STOP_ON_FTH (0x1 << 0)
  143. #define LSM9DS1XG_CTRL_REG10 0x24
  144. # define LSM9DS1XG_CTRL_REG10_ST_G (0x1 << 2)
  145. # define LSM9DS1XG_CTRL_REG10_ST_XL (0x1 << 0)
  146. #define LSM9DS1XG_INT_GEN_SRC_XL 0x26
  147. # define LSM9DS1XG_INT_GEN_SRC_XL_IA_XL (0x1 << 6)
  148. # define LSM9DS1XG_INT_GEN_SRC_XL_ZH_XL (0x1 << 5)
  149. # define LSM9DS1XG_INT_GEN_SRC_XL_ZL_XL (0x1 << 4)
  150. # define LSM9DS1XG_INT_GEN_SRC_XL_YH_XL (0x1 << 3)
  151. # define LSM9DS1XG_INT_GEN_SRC_XL_YL_XL (0x1 << 2)
  152. # define LSM9DS1XG_INT_GEN_SRC_XL_XH_XL (0x1 << 1)
  153. # define LSM9DS1XG_INT_GEN_SRC_XL_XL_XL (0x1 << 0)
  154. //#define LSM9DS1XG_STATUS_REG 0x27 //repeat
  155. #define LSM9DS1XG_OUT_X_L_XL 0x28
  156. #define LSM9DS1XG_OUT_X_H_XL 0x29
  157. #define LSM9DS1XG_OUT_Y_L_XL 0x2A
  158. #define LSM9DS1XG_OUT_Y_H_XL 0x2B
  159. #define LSM9DS1XG_OUT_Z_L_XL 0x2C
  160. #define LSM9DS1XG_OUT_Z_H_XL 0x2D
  161. #define LSM9DS1XG_FIFO_CTRL 0x2E
  162. # define LSM9DS1XG_FIFO_CTRL_FMODE_BYPASS (0x0 << 5)
  163. # define LSM9DS1XG_FIFO_CTRL_FMODE_FIFO (0x1 << 5)
  164. # define LSM9DS1XG_FIFO_CTRL_FMODE_STREAM (0x3 << 5)
  165. # define LSM9DS1XG_FIFO_CTRL_FMODE_B_TO_S (0x4 << 5)
  166. # define LSM9DS1XG_FIFO_CTRL_FMODE_CON (0x5 << 5)
  167. #define LSM9DS1XG_FIFO_SRC 0x2F
  168. # define LSM9DS1XG_FIFO_SRC_FTH (0x1 << 7)
  169. # define LSM9DS1XG_FIFO_SRC_OVRN (0x1 << 6)
  170. # define LSM9DS1XG_FIFO_SRC_UNREAD_SAMPLES 0x3F
  171. #define LSM9DS1XG_INT_GEN_CFG_G 0x30
  172. # define LSM9DS1XG_INT_GEN_CFG_G_AOI_G (0x1 << 7)
  173. # define LSM9DS1XG_INT_GEN_CFG_G_LIR_G (0x1 << 6)
  174. # define LSM9DS1XG_INT_GEN_CFG_G_ZHIE_G (0x1 << 5)
  175. # define LSM9DS1XG_INT_GEN_CFG_G_ZLIE_G (0x1 << 4)
  176. # define LSM9DS1XG_INT_GEN_CFG_G_YHIE_G (0x1 << 3)
  177. # define LSM9DS1XG_INT_GEN_CFG_G_YLIE_G (0x1 << 2)
  178. # define LSM9DS1XG_INT_GEN_CFG_G_XHIE_G (0x1 << 1)
  179. # define LSM9DS1XG_INT_GEN_CFG_G_XLIE_G (0x1 << 0)
  180. #define LSM9DS1XG_INT_GEN_THS_XH_G 0x31
  181. # define LSM9DS1XG_INT_GEN_THS_XH_G_DCRM_G (0x1 << 7)
  182. #define LSM9DS1XG_INT_GEN_THS_XL_G 0x32
  183. #define LSM9DS1XG_INT_GEN_THS_YH_G 0x33
  184. #define LSM9DS1XG_INT_GEN_THS_YL_G 0x34
  185. #define LSM9DS1XG_INT_GEN_THS_ZH_G 0x35
  186. #define LSM9DS1XG_INT_GEN_THS_ZL_G 0x36
  187. #define LSM9DS1XG_INT_GEN_DUR_G 0x37
  188. # define LSM9DS1XG_INT_GEN_DUR_G_WAIT_G (0x1 << 7)
  189. AP_InertialSensor_LSM9DS1::AP_InertialSensor_LSM9DS1(AP_InertialSensor &imu,
  190. AP_HAL::OwnPtr<AP_HAL::SPIDevice> dev,
  191. int drdy_pin_num_xg,
  192. enum Rotation rotation)
  193. : AP_InertialSensor_Backend(imu)
  194. , _dev(std::move(dev))
  195. , _drdy_pin_num_xg(drdy_pin_num_xg)
  196. , _rotation(rotation)
  197. {
  198. }
  199. AP_InertialSensor_Backend *AP_InertialSensor_LSM9DS1::probe(AP_InertialSensor &_imu,
  200. AP_HAL::OwnPtr<AP_HAL::SPIDevice> dev,
  201. enum Rotation rotation)
  202. {
  203. if (!dev) {
  204. return nullptr;
  205. }
  206. AP_InertialSensor_LSM9DS1 *sensor =
  207. new AP_InertialSensor_LSM9DS1(_imu,std::move(dev),
  208. LSM9DS1_DRY_XG_PIN,
  209. rotation);
  210. if (!sensor || !sensor->_init_sensor()) {
  211. delete sensor;
  212. return nullptr;
  213. }
  214. return sensor;
  215. }
  216. bool AP_InertialSensor_LSM9DS1::_init_sensor()
  217. {
  218. _spi_sem = _dev->get_semaphore();
  219. if (_drdy_pin_num_xg >= 0) {
  220. _drdy_pin_xg = hal.gpio->channel(_drdy_pin_num_xg);
  221. if (_drdy_pin_xg == nullptr) {
  222. AP_HAL::panic("LSM9DS1: null accel data-ready GPIO channel\n");
  223. }
  224. _drdy_pin_xg->mode(HAL_GPIO_INPUT);
  225. }
  226. bool success = _hardware_init();
  227. #if LSM9DS1_DEBUG
  228. _dump_registers();
  229. #endif
  230. return success;
  231. }
  232. bool AP_InertialSensor_LSM9DS1::_hardware_init()
  233. {
  234. if (!_spi_sem->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
  235. return false;
  236. }
  237. uint8_t tries, whoami;
  238. // set flag for reading registers
  239. _dev->set_read_flag(0x80);
  240. whoami = _register_read(LSM9DS1XG_WHO_AM_I);
  241. if (whoami != WHO_AM_I) {
  242. hal.console->printf("LSM9DS1: unexpected acc/gyro WHOAMI 0x%x\n", whoami);
  243. goto fail_whoami;
  244. }
  245. _fifo_reset();
  246. for (tries = 0; tries < 5; tries++) {
  247. _dev->set_speed(AP_HAL::Device::SPEED_LOW);
  248. _gyro_init();
  249. _accel_init();
  250. _dev->set_speed(AP_HAL::Device::SPEED_HIGH);
  251. hal.scheduler->delay(10);
  252. int samples = _register_read(LSM9DS1XG_FIFO_SRC);
  253. //if samples == 0 -> FIFO empty
  254. if (samples > 1) {
  255. break;
  256. }
  257. #if LSM9DS1_DEBUG
  258. _dump_registers();
  259. #endif
  260. }
  261. if (tries == 5) {
  262. hal.console->printf("Failed to boot LSM9DS1 5 times\n\n");
  263. goto fail_tries;
  264. }
  265. _spi_sem->give();
  266. return true;
  267. fail_tries:
  268. fail_whoami:
  269. _spi_sem->give();
  270. return false;
  271. }
  272. void AP_InertialSensor_LSM9DS1::_fifo_reset()
  273. {
  274. _dev->set_speed(AP_HAL::Device::SPEED_LOW);
  275. //Disable FIFO
  276. int reg_9 = _register_read(LSM9DS1XG_CTRL_REG9);
  277. _dev->write_register(LSM9DS1XG_CTRL_REG9, reg_9 & ~0x02);
  278. //Enable Bypass for reset FIFO
  279. _dev->write_register(LSM9DS1XG_FIFO_CTRL, LSM9DS1XG_FIFO_CTRL_FMODE_BYPASS);
  280. //Enable FIFO and Disable I2C
  281. _dev->write_register(LSM9DS1XG_CTRL_REG9,LSM9DS1XG_CTRL_REG9_FIFO_EN | LSM9DS1XG_CTRL_REG9_I2C_DISABLE);
  282. //Enable block data update, allow auto-increment during multiple byte read
  283. _dev->write_register(LSM9DS1XG_CTRL_REG8, LSM9DS1XG_CTRL_REG8_BDU | LSM9DS1XG_CTRL_REG8_IF_ADD_INC);
  284. hal.scheduler->delay_microseconds(1);
  285. //Enable FIFO stream mode and set watermark at 32 samples
  286. _dev->write_register(LSM9DS1XG_FIFO_CTRL, 0x1F | LSM9DS1XG_FIFO_CTRL_FMODE_FIFO);
  287. hal.scheduler->delay_microseconds(1);
  288. _dev->set_speed(AP_HAL::Device::SPEED_HIGH);
  289. notify_accel_fifo_reset(_accel_instance);
  290. notify_gyro_fifo_reset(_gyro_instance);
  291. }
  292. /*
  293. start the sensor going
  294. */
  295. void AP_InertialSensor_LSM9DS1::start(void)
  296. {
  297. _gyro_instance = _imu.register_gyro(952, _dev->get_bus_id_devtype(DEVTYPE_GYR_LSM9DS1));
  298. _accel_instance = _imu.register_accel(952, _dev->get_bus_id_devtype(DEVTYPE_ACC_LSM9DS1));
  299. set_accel_orientation(_accel_instance, _rotation);
  300. set_gyro_orientation(_gyro_instance, _rotation);
  301. _set_accel_max_abs_offset(_accel_instance, 5.0f);
  302. /* start the timer process to read samples */
  303. _dev->register_periodic_callback(1000, FUNCTOR_BIND_MEMBER(&AP_InertialSensor_LSM9DS1::_poll_data, void));
  304. }
  305. uint8_t AP_InertialSensor_LSM9DS1::_register_read(uint8_t reg)
  306. {
  307. uint8_t val = 0;
  308. _dev->read_registers(reg, &val, 1);
  309. return val;
  310. }
  311. void AP_InertialSensor_LSM9DS1::_register_write(uint8_t reg, uint8_t val, bool checked)
  312. {
  313. _dev->write_register(reg, val, checked);
  314. }
  315. void AP_InertialSensor_LSM9DS1::_gyro_init()
  316. {
  317. _register_write(LSM9DS1XG_CTRL_REG1_G, LSM9DS1XG_CTRL_REG1_G_ODR_G_952Hz |
  318. LSM9DS1XG_CTRL_REG1_FS_G_2000DPS);
  319. hal.scheduler->delay(1);
  320. _register_write(LSM9DS1XG_CTRL_REG4, LSM9DS1XG_CTRL_REG4_Zen_G |
  321. LSM9DS1XG_CTRL_REG4_Yen_G |
  322. LSM9DS1XG_CTRL_REG4_Xen_G);
  323. _set_gyro_scale();
  324. hal.scheduler->delay(1);
  325. }
  326. void AP_InertialSensor_LSM9DS1::_accel_init()
  327. {
  328. _register_write(LSM9DS1XG_CTRL_REG6_XL, LSM9DS1XG_CTRL_REG6_XL_ODR_XL_952Hz |
  329. LSM9DS1XG_CTRL_REG6_XL_FS_XL_16G);
  330. hal.scheduler->delay(1);
  331. _register_write(LSM9DS1XG_CTRL_REG5_XL, LSM9DS1XG_CTRL_REG5_XL_Zen_XL |
  332. LSM9DS1XG_CTRL_REG5_XL_Yen_XL |
  333. LSM9DS1XG_CTRL_REG5_XL_Xen_XL);
  334. _set_accel_scale(A_SCALE_16G);
  335. hal.scheduler->delay(1);
  336. }
  337. void AP_InertialSensor_LSM9DS1::_set_gyro_scale()
  338. {
  339. /* scale value from datasheet 2000 mdps/digit */
  340. _gyro_scale = 70;
  341. /* convert mdps/digit to dps/digit */
  342. _gyro_scale /= 1000;
  343. /* convert dps/digit to (rad/s)/digit */
  344. _gyro_scale *= DEG_TO_RAD;
  345. }
  346. void AP_InertialSensor_LSM9DS1::_set_accel_scale(accel_scale scale)
  347. {
  348. /*
  349. * Possible accelerometer scales (and their register bit settings) are:
  350. * 2 g (000), 4g (001), 6g (010) 8g (011), 16g (100). Here's a bit of an
  351. * algorithm to calculate g/(ADC tick) based on that 3-bit value:
  352. */
  353. _accel_scale = (((float) scale + 1.0f) * 2.0f) / 32768.0f;
  354. if (scale == A_SCALE_16G) {
  355. /* the datasheet shows an exception for +-16G */
  356. _accel_scale = 0.000732f;
  357. }
  358. /* convert to G/LSB to (m/s/s)/LSB */
  359. _accel_scale *= GRAVITY_MSS;
  360. }
  361. /**
  362. * Timer process to poll for new data from the LSM9DS1.
  363. */
  364. void AP_InertialSensor_LSM9DS1::_poll_data()
  365. {
  366. uint16_t samples = _register_read(LSM9DS1XG_FIFO_SRC);
  367. samples = samples & LSM9DS1XG_FIFO_SRC_UNREAD_SAMPLES;
  368. if (samples > 1) {
  369. _read_data_transaction_g(samples);
  370. _read_data_transaction_x(samples);
  371. }
  372. if (samples == 32) {
  373. _fifo_reset();
  374. }
  375. // check next register value for correctness
  376. if (!_dev->check_next_register()) {
  377. _inc_accel_error_count(_accel_instance);
  378. }
  379. }
  380. void AP_InertialSensor_LSM9DS1::_read_data_transaction_x(uint16_t samples)
  381. {
  382. struct sensor_raw_data raw_data = { };
  383. int32_t _accel_bias[3] = {0, 0, 0};
  384. const uint8_t _reg = LSM9DS1XG_OUT_X_L_XL | 0x80;
  385. // Read the accel data stored in the FIFO
  386. for (int i = 0; i < samples; i++)
  387. {
  388. struct sensor_raw_data raw_data_temp = { };
  389. if (!_dev->transfer(&_reg, 1, (uint8_t *) &raw_data_temp, sizeof(raw_data_temp))) {
  390. hal.console->printf("LSM9DS1: error reading accelerometer\n");
  391. return;
  392. }
  393. _accel_bias[0] += (int32_t) raw_data_temp.x; // Sum individual signed 16-bit biases to get accumulated signed 32-bit biases
  394. _accel_bias[1] += (int32_t) raw_data_temp.y;
  395. _accel_bias[2] += (int32_t) raw_data_temp.z;
  396. }
  397. raw_data.x = _accel_bias[0] / samples; // average the data
  398. raw_data.y = _accel_bias[1] / samples;
  399. raw_data.z = _accel_bias[2] / samples;
  400. Vector3f accel_data(raw_data.x, raw_data.y, -raw_data.z);
  401. accel_data *= _accel_scale;
  402. _rotate_and_correct_accel(_accel_instance, accel_data);
  403. _notify_new_accel_raw_sample(_accel_instance, accel_data);
  404. }
  405. /*
  406. * read from the data registers and update filtered data
  407. */
  408. void AP_InertialSensor_LSM9DS1::_read_data_transaction_g(uint16_t samples)
  409. {
  410. struct sensor_raw_data raw_data = { };
  411. int32_t _gyro_bias[3] = {0, 0, 0};
  412. const uint8_t _reg = LSM9DS1XG_OUT_X_L_G | 0x80;
  413. // Read the gyro data stored in the FIFO
  414. for (int i = 0; i < samples; i++)
  415. {
  416. struct sensor_raw_data raw_data_temp = { };
  417. if (!_dev->transfer(&_reg, 1, (uint8_t *) &raw_data_temp, sizeof(raw_data_temp))) {
  418. hal.console->printf("LSM9DS1: error reading gyroscope\n");
  419. return;
  420. }
  421. _gyro_bias[0] += (int32_t) raw_data_temp.x; // Sum individual signed 16-bit biases to get accumulated signed 32-bit biases
  422. _gyro_bias[1] += (int32_t) raw_data_temp.y;
  423. _gyro_bias[2] += (int32_t) raw_data_temp.z;
  424. }
  425. raw_data.x = _gyro_bias[0] / samples; // average the data
  426. raw_data.y = _gyro_bias[1] / samples;
  427. raw_data.z = _gyro_bias[2] / samples;
  428. Vector3f gyro_data(raw_data.x, raw_data.y, -raw_data.z);
  429. gyro_data *= _gyro_scale;
  430. _rotate_and_correct_gyro(_gyro_instance, gyro_data);
  431. _notify_new_gyro_raw_sample(_gyro_instance, gyro_data);
  432. }
  433. bool AP_InertialSensor_LSM9DS1::update()
  434. {
  435. update_gyro(_gyro_instance);
  436. update_accel(_accel_instance);
  437. return true;
  438. }
  439. #if LSM9DS1_DEBUG
  440. /*
  441. * dump all config registers - used for debug
  442. */
  443. void AP_InertialSensor_LSM9DS1::_dump_registers(void)
  444. {
  445. hal.console->println("LSM9DS1 registers:");
  446. const uint8_t first = LSM9DS1XG_ACT_THS;
  447. const uint8_t last = LSM9DS1XG_INT_GEN_DUR_G;
  448. for (uint8_t reg=first; reg<=last; reg++) {
  449. uint8_t v = _register_read(reg);
  450. hal.console->printf("%02x:%02x ", reg, v);
  451. if ((reg - (first-1)) % 16 == 0) {
  452. hal.console->println();
  453. }
  454. }
  455. hal.console->println();
  456. }
  457. #endif