1
0

bmi055_sensor.cpp 11 KB

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