你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】基于STM32的无线飞鼠(二)

[复制链接]
STMCU小助手 发布时间:2022-5-13 19:00
一、 MPU6050简介
MPU6050集成了3轴加速度和3轴陀螺仪,是一款不错的传感器模块,可以用在很多方面,比如:四轴飞控、空中鼠标、两轮平衡车、GPS定位方面、游戏机、3D遥控器、平板设备等等,此模块给我们提供了强大的数据供应,由于将加速度和陀螺仪集成到了一起,免去了组合这两个模块时之间的轴差问题,减少了包装问题,这两年很火,成了DIY制作者的最爱。

二、 细节问题
在淘宝上买MPU6050时,要注意一下几点:

1.查看卖家给出的介绍信息,是否刻意夸大,结合自己所学的知识进行判断。比如:当时在某个论坛上看到某位大神将的,tb上说他们的模块采用高性能的微处理器和先进的动力学解算与卡尔曼动态滤波算法,能够快速求解出模块当前的实时运动姿态。细心的你就会发现它的这种处理器根本就不能提供这种需求,也就是会所计算不出来。2.不要让模块受到碰撞,否则会影响他的性能。

三、相关技术

MPU6050数据是用IIC进行读取的,So必须学会IIC。类似于USB协议,不过和USB比起来可以说是小巫见大巫。

1.IIC技术概述
IIC 即Inter-Integrated Circuit(集成电路总线),这种总线类型是 由飞利浦半导体公司在八十年代初设计出来的两线式串行总线
特点:接口线少、器件封装形式小、通信速率较高
IIC总线只有两根双向信号线,如下图所示:

20150508164558825.jpg

2.IIC数据传输
数据有效位的定义:
IIC总线在进行数据传输时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线的高电平或低电平状态才允许变化
起始和停止条件:
当SCL线是高电平时,SDA线从高电平向低电平切换,这个情况视为起始条件。
当SCL线是高电平时,SDA线有低电平向高电平切换,表示停止条件
数据传输格式:

20150508164658742.jpg

3.IIC总线寻址
IIC总线规定:从机地址有第一个字节的7位组成
(想要插入表格,可是在这里不会用了,直接从world中截张图算了)

20150508165350695.png

4.IIC总线编号

从机的地址有固定部分和可编程部分组成。在一个系统中可能希望接入多个相同的从机,从机地址中科编程部分决定了可接入总线该类期间的最大数目

例如:一个从机的7位寻址中有4为是固定的,3位是可编程的,那个这时仅能寻址8个同类期间。

5.STM32F103中的IIC
这里主要看下载STM32中,IIC是怎么个分布:

20150508165828778.png

四、操作步骤
1.熟悉MPU6050管脚


20150508174906887.jpg

上图是我自己的模块,由于连上了线,管脚不是很清楚,可以看着一张,管脚和清楚的。

U3FH{[4TW0FIH[H@L$$K(}6.png

2.管脚功能介绍

20150508170531183.png

这里已经很详细的介绍了各个管脚的功能,在心里就有个大概了解,在后面编写代码中就会明白好多,更多细节可以查看手册的!


五、实现代码
当时开始做这个东西的时候参考了原子、野火的各个例子,再次感谢你们。

代码块

MPU初始化:

  1. void MPU_Init()
  2. {
  3.     ANBT_I2C_Configuration();       //IIC初始化
  4.     delay_ms(30);
  5.     AnBT_DMP_MPU6050_Init();        //MPU6050 的DMP初始化
  6. }
复制代码

下边是读取陀螺仪的数据函数:

  1. void Read_Gyro_data(short *rxbuf)
  2. {
  3.     unsigned long sensor_timestamp;
  4.     unsigned char i = 0;
  5.     short gyro[3], accel[3], sensors;//陀螺仪存放数组,加速度存放数组,返回状态量
  6.     unsigned char more;
  7.     long quat[4];       //四元数存放数组

  8.     dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more);
  9.     if(sensors & INV_WXYZ_QUAT)
  10.     {
  11.         rxbuf[0] = gyro[0];
  12.         rxbuf[1] = gyro[1];
  13.         rxbuf[2] = gyro[2];

  14.         printf("\r\nRead_Gyro_data gyro:\r\n");
  15.         for (i = 0; i < 3; i++)
  16.         {
  17.             printf(" %d ",gyro<i>);
  18.         }
  19.         printf("\r\n");
  20.     }
  21. }</i>
复制代码

其实参考了圆点博士的开源代码的,看了下匿名四轴下位机协议,当初试了下自己获取的数据是否正确,很不错的,下面是匿名的协议:

  1. /*
  2. * 函数名:Data_Send_Status
  3. * 描述  :数据发送 传感器  的状态
  4.            根据匿名四轴最新上位机编写的显示姿态的程序
  5. * 输入  :Pitch:俯仰角
  6.            Roll :横滚角
  7.            Yaw  :航向角
  8.            gyro :陀螺仪
  9.            accel:加速度
  10. * 输出  :
  11. * 调用  :
  12. */
  13. void Data_Send_Status(float Pitch,float Roll,float Yaw,int16_t *gyro,int16_t *accel)
  14. {
  15.     unsigned char i = 0;
  16.     unsigned char j = 0;
  17.     unsigned char _cnt = 0,sum = 0;
  18.     unsigned int _temp;

  19.     u8 data_to_send[12] = {0};      //发送数组,初始化为0

  20.     data_to_send[_cnt++] = 0xAA;    // 帧头 170
  21.     data_to_send[_cnt++] = 0xAA;    //      170
  22.     data_to_send[_cnt++] = 0x01;    // 功能字 1
  23.     data_to_send[_cnt++] = 0;       // 长度   0

  24.     //横滚角
  25.     _temp = (int)(Roll * 100);   
  26.     data_to_send[_cnt++] = BYTE1(_temp);  // 高 8 位
  27.     data_to_send[_cnt++] = BYTE0(_temp);  // 低8位

  28.     //俯仰角
  29.     _temp = 0 - (int)(Pitch * 100);
  30.     data_to_send[_cnt++] = BYTE1(_temp);
  31.     data_to_send[_cnt++] = BYTE0(_temp);

  32.     //航向角
  33.     _temp = (int)(Yaw * 100);
  34.     data_to_send[_cnt++] = BYTE1(_temp);
  35.     data_to_send[_cnt++] = BYTE0(_temp);

  36.     data_to_send[3] = _cnt - 4;     //数据长度

  37.     //和校验
  38.     for(i = 0;i < _cnt;i++)
  39. <i>        sum += data_to_send;
  40.     data_to_send[_cnt++] = sum;

  41.     data_to_send[_cnt++] = '\0';

  42.     //NRF_Tx_Dat(data_to_send);   //发送到NRF缓冲区
  43.     //printf("\r\nData_Send_Status:\r\n");
  44. //     for (j = 0; j < 12;j++)
  45. //     {
  46. //         printf("  %d  ",data_to_send[j]);
  47. //     }
  48. //   printf("\r\n");
  49. //  //串口发送数据
  50.     for(i=0;i<_cnt;i++)
  51.         AnBT_Uart1_Send_Char(data_to_send);

  52. }

  53. /*
  54. * 函数名:Send_Data
  55. * 描述  :用于发送传感器的数据
  56. * 输入  :Gyro:陀螺仪存放字符指针
  57.            Accel:加速度存放指针
  58. * 输出  :
  59. * 调用  :
  60. */
  61. void Send_Data(int16_t *Gyro,int16_t *Accel)
  62. {
  63.     unsigned char j = 0;
  64.     unsigned char i = 0;
  65.     unsigned char _cnt = 0;
  66.     unsigned char sum = 0;
  67.      u8 status;
  68. //  unsigned int _temp;
  69.     /*
  70.         匿名数据协议:
  71.         帧头、功能字、长度(len)、数据、校验和(Sum) 共32字节
  72.         接收端在接收到数据的时候进行对应的解析即可
  73.     */
  74.     u8 data_to_send[12];

  75.     data_to_send[_cnt++] = 0xAA;    //帧头  AAAA
  76.     data_to_send[_cnt++] = 0xAA;   
  77.     data_to_send[_cnt++] = 0x02;    //功能字
  78.     data_to_send[_cnt++] = 0;       //长度


  79.     data_to_send[_cnt++] = BYTE1(Accel[0]);
  80.     data_to_send[_cnt++] = BYTE0(Accel[0]);
  81.     data_to_send[_cnt++] = BYTE1(Accel[1]);
  82.     data_to_send[_cnt++] = BYTE0(Accel[1]);
  83.     data_to_send[_cnt++] = BYTE1(Accel[2]);
  84.     data_to_send[_cnt++] = BYTE0(Accel[2]);

  85.     data_to_send[_cnt++] = BYTE1(Gyro[0]);
  86.     data_to_send[_cnt++] = BYTE0(Gyro[0]);
  87.     data_to_send[_cnt++] = BYTE1(Gyro[1]);
  88.     data_to_send[_cnt++] = BYTE0(Gyro[1]);
  89.     data_to_send[_cnt++] = BYTE1(Gyro[2]);
  90.     data_to_send[_cnt++] = BYTE0(Gyro[2]);
  91.     data_to_send[_cnt++] = 0;
  92.     data_to_send[_cnt++] = 0;
  93.     data_to_send[_cnt++] = 0;

  94.     data_to_send[3] = _cnt - 4;
  95.     for(i = 0;i < _cnt;i++)
  96.         sum += data_to_send;

  97.     data_to_send[_cnt++] = sum;

  98.     data_to_send[_cnt++] = '\0';

  99. //     printf("\r\nSend_Data:\r\n");
  100. //     for (j = 0; j < 12;j++)
  101. //     {
  102. //          printf("  %d ",data_to_send[j]);
  103. //     }
  104. //     printf("\r\n");
  105. //     delay_ms(1000);
  106. //     status = NRF_Tx_Dat(data_to_send);
  107. //     
  108. //    /*判断发送状态*/
  109. //     switch(status)
  110. //     {
  111. //         case MAX_RT:
  112. //             printf("\r\n 主机端 没接收到应答信号,发送次数超过限定值,发送失败。 \r\n");
  113. //             break;

  114. //         case ERROR:
  115. //             printf("\r\n 未知原因导致发送失败。 \r\n");
  116. //             break;

  117. //         case TX_DS:
  118. //             printf("\r\n 主机端 接收到 从机端 的应答信号,发送成功! \r\n");         
  119. //             break;                              
  120. //     }
  121. //     
  122. //     delay_ms(1000);

  123. //  //串口发送数据
  124.     for(i = 0;i <_cnt;i++)
  125.         AnBT_Uart1_Send_Char(data_to_send);
  126. }</i>
复制代码

在主函数中调用相应的函数即可获取相关数据,做一个简单的测试。
一下是我从串口中获取的数据:
ML)%UN}OU5~78MDW%QJLFKJ.png

以及其他数据:

20150508173526385.png

因为代码中使用了圆点博士的开源代码,而且都是现成的,就不往出贴了……
以上只是做了个简单介绍,以及获取到了数据,但是并没有说明怎样处理数据,这是很关键的也是最重要的,本次无线飞鼠的数据不好处理,我做到现在数据也不是很稳定,任然有一定幅度的变化。




收藏 评论0 发布时间:2022-5-13 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版