motion_driver_example.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /**
  2. * @file motion_driver_example.c
  3. * @author greedyhao
  4. * @brief 硬件平台基于stm32f767与mpu6050
  5. * @version 0.1
  6. * @date 2019-05-03
  7. *
  8. * @copyright Copyright (c) 2019
  9. *
  10. */
  11. #include <rtthread.h>
  12. #include <finsh.h>
  13. // #define MD_DEBUG
  14. #define LOG_TAG "md.example"
  15. #include "md_log.h"
  16. #include "MD_Ported_to_RTT.h"
  17. #include "motion_driver_example.h"
  18. #include "inv_mpu.h"
  19. #include "inv_mpu_dmp_motion_driver.h"
  20. #include "invensense.h"
  21. #include "invensense_adv.h"
  22. #include "eMPL_outputs.h"
  23. #include "mltypes.h"
  24. #include "mpu.h"
  25. #include "log.h"
  26. #include "packet.h"
  27. /* Private typedef -----------------------------------------------------------*/
  28. /* The bus name of the mpu. */
  29. #define RT_MPU_DEVICE_NAME "i2c1"
  30. unsigned char *mpl_key = (unsigned char*)"eMPL 5.1";
  31. extern struct rt_mpu_device *mpu_dev;
  32. extern int mpu_dev_init_flag; /* Flag to show if the mpu device is inited. */
  33. //q30,q16格式,long转float时的除数.
  34. #define q30 1073741824.0f
  35. #define q16 65536.0f
  36. //陀螺仪方向设置
  37. static signed char gyro_orientation[9] = { 1, 0, 0,
  38. 0, 1, 0,
  39. 0, 0, 1};
  40. // //磁力计方向设置
  41. // static signed char comp_orientation[9] = { 0, 1, 0,
  42. // 1, 0, 0,
  43. // 0, 0,-1};
  44. #define EVENT_MD_LOOP (1<<0)
  45. static struct rt_timer timer_motion;
  46. static struct rt_event event_motion;
  47. static void timer_motion_update(void* parameter)
  48. {
  49. rt_event_send(&event_motion, EVENT_MD_LOOP);
  50. }
  51. void motion_loop(float pitch,float roll,float yaw)
  52. {
  53. char str[48];
  54. if(mpu_mpl_get_data(&pitch,&roll,&yaw)==0)
  55. {
  56. sprintf(str,"pitch=%0.1f\troll=%0.1f\t",pitch,roll);
  57. // sprintf(str,"pitch=%0.1f\troll=%0.1f\tyaw=%0.1f",pitch,roll,yaw);
  58. LOG_I(str);
  59. }
  60. }
  61. void motion_entry(void *parameter)
  62. {
  63. rt_err_t res;
  64. rt_uint32_t recv_set = 0;
  65. rt_uint32_t wait_set = EVENT_MD_LOOP;
  66. struct int_param_s int_param;
  67. unsigned char accel_fsr;
  68. unsigned short gyro_rate, gyro_fsr;
  69. float pitch,roll,yaw; //欧拉角
  70. short aacx,aacy,aacz; //加速度传感器原始数据
  71. // short gyrox,gyroy,gyroz; //陀螺仪原始数据
  72. // unsigned short compass_fsr;
  73. /* Initialize mpu6xxx, The parameter is RT_NULL, means auto probing for i2c*/
  74. mpu_dev = rt_mpu_init(RT_MPU_DEVICE_NAME, RT_NULL);
  75. if (!mpu_dev)
  76. return -1;
  77. else
  78. mpu_dev_init_flag = 1;
  79. res = mpu_init(&int_param);
  80. LOG_D("mpu_init end");
  81. if (res) {
  82. LOG_E("Could not initialize gyro.");
  83. }
  84. else
  85. {
  86. LOG_D("inv_init_mpl..");
  87. res = inv_init_mpl(); //初始化MPL
  88. if (res) return 1;
  89. inv_enable_quaternion();
  90. inv_enable_9x_sensor_fusion();
  91. inv_enable_fast_nomot();
  92. inv_enable_gyro_tc();
  93. // inv_enable_vector_compass_cal();
  94. // inv_enable_magnetic_disturbance();
  95. inv_enable_eMPL_outputs();
  96. LOG_D("inv_start_mpl..");
  97. res = inv_start_mpl(); //开启MPL
  98. if(res) return 1;
  99. LOG_D("mpu_set_sensors..");
  100. res = mpu_set_sensors(INV_XYZ_GYRO|INV_XYZ_ACCEL);//设置所需要的传感器
  101. rt_thread_mdelay(3);
  102. if (res) return 2;
  103. LOG_D("mpu_configure_fifo..");
  104. res = mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL); //设置FIFO
  105. if (res) return 3;
  106. LOG_D("mpu_set_sample_rate..");
  107. res = mpu_set_sample_rate(DEFAULT_MPU_HZ); //设置采样率
  108. if (res) return 4;
  109. // LOG_D("mpu_set_compass_sample_rate..");
  110. // res=mpu_set_compass_sample_rate(1000/COMPASS_READ_MS); //设置磁力计采样率
  111. // if(res)return 5;
  112. mpu_get_sample_rate(&gyro_rate);
  113. mpu_get_gyro_fsr(&gyro_fsr);
  114. mpu_get_accel_fsr(&accel_fsr);
  115. // mpu_get_compass_fsr(&compass_fsr);
  116. inv_set_gyro_sample_rate(1000000L/gyro_rate);
  117. inv_set_accel_sample_rate(1000000L/gyro_rate);
  118. // inv_set_compass_sample_rate(COMPASS_READ_MS*1000L);
  119. inv_set_gyro_orientation_and_scale(
  120. inv_orientation_matrix_to_scalar(gyro_orientation),(long)gyro_fsr<<15);
  121. inv_set_accel_orientation_and_scale(
  122. inv_orientation_matrix_to_scalar(gyro_orientation),(long)accel_fsr<<15);
  123. // inv_set_compass_orientation_and_scale(
  124. // inv_orientation_matrix_to_scalar(comp_orientation),(long)compass_fsr<<15);
  125. LOG_D("dmp_load_motion_driver_firmware..");
  126. res = dmp_load_motion_driver_firmware(); //加载dmp固件
  127. if (res) return 6;
  128. LOG_D("dmp_set_orientation..");
  129. res = dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation));//设置陀螺仪方向
  130. if (res) return 7;
  131. LOG_D("dmp_enable_feature..");
  132. res = dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT|DMP_FEATURE_TAP| //设置dmp功能
  133. DMP_FEATURE_ANDROID_ORIENT|DMP_FEATURE_SEND_RAW_ACCEL|DMP_FEATURE_SEND_CAL_GYRO|
  134. DMP_FEATURE_GYRO_CAL);
  135. if (res) return 8;
  136. LOG_D("dmp_set_fifo_rate..");
  137. res = dmp_set_fifo_rate(DEFAULT_MPU_HZ); //设置DMP输出速率(最大不超过200Hz)
  138. if (res) return 9;
  139. LOG_D("run_self_test..");
  140. res = run_self_test(); //自检
  141. if (res) return 10;
  142. LOG_D("mpu_set_dmp_state..");
  143. res = mpu_set_dmp_state(1); //使能DMP
  144. if (res) return 11;
  145. }
  146. mpu_reset_fifo();
  147. /* initial codes .. */
  148. /* create event */
  149. res = rt_event_init(&event_motion, "event_motion", RT_IPC_FLAG_FIFO);
  150. /* register timer event */
  151. rt_timer_init(&timer_motion, "timer_motion",
  152. timer_motion_update,
  153. RT_NULL,
  154. 1,
  155. RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
  156. rt_timer_start(&timer_motion);
  157. while(1)
  158. {
  159. res = rt_event_recv(&event_motion, wait_set, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
  160. RT_WAITING_FOREVER, &recv_set);
  161. if(res == RT_EOK){
  162. if(recv_set & EVENT_MD_LOOP){
  163. motion_loop(pitch,roll,yaw);
  164. }
  165. }
  166. }
  167. }
  168. int motion_init(void)
  169. {
  170. rt_thread_t thread = RT_NULL;
  171. thread = rt_thread_create("motion_d", motion_entry, RT_NULL, 1024, 10, 5);
  172. if(thread == RT_NULL)
  173. {
  174. return RT_ERROR;
  175. }
  176. rt_thread_startup(thread);
  177. return RT_EOK;
  178. }
  179. // INIT_APP_EXPORT(motion_init);
  180. MSH_CMD_EXPORT(motion_init, motion driver init);
  181. /**
  182. * @brief MPU6050自测试
  183. *
  184. * @return uint8_t 0,正常 其他,失败
  185. */
  186. uint8_t run_self_test(void)
  187. {
  188. int result;
  189. //char test_packet[4] = {0};
  190. long gyro[3], accel[3];
  191. result = mpu_run_self_test(gyro, accel);
  192. if (result == 0x7)
  193. {
  194. /* Test passed. We can trust the gyro data here, so let's push it down
  195. * to the DMP.
  196. */
  197. unsigned short accel_sens;
  198. float gyro_sens;
  199. mpu_get_gyro_sens(&gyro_sens);
  200. gyro[0] = (long)(gyro[0] * gyro_sens);
  201. gyro[1] = (long)(gyro[1] * gyro_sens);
  202. gyro[2] = (long)(gyro[2] * gyro_sens);
  203. //inv_set_gyro_bias(gyro, 3);
  204. dmp_set_gyro_bias(gyro);
  205. mpu_get_accel_sens(&accel_sens);
  206. accel[0] *= accel_sens;
  207. accel[1] *= accel_sens;
  208. accel[2] *= accel_sens;
  209. // inv_set_accel_bias(accel, 3);
  210. dmp_set_accel_bias(accel);
  211. return 0;
  212. }else return 1;
  213. }
  214. /**
  215. * @brief 得到dmp处理后的数据(注意,本函数需要比较多堆栈,局部变量有点多)
  216. *
  217. * @param pitch 俯仰角 精度:0.1° 范围:-90.0° <---> +90.0°
  218. * @param roll 横滚角 精度:0.1° 范围:-180.0°<---> +180.0°
  219. * @param yaw 精度:0.1° 范围:-180.0°<---> +180.0°
  220. * @return uint8_t 0,正常 其他,失败
  221. */
  222. uint8_t mpu_dmp_get_data(float *pitch,float *roll,float *yaw)
  223. {
  224. float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;
  225. unsigned long sensor_timestamp;
  226. short gyro[3], accel[3], sensors;
  227. unsigned char more;
  228. long quat[4];
  229. if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))return 1;
  230. /* Gyro and accel data are written to the FIFO by the DMP in chip frame and hardware units.
  231. * This behavior is convenient because it keeps the gyro and accel outputs of dmp_read_fifo and mpu_read_fifo consistent.
  232. **/
  233. /*if (sensors & INV_XYZ_GYRO )
  234. send_packet(PACKET_TYPE_GYRO, gyro);
  235. if (sensors & INV_XYZ_ACCEL)
  236. send_packet(PACKET_TYPE_ACCEL, accel); */
  237. /* Unlike gyro and accel, quaternions are written to the FIFO in the body frame, q30.
  238. * The orientation is set by the scalar passed to dmp_set_orientation during initialization.
  239. **/
  240. if(sensors&INV_WXYZ_QUAT)
  241. {
  242. q0 = quat[0] / q30; //q30格式转换为浮点数
  243. q1 = quat[1] / q30;
  244. q2 = quat[2] / q30;
  245. q3 = quat[3] / q30;
  246. //计算得到俯仰角/横滚角/航向角
  247. *pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch
  248. *roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
  249. *yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3; //yaw
  250. }else return 2;
  251. return 0;
  252. }
  253. /**
  254. * @brief 得到mpl处理后的数据(注意,本函数需要比较多堆栈,局部变量有点多)
  255. *
  256. * @param pitch pitch:俯仰角 精度:0.1° 范围:-90.0° <---> +90.0°
  257. * @param roll roll:横滚角 精度:0.1° 范围:-180.0°<---> +180.0°
  258. * @param yaw yaw:航向角 精度:0.1° 范围:-180.0°<---> +180.0°
  259. * @return uint8_t 0,正常 其他,失败
  260. */
  261. uint8_t mpu_mpl_get_data(float *pitch,float *roll,float *yaw)
  262. {
  263. unsigned long sensor_timestamp,timestamp;
  264. short gyro[3], accel_short[3],compass_short[3],sensors;
  265. unsigned char more;
  266. long compass[3],accel[3],quat[4],temperature;
  267. long data[9];
  268. int8_t accuracy;
  269. if(dmp_read_fifo(gyro, accel_short, quat, &sensor_timestamp, &sensors,&more))return 1;
  270. if(sensors&INV_XYZ_GYRO)
  271. {
  272. inv_build_gyro(gyro,sensor_timestamp); //把新数据发送给MPL
  273. mpu_get_temperature(&temperature,&sensor_timestamp);
  274. inv_build_temp(temperature,sensor_timestamp); //把温度值发给MPL,只有陀螺仪需要温度值
  275. }
  276. if(sensors&INV_XYZ_ACCEL)
  277. {
  278. accel[0] = (long)accel_short[0];
  279. accel[1] = (long)accel_short[1];
  280. accel[2] = (long)accel_short[2];
  281. inv_build_accel(accel,0,sensor_timestamp); //把加速度值发给MPL
  282. }
  283. // if (!mpu_get_compass_reg(compass_short, &sensor_timestamp))
  284. // {
  285. // compass[0]=(long)compass_short[0];
  286. // compass[1]=(long)compass_short[1];
  287. // compass[2]=(long)compass_short[2];
  288. // inv_build_compass(compass,0,sensor_timestamp); //把磁力计值发给MPL
  289. // }
  290. inv_execute_on_data();
  291. inv_get_sensor_type_euler(data,&accuracy,&timestamp);
  292. *roll = (data[0]/q16);
  293. *pitch = -(data[1]/q16);
  294. *yaw = -data[2] / q16;
  295. return 0;
  296. }