4883|12

654

帖子

26

TA的资源

版主

楼主
 

当BLE遇到MEMS——收服和调教MEMS [复制链接]

 
  本帖最后由 lb8820265 于 2018-3-16 00:38 编辑

       当BLE遇到MEMS,就如同天使有了翅膀。本期从有浅入深的介绍BLE与MEMS的那些事,就从ST的STEVAL-IDB007V1开发板中BLE_SensorDemo例程开始。
蓝牙入门
       网上资料很多,可参考《蓝牙BLE权威教程》,或者看看聊聊入门BLE开发需要知道的事
开发环境搭建
        请参考论坛帖子STEVAL-IDB007V1之透传演示操作流程和所需软件资源下载,从开始菜单进入BlueNRG-1 Navigator可以实际运行各种例程查看效果。
硬件连接
       使用ST-Link V2中SWCLK与SWDIO与开发板对应的引脚连接,用来仿真;供电和串口都通过USB线缆。
程序烧录
       蓝牙芯片的开发和普通MCU的开发并没什么不同,虽说蓝牙芯片里面有协议栈,但是基本不用管,也不要害怕会将其覆盖,学会调用其接口函数就好。打开安装路径下BLE_Examples\BLE_SensorDemo工程,编译烧录(如果烧录不进,使用BlueNRG-1Flasher将内存擦除,然后使用BlueNRG-1 ST-LINK Utility工具确认能够连接上)。
程序初窥
         官方代码并没有使用HAL库或者LL库,很多地方直接操作寄存器,或许这是为了节约内存吧,程序的流程是手机发送指令,芯片接收指令后发送相关的数据,例如发送一个需求加速度计值的指令,芯片就发送一次数据过去。
         官方的演示是可以姿态的,但实际上程序的姿态的获取确只用到了加速度计,加速度计在晃动的时候会抖动的厉害,实际情况却还是不错的,是因为程序将数据更新频率设为了13Hz,虽然没有开启滤波但是这样却大大的减少了抖动,这样使用加速度计来估计姿态在低速下是不错的,而且可以节约计算,但是确是相当的不准确。其实芯片是自带有高通滤波和底通滤波的,如果开启的话效果会更好。
更准确的读取数据
      陀螺仪加速度计使用的是LSM6DS3,这个不算是ST最新的。在之前我做小车的时候曾经用过这款,发现过不少的坑,其中之一就是,连续读取值会读到错误值,下图是将更新频率设置为6600Hz的时候,连续采集时候的陀螺仪的值。
      下图是局部放大图:
      会发现陀螺仪的值会跳变(不同的倾角下跳变的概率不一样,更新频率越高,跳变的概率越大),由于陀螺仪在原始的寄存器值上乘以了70,将跳变值除以70后为+255和-255。
      经过一系列的摸索,和ST工程师的帮助,终于解决了问题,见下图,那就是将BDU(Block Data Update)位置1,没有置1的话,数据没有准备好就被读出来也是有可能的,这也就是为何更新频率设置的越高就会越容易出现错误值的原因。
       其实早在2015年在数据手册中就建议将BDU位置1了,后来的官方初始化程序中也都将BDU置1了。
       下面是不动芯片,仅仅将BDU置1后的效果:
   因此想要准确的的获取的数据记得将BDU位置1哦。
更高效的读取数据
      该传感器使用的是SPI接口,这点很好,相比于IIC,SPI这是要快太多了,我们可以节约更多的时间用来做其他的事,也有利于节能,该芯片最高支持10MHz的SPI速度,但是驱动却写的不是很高效,官方代码如下:
  1. static IMU_6AXES_StatusTypeDef    LSM6DS3_G_GetAxes( int32_t *pData )
  2. {
  3.   /*Here we have to add the check if the parameters are valid*/
  4.   int16_t pDataRaw[3];
  5.   float sensitivity = 0.0f;
  6.   if(LSM6DS3_G_GetAxesRaw(pDataRaw) != IMU_6AXES_OK)
  7.   {
  8.     return IMU_6AXES_ERROR;
  9.   }
  10.   if(LSM6DS3_G_GetSensitivity( &sensitivity ) != IMU_6AXES_OK)
  11.   {
  12.     return IMU_6AXES_ERROR;
  13.   }
  14.   pData[0] = (int32_t)(pDataRaw[0] * sensitivity);
  15.   pData[1] = (int32_t)(pDataRaw[1] * sensitivity);
  16.   pData[2] = (int32_t)(pDataRaw[2] * sensitivity);
  17.   return IMU_6AXES_OK;
  18. }
复制代码
  1. static IMU_6AXES_StatusTypeDef LSM6DS3_G_GetAxesRaw( int16_t *pData )
  2. {
  3.   /*Here we have to add the check if the parameters are valid*/
  4.   uint8_t tempReg[2] = {0, 0};
  5.   if(LSM6DS3_IO_Read(&tempReg[0], LSM6DS3_XG_MEMS_ADDRESS, LSM6DS3_XG_OUT_X_L_G, 2) != IMU_6AXES_OK)
  6.   {
  7.     return IMU_6AXES_ERROR;
  8.   }
  9.   pData[0] = ((((int16_t)tempReg[1]) << 8) + (int16_t)tempReg[0]);
  10.   if(LSM6DS3_IO_Read(&tempReg[0], LSM6DS3_XG_MEMS_ADDRESS, LSM6DS3_XG_OUT_Y_L_G, 2) != IMU_6AXES_OK)
  11.   {
  12.     return IMU_6AXES_ERROR;
  13.   }
  14.   pData[1] = ((((int16_t)tempReg[1]) << 8) + (int16_t)tempReg[0]);
  15.   if(LSM6DS3_IO_Read(&tempReg[0], LSM6DS3_XG_MEMS_ADDRESS, LSM6DS3_XG_OUT_Z_L_G, 2) != IMU_6AXES_OK)
  16.   {
  17.     return IMU_6AXES_ERROR;
  18.   }
  19.   pData[2] = ((((int16_t)tempReg[1]) << 8) + (int16_t)tempReg[0]);
  20.   return IMU_6AXES_OK;
  21. }
复制代码

      每次都是单次读取(读两个字节)每一轴的数据,而且还获取了一次sensitivity(读一个字节)。
      我们知道SPI要完成一次读数据的操作,本质是需要读写两次的,第一次将地址写进去,然后再将0写入,将数据弄出来。因此驱动如果需要读取6轴的数据一共需要写12次,读18次SPI。而我认为sensitivity是开始设置的,可以不读,然后6轴的数据可以一次全部读出来,因为默认SPI地址是会累加的,如下图所示:
      因此程序可以改成如下,然后将陀螺仪值乘以70,加速度计值乘以0.122
  1. void Get_Sensor_RawData(void){
  2.       Sensor_IO_Read(NULL,LSM6DSL_ACC_GYRO_OUTX_L_G,regValue, 12);     
  3.        for(int i=0;i<6;i++){
  4.          Sensor_Raw_Data[/size][/font][font=微软雅黑][size=3] = ( ( ( ( int16_t )m_rx_buf[2*i+2] ) << 8 ) + (int16_t )m_rx_buf[2*i+1] );
  5.        }
  6. }
复制代码

      从0x22地址开读,也就是写1次,读12次,而且还节约了SPI的开启和关闭的耗时,这样就大大的提高的数据获取的速度,如果可以使用DMA能够更高效。
         因此如果想要更加高效的使用陀螺仪加速度计,记得要连续的读取12个字节且无需读取灵敏度哦。


最新回复

这个位置1,为什么还跳啊?加速度值读出来没问题,角速度怎么都不对!   详情 回复 发表于 2018-8-9 14:52

赞赏

1

查看全部赞赏

点赞 关注(1)
个人签名QQ:252669569
 
 

回复
举报

297

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
确实是一个坑
 
 
 

回复

9720

帖子

24

TA的资源

版主

板凳
 
BDU为0时检测DRDY中断后读取也会这样吗?

点评

如果是中断后读取就不会出现这样的问题了  详情 回复 发表于 2018-3-16 18:02
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

654

帖子

26

TA的资源

版主

4
 
littleshrimp 发表于 2018-3-16 09:24
BDU为0时检测DRDY中断后读取也会这样吗?

如果是中断后读取就不会出现这样的问题了

点评

如果是因为数据没有准备好就执行了读取操作,将BDU改为1后读到的数据也应该有很多无效数据 比如它可能是0,在你的曲线里即使出现了也不容易发现 另一种可能是每次读取数据时传感器都有足够的时间将转换完成,只不  详情 回复 发表于 2018-3-19 12:51
个人签名QQ:252669569
 
 
 

回复

7815

帖子

57

TA的资源

裸片初长成(中级)

5
 
老李,你变了,当我看到这个标题,我就知道这段时间你肯定干了或者想了很多很邪恶很黄的事情。
个人签名

强者为尊,弱者,死无葬身之地

 
 
 

回复

9720

帖子

24

TA的资源

版主

6
 
lb8820265 发表于 2018-3-16 18:02
如果是中断后读取就不会出现这样的问题了

如果是因为数据没有准备好就执行了读取操作,将BDU改为1后读到的数据也应该有很多无效数据
比如它可能是0,在你的曲线里即使出现了也不容易发现
另一种可能是每次读取数据时传感器都有足够的时间将转换完成,只不过你读取数据的间隔时间在动态变化
有的时候正好赶上传感器将转换好的数据往寄存器里更新的过程中被你读到了

点评

将BDU改为1后确实就没有了无效数据了,而且我敢肯定无效数据不是0了,会不会是等待数据完成才允许读这个不得而知。 因为芯片可选的更新周期并不是整数,比如104Hz啥的,所以周期定时读取难免会遇到刚好正在准备数据  详情 回复 发表于 2018-3-19 23:57
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

1903

帖子

0

TA的资源

版主

7
 
 
 

回复

654

帖子

26

TA的资源

版主

8
 
littleshrimp 发表于 2018-3-19 12:51
如果是因为数据没有准备好就执行了读取操作,将BDU改为1后读到的数据也应该有很多无效数据
比如它可能是 ...

将BDU改为1后确实就没有了无效数据了,而且我敢肯定无效数据不是0了,会不会是等待数据完成才允许读这个不得而知。
因为芯片可选的更新周期并不是整数,比如104Hz啥的,所以周期定时读取难免会遇到刚好正在准备数据,也就是和你说的原因差不多。
个人签名QQ:252669569
 
 
 

回复

875

帖子

1

TA的资源

纯净的硅(高级)

9
 
这两天调试这个陀螺,也遇到了这个问题,费了好大的劲才解决了问题,但是现在遇到一个新的问题,那就是温度的影响有点大,该怎么解决?

点评

你是说影响陀螺仪的零偏吧,这个确实是这个芯片的一个很大的问题,芯片本身的零偏就巨大,更不要说温偏了。ST的工程师说建议使用LSM6DSL,事实上这个是要好一点。  详情 回复 发表于 2018-6-15 00:48
 
 
 

回复

654

帖子

26

TA的资源

版主

10
 
曹伟1993 发表于 2018-6-14 20:02
这两天调试这个陀螺,也遇到了这个问题,费了好大的劲才解决了问题,但是现在遇到一个新的问题,那就是温度 ...

你是说影响陀螺仪的零偏吧,这个确实是这个芯片的一个很大的问题,芯片本身的零偏就巨大,更不要说温偏了。ST的工程师说建议使用LSM6DSL,事实上这个是要好一点。

点评

我用的是ISM330DLC,也就是这款芯片的加强版,但是资料差不多,性能应该强一些,可是我调试也是出现温偏  详情 回复 发表于 2018-6-15 09:20
个人签名QQ:252669569
 
 
 

回复

875

帖子

1

TA的资源

纯净的硅(高级)

11
 
lb8820265 发表于 2018-6-15 00:48
你是说影响陀螺仪的零偏吧,这个确实是这个芯片的一个很大的问题,芯片本身的零偏就巨大,更不要说温偏了 ...

我用的是ISM330DLC,也就是这款芯片的加强版,但是资料差不多,性能应该强一些,可是我调试也是出现温偏
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

12
 
这个位置1,为什么还跳啊?加速度值读出来没问题,角速度怎么都不对!

点评

不知道你用的哪个库呢?可能有其他地方还需要设置,你完全按照官方的设置来试试,然后还是不行的话那就只能在中断里面读取了。  详情 回复 发表于 2018-8-10 00:16
 
 
 

回复

654

帖子

26

TA的资源

版主

13
 
nxmhp 发表于 2018-8-9 14:52
这个位置1,为什么还跳啊?加速度值读出来没问题,角速度怎么都不对!

不知道你用的哪个库呢?可能有其他地方还需要设置,你完全按照官方的设置来试试,然后还是不行的话那就只能在中断里面读取了。
个人签名QQ:252669569
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

开源项目 更多>>
    随便看看
    查找数据手册?

    EEWorld Datasheet 技术支持

    相关文章 更多>>
    关闭
    站长推荐上一条 1/10 下一条

     
    EEWorld订阅号

     
    EEWorld服务号

     
    汽车开发圈

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

    电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表