1
0

mpu6050_sensor.cpp 11 KB

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