ICM20789.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. minimal test program for ICM20789 baro with IMU on SPI and baro on I2C
  3. */
  4. #include <AP_HAL/AP_HAL.h>
  5. #include <AP_HAL/I2CDevice.h>
  6. #include <AP_Baro/AP_Baro.h>
  7. #include <AP_BoardConfig/AP_BoardConfig.h>
  8. #include <utility>
  9. #include <stdio.h>
  10. const AP_HAL::HAL& hal = AP_HAL::get_HAL();
  11. static AP_HAL::OwnPtr<AP_HAL::Device> i2c_dev;
  12. static AP_HAL::OwnPtr<AP_HAL::Device> spi_dev;
  13. static AP_HAL::OwnPtr<AP_HAL::Device> dev;
  14. // SPI registers
  15. #define MPUREG_WHOAMI 0x75
  16. #define MPUREG_USER_CTRL 0x6A
  17. #define MPUREG_PWR_MGMT_1 0x6B
  18. #define MPUREG_INT_PIN_CFG 0x37
  19. # define BIT_BYPASS_EN 0x02
  20. # define BIT_INT_RD_CLEAR 0x10 // clear the interrupt when any read occurs
  21. # define BIT_LATCH_INT_EN 0x20 // latch data ready pin
  22. #define BIT_USER_CTRL_I2C_MST_EN 0x20 // Enable MPU to act as the I2C Master to external slave sensors
  23. #define BIT_PWR_MGMT_1_DEVICE_RESET 0x80 // reset entire device
  24. #define BIT_USER_CTRL_I2C_IF_DIS 0x10 // Disable primary I2C interface and enable hal.spi->interface
  25. #define BIT_PWR_MGMT_1_CLK_XGYRO 0x01 // PLL with X axis gyroscope reference
  26. #define BIT_PWR_MGMT_1_CLK_ZGYRO 0x03 // PLL with Z axis gyroscope reference
  27. // baro commands
  28. #define CMD_SOFT_RESET 0x805D
  29. #define CMD_READ_ID 0xEFC8
  30. void setup(void);
  31. void loop(void);
  32. #ifdef HAL_INS_MPU60x0_NAME
  33. static void spi_init()
  34. {
  35. // SPI reads have flag 0x80 set
  36. spi_dev->set_read_flag(0x80);
  37. // run the SPI bus at low speed
  38. spi_dev->set_speed(AP_HAL::Device::SPEED_LOW);
  39. uint8_t whoami = 0;
  40. uint8_t v;
  41. spi_dev->write_register(0x6B, 0x01);
  42. spi_dev->write_register(0x6B, 0x01);
  43. hal.scheduler->delay(1);
  44. spi_dev->write_register(0x6A, 0x10);
  45. spi_dev->write_register(0x6B, 0x41);
  46. hal.scheduler->delay(1);
  47. spi_dev->write_register(0x6C, 0x3f);
  48. spi_dev->write_register(0xF5, 0x00);
  49. spi_dev->write_register(0x19, 0x09);
  50. spi_dev->write_register(0xEA, 0x00);
  51. spi_dev->write_register(0x6B, 0x01);
  52. hal.scheduler->delay(1);
  53. spi_dev->write_register(0x6A, 0x10);
  54. spi_dev->write_register(0x6B, 0x41);
  55. hal.scheduler->delay(1);
  56. spi_dev->write_register(0x6B, 0x01);
  57. hal.scheduler->delay(1);
  58. spi_dev->write_register(0x23, 0x00);
  59. spi_dev->write_register(0x6B, 0x41);
  60. hal.scheduler->delay(1);
  61. spi_dev->write_register(0x1D, 0xC0);
  62. spi_dev->write_register(0x6B, 0x01);
  63. hal.scheduler->delay(1);
  64. spi_dev->write_register(0x1A, 0xC0);
  65. spi_dev->write_register(0x6B, 0x41);
  66. hal.scheduler->delay(1);
  67. spi_dev->write_register(0x38, 0x01);
  68. spi_dev->read_registers(0x6A, &v, 1);
  69. printf("reg 0x6A=0x%02x\n", v);
  70. spi_dev->read_registers(0x6B, &v, 1);
  71. printf("reg 0x6B=0x%02x\n", v);
  72. hal.scheduler->delay(1);
  73. spi_dev->write_register(0x6A, 0x10);
  74. spi_dev->write_register(0x6B, 0x41);
  75. hal.scheduler->delay(1);
  76. spi_dev->write_register(0x6B, 0x01);
  77. hal.scheduler->delay(1);
  78. spi_dev->write_register(0x23, 0x00);
  79. spi_dev->write_register(0x6B, 0x41);
  80. hal.scheduler->delay(1);
  81. spi_dev->write_register(0x6B, 0x41);
  82. spi_dev->write_register(0x6C, 0x3f);
  83. spi_dev->write_register(0x6B, 0x41);
  84. spi_dev->read_registers(0x6A, &v, 1);
  85. printf("reg 0x6A=0x%02x\n", v);
  86. spi_dev->write_register(0x6B, 0x01);
  87. hal.scheduler->delay(1);
  88. spi_dev->write_register(0x6A, 0x10);
  89. spi_dev->write_register(0x6B, 0x41);
  90. hal.scheduler->delay(1);
  91. spi_dev->write_register(0x6B, 0x01);
  92. hal.scheduler->delay(1);
  93. spi_dev->write_register(0x23, 0x00);
  94. spi_dev->write_register(0x6B, 0x41);
  95. hal.scheduler->delay(1);
  96. spi_dev->read_registers(0x6A, &v, 1);
  97. printf("reg 0x6A=0x%02x\n", v);
  98. spi_dev->write_register(0x6B, 0x01);
  99. hal.scheduler->delay(1);
  100. spi_dev->write_register(0x6A, 0x10);
  101. spi_dev->write_register(0x6B, 0x41);
  102. hal.scheduler->delay(1);
  103. spi_dev->write_register(0x6B, 0x01);
  104. hal.scheduler->delay(1);
  105. spi_dev->write_register(0x23, 0x00);
  106. spi_dev->write_register(0x6B, 0x41);
  107. hal.scheduler->delay(1);
  108. spi_dev->write_register(0x6B, 0x41);
  109. spi_dev->write_register(0x6C, 0x3f);
  110. spi_dev->write_register(0x6B, 0x41);
  111. spi_dev->read_registers(0x6A, &v, 1);
  112. printf("reg 0x6A=0x%02x\n", v);
  113. spi_dev->write_register(0x6B, 0x01);
  114. hal.scheduler->delay(1);
  115. spi_dev->write_register(0x6A, 0x10);
  116. spi_dev->write_register(0x6B, 0x41);
  117. hal.scheduler->delay(1);
  118. spi_dev->write_register(0x6B, 0x01);
  119. hal.scheduler->delay(1);
  120. spi_dev->write_register(0x23, 0x00);
  121. spi_dev->write_register(0x6B, 0x41);
  122. // print the WHOAMI
  123. spi_dev->read_registers(MPUREG_WHOAMI, &whoami, 1);
  124. printf("20789 SPI whoami: 0x%02x\n", whoami);
  125. // wait for sensor to settle
  126. hal.scheduler->delay(100);
  127. // dump registers
  128. printf("ICM20789 registers\n");
  129. #if 0
  130. for (uint8_t reg = 0; reg<0x80; reg++) {
  131. v=0;
  132. spi_dev->read_registers(reg, &v, 1);
  133. printf("%02x:%02x ", (unsigned)reg, (unsigned)v);
  134. if ((reg+1) % 16 == 0) {
  135. printf("\n");
  136. }
  137. }
  138. printf("\n");
  139. #endif
  140. spi_dev->get_semaphore()->give();
  141. }
  142. #endif
  143. /*
  144. send a 16 bit command to the baro
  145. */
  146. static bool send_cmd16(uint16_t cmd)
  147. {
  148. uint8_t cmd_b[2] = { uint8_t(cmd >> 8), uint8_t(cmd & 0xFF) };
  149. return i2c_dev->transfer(cmd_b, 2, nullptr, 0);
  150. }
  151. /*
  152. read baro calibration data
  153. */
  154. static bool read_calibration_data(void)
  155. {
  156. // setup for OTP read
  157. const uint8_t cmd[5] = { 0xC5, 0x95, 0x00, 0x66, 0x9C };
  158. if (!i2c_dev->transfer(cmd, sizeof(cmd), nullptr, 0)) {
  159. return false;
  160. }
  161. for (uint8_t i=0; i<4; i++) {
  162. if (!send_cmd16(0xC7F7)) {
  163. return false;
  164. }
  165. uint8_t d[3];
  166. if (!i2c_dev->transfer(nullptr, 0, d, sizeof(d))) {
  167. return false;
  168. }
  169. uint16_t c = int16_t((d[0]<<8) | d[1]);
  170. printf("sensor_constants[%u]=%d\n", i, c);
  171. }
  172. return true;
  173. }
  174. #ifdef HAL_INS_MPU60x0_NAME
  175. // initialise baro on i2c
  176. static void i2c_init(void)
  177. {
  178. if (!i2c_dev->get_semaphore()->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
  179. AP_HAL::panic("Failed to get baro semaphore");
  180. }
  181. if (send_cmd16(CMD_READ_ID)) {
  182. printf("ICM20789: read ID ******\n");
  183. uint8_t id[3] {};
  184. if (!i2c_dev->transfer(nullptr, 0, id, 3)) {
  185. printf("ICM20789: failed to read ID\n");
  186. }
  187. printf("ICM20789: ID %02x %02x %02x\n", id[0], id[1], id[2]);
  188. } else {
  189. printf("ICM20789 read ID failed\n");
  190. }
  191. if (send_cmd16(CMD_SOFT_RESET)) {
  192. printf("ICM20789: reset OK ************###########*********!!!!!!!!\n");
  193. } else {
  194. printf("ICM20789 baro reset failed\n");
  195. }
  196. hal.scheduler->delay(1);
  197. read_calibration_data();
  198. i2c_dev->get_semaphore()->give();
  199. printf("checking baro\n");
  200. if (!dev->get_semaphore()->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
  201. AP_HAL::panic("Failed to get device semaphore");
  202. }
  203. uint8_t regs[3] = { 0xC0, 0xC1, 0xC2 };
  204. for (uint8_t i=0; i<ARRAY_SIZE(regs); i++) {
  205. uint8_t v = 0;
  206. dev->read_registers(regs[i], &v, 1);
  207. printf("0x%02x : 0x%02x\n", regs[i], v);
  208. }
  209. dev->get_semaphore()->give();
  210. }
  211. #endif
  212. void setup()
  213. {
  214. printf("ICM20789 test\n");
  215. AP_BoardConfig{}.init();
  216. hal.scheduler->delay(1000);
  217. #ifdef HAL_INS_MPU60x0_NAME
  218. spi_dev = std::move(hal.spi->get_device(HAL_INS_MPU60x0_NAME));
  219. if (!spi_dev->get_semaphore()->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
  220. AP_HAL::panic("Failed to get spi semaphore");
  221. }
  222. i2c_dev = std::move(hal.i2c_mgr->get_device(1, 0x63));
  223. dev = std::move(hal.i2c_mgr->get_device(1, 0x29));
  224. while (true) {
  225. spi_init();
  226. i2c_init();
  227. hal.scheduler->delay(1000);
  228. }
  229. #else
  230. while (true) {
  231. printf("HAL_INS_MPU60x0_NAME not defined for this board\n");
  232. hal.scheduler->delay(1000);
  233. }
  234. #endif
  235. }
  236. void loop()
  237. {
  238. }
  239. AP_HAL_MAIN();