bmi055_sensor.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2015-1-11 RT_learning the first version
  9. */
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <rtdevice.h>
  13. #include "bmi055_sensor.h"
  14. const static sensor_t _BMI055_sensor[] =
  15. {
  16. {
  17. .name = "Accelerometer",
  18. .vendor = "Bosch",
  19. .version = sizeof(sensor_t),
  20. .handle = 0,
  21. .type = SENSOR_TYPE_ACCELEROMETER,
  22. .maxRange = SENSOR_ACCEL_RANGE_16G,
  23. .resolution = 1.0f,
  24. .power = 0.5f,
  25. .minDelay = 10000,
  26. .fifoReservedEventCount = 0,
  27. .fifoMaxEventCount = 64,
  28. },
  29. {
  30. .name = "Gyroscope",
  31. .vendor = "Bosch",
  32. .version = sizeof(sensor_t),
  33. .handle = 0,
  34. .type = SENSOR_TYPE_GYROSCOPE,
  35. .maxRange = SENSOR_GYRO_RANGE_2000DPS,
  36. .resolution = 1.0f,
  37. .power = 0.5f,
  38. .minDelay = 10000,
  39. .fifoReservedEventCount = 0,
  40. .fifoMaxEventCount = 64,
  41. }
  42. };
  43. BMI055::BMI055(int sensor_type, const char* iic_bus, int addr)
  44. : SensorBase(sensor_type)
  45. {
  46. this->i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(iic_bus);
  47. if (this->i2c_bus == NULL)
  48. {
  49. printf("BMI055: No IIC device:%s\n", iic_bus);
  50. return;
  51. }
  52. this->i2c_addr = addr;
  53. /* register to sensor manager */
  54. SensorManager::registerSensor(this);
  55. }
  56. int BMI055::read_reg(rt_uint8_t reg, rt_uint8_t *value)
  57. {
  58. struct rt_i2c_msg msgs[2];
  59. msgs[0].addr = this->i2c_addr;
  60. msgs[0].flags = RT_I2C_WR;
  61. msgs[0].buf = &reg;
  62. msgs[0].len = 1;
  63. msgs[1].addr = this->i2c_addr;
  64. msgs[1].flags = RT_I2C_RD; /* Read from slave */
  65. msgs[1].buf = (rt_uint8_t *)value;
  66. msgs[1].len = 1;
  67. if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2)
  68. return RT_EOK;
  69. return -RT_ERROR;
  70. }
  71. int BMI055::read_buffer(rt_uint8_t reg, rt_uint8_t* value, rt_size_t size)
  72. {
  73. struct rt_i2c_msg msgs[2];
  74. msgs[0].addr = this->i2c_addr;
  75. msgs[0].flags = RT_I2C_WR;
  76. msgs[0].buf = &reg;
  77. msgs[0].len = 1;
  78. msgs[1].addr = this->i2c_addr;
  79. msgs[1].flags = RT_I2C_RD; /* Read from slave */
  80. msgs[1].buf = (rt_uint8_t *)value;
  81. msgs[1].len = size;
  82. if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2)
  83. return RT_EOK;
  84. return -RT_ERROR;
  85. }
  86. int BMI055::write_reg(rt_uint8_t reg, rt_uint8_t value)
  87. {
  88. struct rt_i2c_msg msgs[2];
  89. msgs[0].addr = this->i2c_addr;
  90. msgs[0].flags = RT_I2C_WR;
  91. msgs[0].buf = &reg;
  92. msgs[0].len = 1;
  93. msgs[1].addr = this->i2c_addr;
  94. msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;
  95. msgs[1].buf = (rt_uint8_t *)&value;
  96. msgs[1].len = 1;
  97. if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2)
  98. return RT_EOK;
  99. return -RT_ERROR;
  100. }
  101. BMI055_Accelerometer::BMI055_Accelerometer(const char* iic_name, int addr)
  102. : BMI055(SENSOR_TYPE_ACCELEROMETER, iic_name, addr)
  103. {
  104. int index;
  105. uint8_t id;
  106. rt_uint8_t value[6] = {0};
  107. rt_int32_t x, y, z;
  108. SensorConfig config = {SENSOR_MODE_NORMAL, SENSOR_DATARATE_400HZ, SENSOR_ACCEL_RANGE_2G};
  109. write_reg(BMI055_BGW_SOFTRESET, 0xB6); /* reset of the sensor P57 */
  110. write_reg(BMI055_PMU_LPW, 0x00); /* PMU_LPW NORMAL mode P55 */
  111. write_reg(BMI055_PMU_BW, 0x0A); /* 01010b 31.25 Hz P55 */
  112. write_reg(BMI055_PMU_RANGE, 0x05); /* 0101b 卤4g range PMU_RANGE set acc +-4g/s P54 */
  113. x_offset = y_offset = z_offset = 0;
  114. x = y = z = 0;
  115. /* read BMI055 id */
  116. read_buffer(BMI055_ACC_BGW_CHIPID, &id, 1); /* BGW_CHIPID P47*/
  117. if (id != BMI055_ACC_BGW_CHIPID_VALUE)
  118. {
  119. printf("Warning: not found BMI055 id: %02x\n", id);
  120. }
  121. /* get offset */
  122. for (index = 0; index < 200; index ++)
  123. {
  124. read_buffer(BMI055_ACCD_X_LSB, value, 6); /*ACCD_X_LSB P47 */
  125. x += (((rt_int16_t)value[1] << 8) | value[0]);
  126. y += (((rt_int16_t)value[3] << 8) | value[2]);
  127. z += (((rt_int16_t)value[5] << 8) | value[4]);
  128. }
  129. x_offset = x / 200;
  130. y_offset = y / 200;
  131. z_offset = z / 200;
  132. this->enable = RT_FALSE;
  133. this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G;
  134. this->config = config;
  135. }
  136. int
  137. BMI055_Accelerometer::configure(SensorConfig *config)
  138. {
  139. int range;
  140. uint8_t value;
  141. if (config == RT_NULL) return -1;
  142. /* TODO: set datarate */
  143. /* get range and calc the sensitivity */
  144. range = config->range.accel_range;
  145. switch (range)
  146. {
  147. case SENSOR_ACCEL_RANGE_2G:
  148. this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G;
  149. range = 0x03; //0011b
  150. break;
  151. case SENSOR_ACCEL_RANGE_4G:
  152. this->sensitivity = SENSOR_ACCEL_SENSITIVITY_4G;
  153. range = 0x05; //0101b
  154. break;
  155. case SENSOR_ACCEL_RANGE_8G:
  156. this->sensitivity = SENSOR_ACCEL_SENSITIVITY_8G;
  157. range = 0x01 << 3; //1000b
  158. break;
  159. case SENSOR_ACCEL_RANGE_16G:
  160. this->sensitivity = SENSOR_ACCEL_SENSITIVITY_16G;
  161. range = 0x03 << 2; //1100b
  162. break;
  163. default:
  164. return -1;
  165. }
  166. /* set range to sensor */
  167. read_reg(BMI055_PMU_RANGE, &value); /* PMU_RANGE P54 */
  168. value &= 0xF0;
  169. value |= range;
  170. write_reg(BMI055_PMU_RANGE, value);
  171. return 0;
  172. }
  173. int
  174. BMI055_Accelerometer::activate(int enable)
  175. {
  176. uint8_t value;
  177. if (enable && this->enable == RT_FALSE)
  178. {
  179. /* enable accelerometer */
  180. read_reg(BMI055_PMU_LPW, &value); /* P55 */
  181. value &= ~(0x07 << 7);
  182. write_reg(BMI055_PMU_LPW, value);
  183. }
  184. if (!enable && this->enable == RT_TRUE)
  185. {
  186. /* disable accelerometer */
  187. read_reg(BMI055_PMU_LPW, &value);
  188. value &= ~(0x07 << 7);
  189. value |= (0x01 << 7);
  190. write_reg(BMI055_PMU_LPW, value);
  191. }
  192. if (enable) this->enable = RT_TRUE;
  193. else this->enable = RT_FALSE;
  194. return 0;
  195. }
  196. int
  197. BMI055_Accelerometer::poll(sensors_event_t *event)
  198. {
  199. rt_uint8_t value[6];
  200. rt_int16_t x, y, z;
  201. /* parameters check */
  202. if (event == NULL) return -1;
  203. /* get event data */
  204. event->version = sizeof(sensors_event_t);
  205. event->sensor = (int32_t) this;
  206. event->timestamp = rt_tick_get();
  207. event->type = SENSOR_TYPE_ACCELEROMETER;
  208. read_buffer(0x02, value, 6);
  209. /* get raw data */
  210. x = (((rt_int16_t)value[1] << 8) | value[0]);
  211. y = (((rt_int16_t)value[3] << 8) | value[2]);
  212. z = (((rt_int16_t)value[5] << 8) | value[4]);
  213. if (config.mode == SENSOR_MODE_RAW)
  214. {
  215. event->raw_acceleration.x = x;
  216. event->raw_acceleration.y = y;
  217. event->raw_acceleration.z = z;
  218. }
  219. else
  220. {
  221. x -= x_offset; y -= y_offset; z -= z_offset;
  222. event->acceleration.x = x * this->sensitivity * SENSORS_GRAVITY_STANDARD;
  223. event->acceleration.y = y * this->sensitivity * SENSORS_GRAVITY_STANDARD;
  224. event->acceleration.z = z * this->sensitivity * SENSORS_GRAVITY_STANDARD;
  225. }
  226. return 0;
  227. }
  228. void
  229. BMI055_Accelerometer::getSensor(sensor_t *sensor)
  230. {
  231. /* get sensor description */
  232. if (sensor)
  233. {
  234. memcpy(sensor, &_BMI055_sensor[0], sizeof(sensor_t));
  235. }
  236. }
  237. BMI055_Gyroscope::BMI055_Gyroscope(const char* iic_name, int addr)
  238. : BMI055(SENSOR_TYPE_GYROSCOPE, iic_name, addr)
  239. {
  240. int index;
  241. uint8_t id;
  242. rt_uint8_t value[6];
  243. rt_int32_t x, y, z;
  244. /* initialize BMI055 */
  245. write_reg(BMI055_MODE_LPM1_ADDR, 0x00); /* normal mode */
  246. write_reg(BMI055_MODE_LPM2_ADDR, 0x80); /* fast powerup */
  247. write_reg(BMI055_BW_ADDR, 0x03); /* ODR:400Hz Filter Bandwidth:47Hz */
  248. write_reg(BMI055_RANGE_ADDR, 0x00); /* 2000dps */
  249. x_offset = y_offset = z_offset = 0;
  250. x = y = z = 0;
  251. /* read BMI055 id */
  252. read_buffer(BMI055_CHIP_ID_ADDR, &id, 1);
  253. if (id != BMI055_GRRO_CHIP_ID)
  254. {
  255. printf("Warning: not found BMI055 id: %02x\n", id);
  256. }
  257. /* get offset */
  258. for (index = 0; index < 200; index ++)
  259. {
  260. read_buffer(BMI055_RATE_X_LSB_ADDR, value, 6);
  261. x += (((rt_int16_t)value[1] << 8) | value[0]);
  262. y += (((rt_int16_t)value[3] << 8) | value[2]);
  263. z += (((rt_int16_t)value[5] << 8) | value[4]);
  264. }
  265. x_offset = x / 200;
  266. y_offset = y / 200;
  267. z_offset = z / 200;
  268. this->enable = RT_FALSE;
  269. this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS;
  270. }
  271. int
  272. BMI055_Gyroscope::configure(SensorConfig *config)
  273. {
  274. int range;
  275. uint8_t value;
  276. if (config == RT_NULL) return -1;
  277. /* TODO: set datarate */
  278. /* get range and calc the sensitivity */
  279. range = config->range.gyro_range;
  280. switch (range)
  281. {
  282. //to do add more range e.g 125DPS
  283. //case
  284. case SENSOR_GYRO_RANGE_250DPS:
  285. this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS;
  286. range = 0x11;
  287. break;
  288. case SENSOR_GYRO_RANGE_500DPS:
  289. this->sensitivity = SENSOR_GYRO_SENSITIVITY_500DPS;
  290. range = 0x10;
  291. break;
  292. case SENSOR_GYRO_RANGE_1000DPS:
  293. this->sensitivity = SENSOR_GYRO_SENSITIVITY_1000DPS;
  294. range = 0x01;
  295. break;
  296. case SENSOR_GYRO_RANGE_2000DPS:
  297. this->sensitivity = SENSOR_GYRO_SENSITIVITY_2000DPS;
  298. range = 0x00;
  299. break;
  300. default:
  301. return -1;
  302. }
  303. /* set range to sensor */
  304. read_reg(BMI055_RANGE_ADDR, &value);
  305. value &= ~0x07;
  306. value |= range;
  307. write_reg(BMI055_RANGE_ADDR, value);
  308. return 0;
  309. }
  310. int
  311. BMI055_Gyroscope::activate(int enable)
  312. {
  313. uint8_t value;
  314. if (enable && this->enable == RT_FALSE)
  315. {
  316. /* enable gyroscope */
  317. read_reg(BMI055_MODE_LPM1_ADDR, &value);
  318. value &= ~(0x1010 << 4); //{0; 0} NORMAL mode
  319. write_reg(BMI055_MODE_LPM1_ADDR, value); //P101 NORMAL mode
  320. }
  321. if (!enable && this->enable == RT_TRUE)
  322. {
  323. /* disable gyroscope */
  324. read_reg(BMI055_MODE_LPM1_ADDR, &value);
  325. value &= ~(0x01 << 5); //set bit5 deep_suspend 0
  326. value |= (0x01 << 7); //set bit1 suspend 1
  327. write_reg(BMI055_MODE_LPM1_ADDR, value); //{1; 0} SUSPEND mode
  328. }
  329. if (enable) this->enable = RT_TRUE;
  330. else this->enable = RT_FALSE;
  331. return 0;
  332. }
  333. int
  334. BMI055_Gyroscope::poll(sensors_event_t *event)
  335. {
  336. rt_uint8_t value[6];
  337. rt_int16_t x, y, z;
  338. /* parameters check */
  339. if (event == NULL) return -1;
  340. /* get event data */
  341. event->version = sizeof(sensors_event_t);
  342. event->sensor = (int32_t) this;
  343. event->timestamp = rt_tick_get();
  344. event->type = SENSOR_TYPE_GYROSCOPE;
  345. read_buffer(BMI055_RATE_X_LSB_ADDR, value, 6);
  346. /* get raw data */
  347. x = (((rt_int16_t)value[1] << 8) | value[0]);
  348. y = (((rt_int16_t)value[3] << 8) | value[2]);
  349. z = (((rt_int16_t)value[5] << 8) | value[4]);
  350. if (config.mode == SENSOR_MODE_RAW)
  351. {
  352. event->raw_gyro.x = x;
  353. event->raw_gyro.y = y;
  354. event->raw_gyro.z = z;
  355. }
  356. else
  357. {
  358. x -= x_offset; y -= y_offset; z -= z_offset;
  359. event->gyro.x = x * this->sensitivity * SENSORS_DPS_TO_RADS;
  360. event->gyro.y = y * this->sensitivity * SENSORS_DPS_TO_RADS;
  361. event->gyro.z = z * this->sensitivity * SENSORS_DPS_TO_RADS;
  362. }
  363. return 0;
  364. }
  365. void
  366. BMI055_Gyroscope::getSensor(sensor_t *sensor)
  367. {
  368. /* get sensor description */
  369. if (sensor)
  370. {
  371. memcpy(sensor, &_BMI055_sensor[1], sizeof(sensor_t));
  372. }
  373. }