MPU9250 内部包括 3 轴陀螺仪、3 轴加速度计和 3 轴磁力计,这3个功能输出都是 16 位的数字量; 可以通过常用的数据总线( IIC) 接口和单片机进行数据交互,传输速率 400 kHz /s。陀螺仪的角速度测量范围±2000(° /s),具有良好的动态响应特性。加速度计的测量范围最大为±16g( g 为重力加速度),静态测量精度高。磁力计采用高灵度霍尔型传感器进行数据采集,磁感应强度测量范围为±4800μT,可用于对偏航角的辅助测量。
MPU9250 自带的数字运动处理器DMP硬件加速引擎,可以整合九轴传感器数据,向应用端输出完整的 9 轴融合演算数据。 有了 DMP,我们可以使用运动处理库非常方便的实现姿态解算,降低了运动处理运算对操作系统的负荷,同时大大降低了开发难度。

三轴陀螺仪

MPU9250陀螺仪是由三个独立检测X, Y, Z轴的MEMS组成。检测每个轴的转动(一但某个轴发生变化,相应的电容传感器会发生相应的变化,产生的信号被放大,调解,滤波,最后产生个与角速率成正比的电压,然后将每一个轴的电压转换成16位的数据。ADC的采样速率也是可编程的,从每秒3.9-8000个。

三轴加速度

MPU9250的三轴加速度也是单独分开测量的。根据每个轴上的电容来测量轴的偏差度。结构上降低了各种因素造成的测量偏差。加速度计的校准是根据工厂的标准来设定的,电源电压也许和你用的不一样。每一个传感器都有专门的ADC来提供数字性的输出。

三轴磁力计

三轴磁力计采用高精度的霍尔效应传感器,通过驱动电路,信号放大和计算电路来处理信号来采集地磁场在X, Y, Z轴上的电磁强度。

IIC通信

MPU9250的电路图连接如下

我们使用IIC让MPU9250和单片机通信,并且输出获取到的传感器值。
IIC数据总线是由两根通信线组成,必要的是包含一个主控制器件和多个从控制器件,不同的从器件通过地址与主器件通信。
实际使用中,一般是单片机作为主机,其它器件作为从机,单片机先向器件发送信息表示要读取数据,之后转变传输方向,器件发送数据到单片机。
 
在通信时,IIC通信线只有只有两根,数据线SDA的高低电平传输2进制的数据,时钟线SCL通过方波信号提供时钟节拍。在时钟的高电平周期内,SDA线上的数据必须保持稳定,数据线仅可以在时钟SCL为低电平时改变。
IIC的通信数据包含起始信号应答信号和结束信号等。
其中起始信号产生的条件是当SCL为高电平的时候,SDA线上由高到低的跳变被定义为起始条件。结束信号产生的条件是SCL为高电平的时候,SDA线上由低到高的跳变被定义为停止条件。
从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答。
关于通信协议具体的内容,可以网上找找详细介绍。作为嵌入式软件工程师,这些常用协议一定要去仔细研究一下,只有理解了协议才能在程序上理清协议实现的逻辑。

程序

由于使用IIC通信协议控制MPU9250,我们需要实现IIC协议。
代码参考正点原子的源码,封装好的函数用起来比较高效。

 
  1. void IIC_Init(void)
  2. {
  3. GPIO_InitTypeDef GPIO_Initure;
  4. __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOB时钟
  5. //PH4,5初始化设置
  6. GPIO_Initure.Pin=GPIO_PIN_4|GPIO_PIN_5;
  7. GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
  8. GPIO_Initure.Pull=GPIO_PULLUP; //上拉
  9. GPIO_Initure.Speed=GPIO_SPEED_FAST; //快速
  10. HAL_GPIO_Init(GPIOA,&GPIO_Initure);
  11. IIC_SDA=1;
  12. IIC_SCL=1;
  13. }
  14. //产生IIC起始信号
  15. void IIC_Start(void)
  16. {
  17. SDA_OUT(); //sda线输出
  18. IIC_SDA=1;
  19. IIC_SCL=1;
  20. delay_us(4);
  21. IIC_SDA=0;//START:when CLK is high,DATA change form high to low
  22. delay_us(4);
  23. IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
  24. }
  25. //产生IIC停止信号
  26. void IIC_Stop(void)
  27. {
  28. SDA_OUT();//sda线输出
  29. IIC_SCL=0;
  30. IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
  31. delay_us(4);
  32. IIC_SCL=1;
  33. delay_us(4);
  34. IIC_SDA=1;//发送I2C总线结束信号
  35. }
  36. //等待应答信号到来
  37. //返回值:1,接收应答失败
  38. // 0,接收应答成功
  39. u8 IIC_Wait_Ack(void)
  40. {
  41. u8 ucErrTime=0;
  42. SDA_IN(); //SDA设置为输入
  43. IIC_SDA=1;delay_us(1);
  44. IIC_SCL=1;delay_us(1);
  45. while(READ_SDA)
  46. {
  47. ucErrTime++;
  48. if(ucErrTime>250)
  49. {
  50. IIC_Stop();
  51. return 1;
  52. }
  53. }
  54. IIC_SCL=0;//时钟输出0
  55. return 0;
  56. }
  57. //产生ACK应答
  58. void IIC_Ack(void)
  59. {
  60. IIC_SCL=0;
  61. SDA_OUT();
  62. IIC_SDA=0;
  63. delay_us(2);
  64. IIC_SCL=1;
  65. delay_us(2);
  66. IIC_SCL=0;
  67. }
  68. //不产生ACK应答
  69. void IIC_NAck(void)
  70. {
  71. IIC_SCL=0;
  72. SDA_OUT();
  73. IIC_SDA=1;
  74. delay_us(2);
  75. IIC_SCL=1;
  76. delay_us(2);
  77. IIC_SCL=0;
  78. }
  79. //IIC发送一个字节
  80. //返回从机有无应答
  81. //1,有应答
  82. //0,无应答
  83. void IIC_Send_Byte(u8 txd)
  84. {
  85. u8 t;
  86. SDA_OUT();
  87. IIC_SCL=0;//拉低时钟开始数据传输
  88. for(t=0;t<8;t++)
  89. {
  90. IIC_SDA=(txd&0x80)>>7;
  91. txd<<=1;
  92. delay_us(2); //对TEA5767这三个延时都是必须的
  93. IIC_SCL=1;
  94. delay_us(2);
  95. IIC_SCL=0;
  96. delay_us(2);
  97. }
  98. }
  99. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK
  100. u8 IIC_Read_Byte(unsigned char ack)
  101. {
  102. unsigned char i,receive=0;
  103. SDA_IN();//SDA设置为输入
  104. for(i=0;i<8;i++ )
  105. {
  106. IIC_SCL=0;
  107. delay_us(2);
  108. IIC_SCL=1;
  109. receive<<=1;
  110. if(READ_SDA)receive++;
  111. delay_us(1);
  112. }
  113. if (!ack)
  114. IIC_NAck();//发送nACK
  115. else
  116. IIC_Ack(); //发送ACK
  117. return receive;
  118. }
  119. u8 MPU9250_Init(void)
  120. {
  121. u8 res=0;
  122. IIC_Init(); //初始化IIC总线
  123. MPU_Write_Byte(MPU9250_ADDR,MPU_PWR_MGMT1_REG,0X80);//复位MPU9250
  124. delay_ms(100); //延时100ms
  125. MPU_Write_Byte(MPU9250_ADDR,MPU_PWR_MGMT1_REG,0X00);//唤醒MPU9250
  126. MPU_Set_Gyro_Fsr(3); //陀螺仪传感器,±2000dps
  127. MPU_Set_Accel_Fsr(0); //加速度传感器,±2g
  128. MPU_Set_Rate(50); //设置采样率50Hz
  129. MPU_Write_Byte(MPU9250_ADDR,MPU_INT_EN_REG,0X00); //关闭所有中断
  130. MPU_Write_Byte(MPU9250_ADDR,MPU_USER_CTRL_REG,0X00);//I2C主模式关闭
  131. MPU_Write_Byte(MPU9250_ADDR,MPU_FIFO_EN_REG,0X00); //关闭FIFO
  132. MPU_Write_Byte(MPU9250_ADDR,MPU_INTBP_CFG_REG,0X82);//INT引脚低电平有效,开启bypass模式,可以直接读取磁力计
  133. res=MPU_Read_Byte(MPU9250_ADDR,MPU_DEVICE_ID_REG); //读取MPU6500的ID
  134. if(res==MPU6500_ID) //器件ID正确
  135. {
  136. MPU_Write_Byte(MPU9250_ADDR,MPU_PWR_MGMT1_REG,0X01); //设置CLKSEL,PLL X轴为参考
  137. MPU_Write_Byte(MPU9250_ADDR,MPU_PWR_MGMT2_REG,0X00); //加速度与陀螺仪都工作
  138. MPU_Set_Rate(50); //设置采样率为50Hz
  139. }else return 1;
  140. res=MPU_Read_Byte(AK8963_ADDR,MAG_WIA); //读取AK8963 ID
  141. if(res==AK8963_ID)
  142. {
  143. MPU_Write_Byte(AK8963_ADDR,MAG_CNTL1,0X11); //设置AK8963为单次测量模式
  144. }else return 1;
  145. return 0;
  146. }
  147. //设置MPU9250陀螺仪传感器满量程范围
  148. //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
  149. //返回值:0,设置成功
  150. // 其他,设置失败
  151. u8 MPU_Set_Gyro_Fsr(u8 fsr)
  152. {
  153. return MPU_Write_Byte(MPU9250_ADDR,MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围
  154. }
  155. //设置MPU9250加速度传感器满量程范围
  156. //fsr:0,±2g;1,±4g;2,±8g;3,±16g
  157. //返回值:0,设置成功
  158. // 其他,设置失败
  159. u8 MPU_Set_Accel_Fsr(u8 fsr)
  160. {
  161. return MPU_Write_Byte(MPU9250_ADDR,MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围
  162. }
  163. //设置MPU9250的数字低通滤波器
  164. //lpf:数字低通滤波频率(Hz)
  165. //返回值:0,设置成功
  166. // 其他,设置失败
  167. u8 MPU_Set_LPF(u16 lpf)
  168. {
  169. u8 data=0;
  170. if(lpf>=188)data=1;
  171. else if(lpf>=98)data=2;
  172. else if(lpf>=42)data=3;
  173. else if(lpf>=20)data=4;
  174. else if(lpf>=10)data=5;
  175. else data=6;
  176. return MPU_Write_Byte(MPU9250_ADDR,MPU_CFG_REG,data);//设置数字低通滤波器
  177. }
  178. //设置MPU9250的采样率(假定Fs=1KHz)
  179. //rate:4~1000(Hz)
  180. //返回值:0,设置成功
  181. // 其他,设置失败
  182. u8 MPU_Set_Rate(u16 rate)
  183. {
  184. u8 data;
  185. if(rate>1000)rate=1000;
  186. if(rate<4)rate=4;
  187. data=1000/rate-1;
  188. data=MPU_Write_Byte(MPU9250_ADDR,MPU_SAMPLE_RATE_REG,data); //设置数字低通滤波器
  189. return MPU_Set_LPF(rate/2); //自动设置LPF为采样率的一半
  190. }
  191. //得到陀螺仪值(原始值)
  192. //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
  193. //返回值:0,成功
  194. // 其他,错误代码
  195. u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
  196. {
  197. u8 buf[6],res;
  198. res=MPU_Read_Len(MPU9250_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
  199. if(res==0)
  200. {
  201. *gx=((u16)buf[0]<<8)|buf[1];
  202. *gy=((u16)buf[2]<<8)|buf[3];
  203. *gz=((u16)buf[4]<<8)|buf[5];
  204. }
  205. return res;;
  206. }
  207. //得到加速度值(原始值)
  208. //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
  209. //返回值:0,成功
  210. // 其他,错误代码
  211. u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
  212. {
  213. u8 buf[6],res;
  214. res=MPU_Read_Len(MPU9250_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);
  215. if(res==0)
  216. {
  217. *ax=((u16)buf[0]<<8)|buf[1];
  218. *ay=((u16)buf[2]<<8)|buf[3];
  219. *az=((u16)buf[4]<<8)|buf[5];
  220. }
  221. return res;;
  222. }
  223. //得到磁力计值(原始值)
  224. //mx,my,mz:磁力计x,y,z轴的原始读数(带符号)
  225. //返回值:0,成功
  226. // 其他,错误代码
  227. u8 MPU_Get_Magnetometer(short *mx,short *my,short *mz)
  228. {
  229. u8 buf[6],res;
  230. res=MPU_Read_Len(AK8963_ADDR,MAG_XOUT_L,6,buf);
  231. if(res==0)
  232. {
  233. *mx=((u16)buf[1]<<8)|buf[0];
  234. *my=((u16)buf[3]<<8)|buf[2];
  235. *mz=((u16)buf[5]<<8)|buf[4];
  236. }
  237. MPU_Write_Byte(AK8963_ADDR,MAG_CNTL1,0X11); //AK8963每次读完以后都需要重新设置为单次测量模式
  238. return res;;
  239. }
  240. //IIC连续写
  241. //addr:器件地址
  242. //reg:寄存器地址
  243. //len:写入长度
  244. //buf:数据区
  245. //返回值:0,正常
  246. // 其他,错误代码
  247. u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
  248. {
  249. u8 i;
  250. IIC_Start();
  251. IIC_Send_Byte((addr<<1)|0); //发送器件地址+写命令
  252. if(IIC_Wait_Ack()) //等待应答
  253. {
  254. IIC_Stop();
  255. return 1;
  256. }
  257. IIC_Send_Byte(reg); //写寄存器地址
  258. IIC_Wait_Ack(); //等待应答
  259. for(i=0;i<len;i++)
  260. {
  261. IIC_Send_Byte(buf[i]); //发送数据
  262. if(IIC_Wait_Ack()) //等待ACK
  263. {
  264. IIC_Stop();
  265. return 1;
  266. }
  267. }
  268. IIC_Stop();
  269. return 0;
  270. }
  271. //IIC连续读
  272. //addr:器件地址
  273. //reg:要读取的寄存器地址
  274. //len:要读取的长度
  275. //buf:读取到的数据存储区
  276. //返回值:0,正常
  277. // 其他,错误代码
  278. u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
  279. {
  280. IIC_Start();
  281. IIC_Send_Byte((addr<<1)|0); //发送器件地址+写命令
  282. if(IIC_Wait_Ack()) //等待应答
  283. {
  284. IIC_Stop();
  285. return 1;
  286. }
  287. IIC_Send_Byte(reg); //写寄存器地址
  288. IIC_Wait_Ack(); //等待应答
  289. IIC_Start();
  290. IIC_Send_Byte((addr<<1)|1); //发送器件地址+读命令
  291. IIC_Wait_Ack(); //等待应答
  292. while(len)
  293. {
  294. if(len==1)*buf=IIC_Read_Byte(0);//读数据,发送nACK
  295. else *buf=IIC_Read_Byte(1); //读数据,发送ACK
  296. len--;
  297. buf++;
  298. }
  299. IIC_Stop(); //产生一个停止条件
  300. return 0;
  301. }
  302. //IIC写一个字节
  303. //devaddr:器件IIC地址
  304. //reg:寄存器地址
  305. //data:数据
  306. //返回值:0,正常
  307. // 其他,错误代码
  308. u8 MPU_Write_Byte(u8 addr,u8 reg,u8 data)
  309. {
  310. IIC_Start();
  311. IIC_Send_Byte((addr<<1)|0); //发送器件地址+写命令
  312. if(IIC_Wait_Ack()) //等待应答
  313. {
  314. IIC_Stop();
  315. return 1;
  316. }
  317. IIC_Send_Byte(reg); //写寄存器地址
  318. IIC_Wait_Ack(); //等待应答
  319. IIC_Send_Byte(data); //发送数据
  320. if(IIC_Wait_Ack()) //等待ACK
  321. {
  322. IIC_Stop();
  323. return 1;
  324. }
  325. IIC_Stop();
  326. return 0;
  327. }
  328. //IIC读一个字节
  329. //reg:寄存器地址
  330. //返回值:读到的数据
  331. u8 MPU_Read_Byte(u8 addr,u8 reg)
  332. {
  333. u8 res;
  334. IIC_Start();
  335. IIC_Send_Byte((addr<<1)|0); //发送器件地址+写命令
  336. IIC_Wait_Ack(); //等待应答
  337. IIC_Send_Byte(reg); //写寄存器地址
  338. IIC_Wait_Ack(); //等待应答
  339. IIC_Start();
  340. IIC_Send_Byte((addr<<1)|1); //发送器件地址+读命令
  341. IIC_Wait_Ack(); //等待应答
  342. res=IIC_Read_Byte(0); //读数据,发送nACK
  343. IIC_Stop(); //产生一个停止条件
  344. return res;
  345. }

下面的代码是控制MPU9250的关键代码,是针对芯片本身的。也是主要代码。
首先初始化DMP

 
  1. u8 mpu_dmp_init(void)
  2. {
  3. u8 res=0;
  4. struct int_param_s int_param;
  5. unsigned char accel_fsr;
  6. unsigned short gyro_rate, gyro_fsr;
  7. unsigned short compass_fsr;
  8. IIC_Init(); //初始化IIC总线
  9. if(mpu_init(&int_param)==0) //初始化MPU9250
  10. {
  11. res=inv_init_mpl(); //初始化MPL
  12. if(res)return 1;
  13. inv_enable_quaternion();
  14. inv_enable_9x_sensor_fusion();
  15. inv_enable_fast_nomot();
  16. inv_enable_gyro_tc();
  17. inv_enable_vector_compass_cal();
  18. inv_enable_magnetic_disturbance();
  19. inv_enable_eMPL_outputs();
  20. res=inv_start_mpl(); //开启MPL
  21. if(res)return 1;
  22. res=mpu_set_sensors(INV_XYZ_GYRO|INV_XYZ_ACCEL|INV_XYZ_COMPASS);//设置所需要的传感器
  23. if(res)return 2;
  24. res=mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL); //设置FIFO
  25. if(res)return 3;
  26. res=mpu_set_sample_rate(DEFAULT_MPU_HZ); //设置采样率
  27. if(res)return 4;
  28. res=mpu_set_compass_sample_rate(1000/COMPASS_READ_MS); //设置磁力计采样率
  29. if(res)return 5;
  30. mpu_get_sample_rate(&gyro_rate);
  31. mpu_get_gyro_fsr(&gyro_fsr);
  32. mpu_get_accel_fsr(&accel_fsr);
  33. mpu_get_compass_fsr(&compass_fsr);
  34. inv_set_gyro_sample_rate(1000000L/gyro_rate);
  35. inv_set_accel_sample_rate(1000000L/gyro_rate);
  36. inv_set_compass_sample_rate(COMPASS_READ_MS*1000L);
  37. inv_set_gyro_orientation_and_scale(
  38. inv_orientation_matrix_to_scalar(gyro_orientation),(long)gyro_fsr<<15);
  39. inv_set_accel_orientation_and_scale(
  40. inv_orientation_matrix_to_scalar(gyro_orientation),(long)accel_fsr<<15);
  41. inv_set_compass_orientation_and_scale(
  42. inv_orientation_matrix_to_scalar(comp_orientation),(long)compass_fsr<<15);
  43. res=dmp_load_motion_driver_firmware(); //加载dmp固件
  44. if(res)return 6;
  45. res=dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation));//设置陀螺仪方向
  46. if(res)return 7;
  47. res=dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT|DMP_FEATURE_TAP| //设置dmp功能
  48. DMP_FEATURE_ANDROID_ORIENT|DMP_FEATURE_SEND_RAW_ACCEL|DMP_FEATURE_SEND_CAL_GYRO|
  49. DMP_FEATURE_GYRO_CAL);
  50. if(res)return 8;
  51. res=dmp_set_fifo_rate(DEFAULT_MPU_HZ); //设置DMP输出速率(最大不超过200Hz)
  52. if(res)return 9;
  53. res=run_self_test(); //自检
  54. if(res)return 10;
  55. res=mpu_set_dmp_state(1); //使能DMP
  56. if(res)return 11;
  57. }
  58. return 0;
  59. }

获取mp1的数据

 
  1. u8 mpu_mpl_get_data(float *pitch,float *roll,float *yaw)
  2. {
  3. unsigned long sensor_timestamp,timestamp;
  4. short gyro[3], accel_short[3],compass_short[3],sensors;
  5. unsigned char more;
  6. long compass[3],accel[3],quat[4],temperature;
  7. long data[9];
  8. int8_t accuracy;
  9. if(dmp_read_fifo(gyro, accel_short, quat, &sensor_timestamp, &sensors,&more))return 1;
  10. if(sensors&INV_XYZ_GYRO)
  11. {
  12. inv_build_gyro(gyro,sensor_timestamp); //把新数据发送给MPL
  13. mpu_get_temperature(&temperature,&sensor_timestamp);
  14. inv_build_temp(temperature,sensor_timestamp); //把温度值发给MPL,只有陀螺仪需要温度值
  15. }
  16. if(sensors&INV_XYZ_ACCEL)
  17. {
  18. accel[0] = (long)accel_short[0];
  19. accel[1] = (long)accel_short[1];
  20. accel[2] = (long)accel_short[2];
  21. inv_build_accel(accel,0,sensor_timestamp); //把加速度值发给MPL
  22. }
  23. if (!mpu_get_compass_reg(compass_short, &sensor_timestamp))
  24. {
  25. compass[0]=(long)compass_short[0];
  26. compass[1]=(long)compass_short[1];
  27. compass[2]=(long)compass_short[2];
  28. inv_build_compass(compass,0,sensor_timestamp); //把磁力计值发给MPL
  29. }
  30. inv_execute_on_data();
  31. inv_get_sensor_type_euler(data,&accuracy,×tamp);
  32. *roll = (data[0]/q16);
  33. *pitch = -(data[1]/q16);
  34. *yaw = -data[2] / q16;
  35. return 0;
  36. }

其中,数据从队列中读取代码如下

 
  1. int dmp_read_fifo(short *gyro, short *accel, long *quat,
  2. unsigned long *timestamp, short *sensors, unsigned char *more)
  3. {
  4. unsigned char fifo_data[MAX_PACKET_LENGTH];
  5. unsigned char ii = 0;
  6. sensors[0] = 0;
  7. if (mpu_read_fifo_stream(dmp.packet_length, fifo_data, more))
  8. return -1;
  9. if (dmp.feature_mask & (DMP_FEATURE_LP_QUAT | DMP_FEATURE_6X_LP_QUAT)) {
  10. #ifdef FIFO_CORRUPTION_CHECK
  11. long quat_q14[4], quat_mag_sq;
  12. #endif
  13. quat[0] = ((long)fifo_data[0] << 24) | ((long)fifo_data[1] << 16) |
  14. ((long)fifo_data[2] << 8) | fifo_data[3];
  15. quat[1] = ((long)fifo_data[4] << 24) | ((long)fifo_data[5] << 16) |
  16. ((long)fifo_data[6] << 8) | fifo_data[7];
  17. quat[2] = ((long)fifo_data[8] << 24) | ((long)fifo_data[9] << 16) |
  18. ((long)fifo_data[10] << 8) | fifo_data[11];
  19. quat[3] = ((long)fifo_data[12] << 24) | ((long)fifo_data[13] << 16) |
  20. ((long)fifo_data[14] << 8) | fifo_data[15];
  21. ii += 16;
  22. #ifdef FIFO_CORRUPTION_CHECK
  23. quat_q14[0] = quat[0] >> 16;
  24. quat_q14[1] = quat[1] >> 16;
  25. quat_q14[2] = quat[2] >> 16;
  26. quat_q14[3] = quat[3] >> 16;
  27. quat_mag_sq = quat_q14[0] * quat_q14[0] + quat_q14[1] * quat_q14[1] +
  28. quat_q14[2] * quat_q14[2] + quat_q14[3] * quat_q14[3];
  29. if ((quat_mag_sq < QUAT_MAG_SQ_MIN) ||
  30. (quat_mag_sq > QUAT_MAG_SQ_MAX)) {
  31. /@@* Quaternion is outside of the acceptable threshold. */
  32. mpu_reset_fifo();
  33. sensors[0] = 0;
  34. return -1;
  35. }
  36. sensors[0] |= INV_WXYZ_QUAT;
  37. #endif
  38. }
  39. if (dmp.feature_mask & DMP_FEATURE_SEND_RAW_ACCEL) {
  40. accel[0] = ((short)fifo_data[ii+0] << 8) | fifo_data[ii+1];
  41. accel[1] = ((short)fifo_data[ii+2] << 8) | fifo_data[ii+3];
  42. accel[2] = ((short)fifo_data[ii+4] << 8) | fifo_data[ii+5];
  43. ii += 6;
  44. sensors[0] |= INV_XYZ_ACCEL;
  45. }
  46. if (dmp.feature_mask & DMP_FEATURE_SEND_ANY_GYRO) {
  47. gyro[0] = ((short)fifo_data[ii+0] << 8) | fifo_data[ii+1];
  48. gyro[1] = ((short)fifo_data[ii+2] << 8) | fifo_data[ii+3];
  49. gyro[2] = ((short)fifo_data[ii+4] << 8) | fifo_data[ii+5];
  50. ii += 6;
  51. sensors[0] |= INV_XYZ_GYRO;
  52. }
  53. if (dmp.feature_mask & (DMP_FEATURE_TAP | DMP_FEATURE_ANDROID_ORIENT))
  54. decode_gesture(fifo_data + ii);
  55. get_ms(timestamp);
  56. return 0;
  57. }

结果

MPU9250传感器相关推荐

  1. 龙邱MPU9250传感器 | 使用ESP32 模块进行测试

    简 介: 利用ESP32 MicroPython对于来自于龙邱的MPU9250进行初步测试. 关键词: MPU9250,I2C,ESP32,软件I2C #mermaid-svg-fMBqdJ8sCAu ...

  2. PX4添加外置IMU传感器MPU-9250

    使用PX4 v1.13.2代码,淘宝购买的MPU-9250传感器 MPU-9250 芯片架构图 实物图 手册: 寄存器 https://invensense.tdk.com/wp-content/up ...

  3. 基于Matlalb使用惯性传感器融合和MPU9250估计方向(附源码)

    目录 一.硬件连接 二.创建传感器对象 2.1 创建一个对象并包含 I2C 库 2.2 创建 MPU-9250 传感器对象 2.3 补偿磁力计失真 2.4 将MPU-9250传感器的轴线与NED坐标对 ...

  4. 使用ESP32 MicroPython I2C功能读取 BH1750光度传感器模块数据

    简 介: 使用ESP32读取BH1750的光度传感器的数据.但是最终不知道甚么原因,所读取的数据都是0 ? 后面通过证明,说明在原来进行I2C写的时候出现了语法错误. 关键词: BH1750,ESP3 ...

  5. 龙邱 MPU9250 模块接口 | 基于ESP32模块

    简 介: 制作了MPU9250的转接接口,并利用舵机带动起旋转测量了模块测量角度功能. 关键词: MPU9250,ESP32 #mermaid-svg-dGY7dbxoXuc3EI5H {font-f ...

  6. ESP32设备驱动-MPU-9250 3轴陀螺仪/加速度计/磁力计驱动

    MPU-9250 3轴陀螺仪/加速度计/磁力计驱动 1.MPU9250介绍 MPU-9250 是面向智能手机.平板电脑.可穿戴传感器和其他消费市场的第二代 9 轴运动处理单元™(Motion Proc ...

  7. 一、Arduino+MPU6050/MPU9250——IMU惯性传感器原理

    由于最近的一个小项目,接触到了Arduino+MPU9250获取加速度.角速度和磁场数据,并计算Pitch角.Roll角.Yaw角.现对搜索到的资料和复现的代码进行一些整理. 目录 一. IMU原理 ...

  8. 九轴传感器MPU9250数据读取磁力计

    有的小伙伴找不到MPU9250的中文资料,只能根据MPU6500的例程读取六轴. 关键的地方是MPU9250里已经说明了,看不到实在不应该. MPU9150里面是MPU6500+AK8975,MPU9 ...

  9. 四旋翼无人机学习第6节--SPL06气压传感器和MPU9250九轴传感器电路分析

    文章目录 0 前言 1 SPL06气压传感器芯片手册示例图分析 2 原理图绘制成果分享 3 芯片IIC功能介绍 4 MPU9250气压传感器芯片手册示例图分析 5 原理图绘制成果分享 6 防护罩原理图 ...

  10. PX4原生固件SPI驱动动编写与IMU传感器替换

    适用于PX4原生固件 核心目标:完成XSENS的MTI3,IMU替换.MTI3是一款航姿参考系统,可以独立的输出四元数,加速度,磁力计等,角速度等航姿信息.里面有完整的卡尔曼滤波,可以替换飞控本身里面 ...

最新文章

  1. en45545防火标准_EN45545-2材料及元件的防火要求
  2. Linux中字符设备注册方式,3.4. 字符设备注册
  3. MVC5中EF6 Code First启动慢及间隙变慢的一些优化处理
  4. 每日英语:The First Day On A Job Is Tough Work
  5. 讲一讲应用服务的新鲜事儿
  6. SP2010开发和VS2010专家食谱--第二章节--工作流
  7. python-类方法和属性
  8. 【SPOJ COT2】Count on a tree II,树上莫队
  9. 文字描边_巧用Illustrator“3D”和“凸出和斜角”功能,制作炫酷立体文字
  10. Vue修改mint-ui默认样式(默认风格)
  11. 古代汉语复习资料与练习题(适合王力版教材)
  12. 判断是否为字母 ctype
  13. 点播和播放器下载需要的参数的区别(VideoId、AccessKeyId、AccessKeySecret、playKey、playauth)...
  14. STM32与DS1302设计时钟芯片,超详细
  15. 计算机的剪切快捷键是什么意思,剪切的快捷键是什么【快捷键大全】
  16. 医院预约挂号系统的设计
  17. 再见!Notepad++
  18. 计算机主板桥烧坏了怎么办,经验:快速判断主板南、北桥是否损坏
  19. UML建模与软件开发设计(六)——类图设计与类之间的关系
  20. 二层与三层交换机配置

热门文章

  1. 利用 MATLAB 绘制正态分布曲线
  2. DB2学习之表误删除恢复
  3. MEMS陀螺仪传感器的原理
  4. Python爬虫16-Scrapy爬取阳光政务平台信息
  5. bug10下的工具(以防重新装机)
  6. 共享文件 麒麟系统_麒麟操作系统安装手册.doc
  7. 部分js文件在360浏览器极速模式下不加载,不执行的原因
  8. Yate for mac(标记和管理音频文件工具)
  9. 小米 12S Utra 莱卡水印生成在线工具
  10. 什么是存储器?存储器可分为哪三类?