115|2

9

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【Follow me第二季第4期】任务二:学习IMU基础知识,调试IMU传感器,通过串口打印... [复制链接]

  本帖最后由 mingzhe123 于 2024-12-1 12:16 编辑

IMU原理及选型介绍

所谓IMU(Inertial Measurement Unit)是指惯性测量单元,利用惯性的变化测量物体加速运动和旋转。其中目前主流的惯性测量器件是MEMS(微机电)传感器,它将用于机械结构缩小至纳米尺度,可测量机器人加速度与旋转角速度。后面讨论的内容应该可以归为捷联式惯导系统(Strapdown Inertial Navigation System),即测量单元直接安装于被测物体上,与平台式惯导系统区别开来。

需要注意的是,IMU或者说六轴(6Dof)传感器讨论的是三轴加速度计和三轴角速度计(俗称陀螺仪),与AHRS(航姿参考系)或者说9轴(9Dof)传感器是有区别的,后者增加了磁力计,以地磁场作为参考。但是在地面机器人运动并且夹杂大量电机磁干扰的情况下,引入微弱的地磁作为绝对航向并不是一个好主意。

原理

 

 

当物体运动的惯性改变时,根据牛顿第二定律实际上物体内部会有相对的作用力,我们可以想象一个加速度计的结构如上图,在整个系统加速或减速时弹簧会有不同程度的伸长或压缩,通过测量弹簧的所连接的物体的位移可以测量出实际加速度的大小,当然这其中也包含重力加速度。在目前MEMS工艺制造的传感器中这些结构都被缩得非常小,以至于测量的位置可以视为被缩在同一点上。

而角速度计的原理类似,但是测量原理是令质量块不断在轴的径向上产生移动,探测其切向偏移测量科氏力大小,从而推出角速度的大小。

性能

通常情况下,这两种传感器都有一般传感器所拥有的性能指标,例如不论是机械制造的误差还是A/D采样带来的偏置,满刻度误差,以及采样数据的噪声还有抗震性能,当然这些也会受到温度和输入电压的影响。有些误差的校正会在后续的校准中提到。

IMU参数

作为一种电子元器件,基本的参数都可以在其数据手册(datasheet)中查到,这些参数说明了IMU的性能范围,可以为选型提供参考,这里列举一些常用的参数

  • 量程和灵敏度(sensitivity):代表最大角速度或加速度范围和取样精度,通常有数字接口的IMU都会有这项
  • 敏感度温漂(sensitivity change over temperature/ sensitivity temperature drift):敏感度随温度的改变,通常用百分比或者FS/K(满刻度每度)
  • 零偏(zero-rate offset/level):IMU中尤其针对角速度计的一个重要参数,它代表了角速度计/加速计在静止时仍然输出的大小,是后续IMU校准中重点讨论的参数。我们希望它越小越好,以避免积分时带来的累计误差。通常目前IMU给出的典型值都是在1deg/s以上。
  • 温度漂移(zero-rate offset change over temperature):零偏随温度改变的大小,同样是角速度计的重要参数,越小代表IMU的零偏随温度影响越小。
  • 噪声系数(noise):代表输出噪声与带宽的关系,单位一般为(ug/√Hz或者dps/√Hz),直观的说就是影响对真实信号的辨识程度。
  • 交叉轴敏感度(cross-axis sensitivity):通常情况下三个轴的输出应该都是独立的,但实际上可能出现跨轴影响输出的现象,这个参数就是用于衡量各轴之间的影响程度
  • 加速度敏感度(g-sensitivity):角速度计特有的参数,用于衡量加速度对角速度计输出的影响大小,通常单位为dps/g
  • 零偏不稳定性:主要针对角速度计的参数,代表零偏在较长时间下的随机游走

IMU选型

目前可以找到的IMU厂商有以下几个:

  • TDK InvenSense:MEMS加速度计,角速度计,磁力计,六轴/九轴厂商,有广泛使用的IMU MPU6050,价位中等(也有更贵的高性能的ICM系列)
  • ST(意法半导体):MEMS加速度计,角速度计以及六轴厂商,主要为智能手机市场提供IMU,例如有LSM6DS3TR,价位偏低
  • Bosch(博世):MEMS加速度计,角速度计,磁力计,六轴/九轴厂商,主要为机器人和无人机市场提供IMU,六轴传感器的有BMI系列,价位偏高
  • ADI:老牌半导体公司,有加速度计和六轴,主要用于汽车和军事领域,性能最高但价位也是极高。当然也有低端的加速计ADXL35x系列
  • QST(上海矽睿):磁力计,加速度计以及六轴的国产厂商,有QMI8658/QMI8610等六轴传感器

选型过程自然要比较性能,当然主要看零偏,温漂以及噪声。考虑到价格因素,ADI的六轴这个选项基本可以舍弃。高性能的一档有ICM4x6xx,BMI0xx,QMI86xx和LSM6Dx的性能略逊一筹。

截止目前,已知官方有库存的只有ST和QST。在疫情的背景下,选用国产的IMU或许更能确保稳定供应。

Arduino Nano RP2040 Connect  --  LSM6DSOX

开发板使用的是LSM6DSOXTR是一款高性能的6轴惯性测量单元(IMU),由STMicroelectronics(意法半导体)制造。集成了3轴数字加速度计和3轴数字陀螺仪,采用系统级封装技术,具有出色的性能和低功耗特性。提供SPI、I²C和MIPI I3C串行接口,支持主处理器数据同步。是一款功能强大、性能卓越的6轴IMU。其手册特征如下图所示。意法半导体为其封装了传感器专用库-

链接已隐藏,如需查看请登录或者注册
库,使用Arduino编程只需调用其库即可。

 

IMU编程与调试

Arduino® Nano RP2040 Connect代码:


/* WIRING
  In order to use the Adafruit lsm6dsox sensor with a ST nucleo board,
  plug Nucleo "+3.3V" to AdafruitLSM6DOX "VIN",
  plug Nucleo "GND" to AdafruitLSM6DOX "GND",
  plug Nucleo "SCL"(D15) to AdafruitLSM6DOX "SCL",
  plug Nucleo "SDA"(D14) to AdafruitLSM6DOX "SDA".*/

#include "LSM6DSOXSensor.h"
#include <Arduino.h>
// Declare LSM6DSOX sensor. Sensor address can have 2 values LSM6DSOX_I2C_ADD_L (corresponds to 0x6A I2C address) or LSM6DSOX_I2C_ADD_H (corresponds to 0x6B I2C address)
// On Adafruit lsm6dsox sensor, LSM6DSOX_I2C_ADD_L is the default address
LSM6DSOXSensor lsm6dsoxSensor = LSM6DSOXSensor(&Wire, LSM6DSOX_I2C_ADD_L);

int flag;
long  last_update_time;


// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 1000;

void setup() {
  Serial.begin(115200);
  
  Serial1.begin(115200); // opensserial port, sets data rate to 115200 bps  
  while(Serial1.read()>= 0){}//clear serialbuffer 

  pinMode(LED_BUILTIN,OUTPUT);

  digitalWrite(LED_BUILTIN,LOW);

  Wire.begin();

  // Default clock is 100kHz. LSM6DSOX also supports 400kHz, let's use it
  Wire.setClock(400000);

  // Init the sensor
  lsm6dsoxSensor.begin();

  // Enable accelerometer and gyroscope, and check success
  if (lsm6dsoxSensor.Enable_X() == LSM6DSOX_OK && lsm6dsoxSensor.Enable_G() == LSM6DSOX_OK) {
    Serial.println("Success enabling accelero and gyro");
  } else {
    Serial.println("Error enabling accelero and gyro");
  }

  // Read ID of device and check that it is correct
  uint8_t id;
  lsm6dsoxSensor.ReadID(&id);
  if (id != LSM6DSOX_ID) {
    Serial.println("Wrong ID for LSM6DSOX sensor. Check that device is plugged");
  } else {
    Serial.println("Receviced correct ID for LSM6DSOX sensor");
  }

  // Set accelerometer scale at +- 2G. Available values are +- 2, 4, 8, 16 G
  lsm6dsoxSensor.Set_X_FS(2);

  // Set gyroscope scale at +- 125 degres per second. Available values are +- 125, 250, 500, 1000, 2000 dps
  lsm6dsoxSensor.Set_G_FS(125);


  // Set Accelerometer sample rate to 208 Hz. Available values are +- 12.0, 26.0, 52.0, 104.0, 208.0, 416.0, 833.0, 1667.0, 3333.0, 6667.0 Hz
  lsm6dsoxSensor.Set_X_ODR(208.0f);


  // Set Gyroscope sample rate to 208 Hz. Available values are +- 12.0, 26.0, 52.0, 104.0, 208.0, 416.0, 833.0, 1667.0, 3333.0, 6667.0 Hz
  lsm6dsoxSensor.Set_G_ODR(208.0f);


}


void IMU_update(int interval)
{
  // Read accelerometer
  uint8_t acceleroStatus;
  lsm6dsoxSensor.Get_X_DRDY_Status(&acceleroStatus);
  if (acceleroStatus == 1) { // Status == 1 means a new data is available
    int32_t acceleration[3];
    lsm6dsoxSensor.Get_X_Axes(acceleration);
    // Plot data for each axis in mg
    Serial.print("AccelerationX="); 

    Serial.print(acceleration[0]); 

    Serial.print("mg, AccelerationY="); 

    Serial.print(acceleration[1]); 

    Serial.print("mg, AccelerationZ="); 

    Serial.print(acceleration[2]); 
    Serial.println("mg");


    if (millis() - last_update_time > interval)
	  {
		  if (acceleration[1] > 1000)
		  {
			//encoder_diff--;
			flag = 1;
      Serial.print("flag=1");
      Serial1.write(49);
      digitalWrite(LED_BUILTIN,LOW);
		  }
		else if (acceleration[1] < -1000)
		{
		//	encoder_diff++;
			flag = 2;
      Serial.print("flag=2");
      Serial1.write(50);
      digitalWrite(LED_BUILTIN,HIGH);
		}
		else
		{
			flag = 0;
		} 

		last_update_time = millis();
	  }
  }
  
	

  // Read gyroscope
  uint8_t gyroStatus;
  lsm6dsoxSensor.Get_G_DRDY_Status(&gyroStatus);
  if (gyroStatus == 1) { // Status == 1 means a new data is available
    int32_t rotation[3];
    lsm6dsoxSensor.Get_G_Axes(rotation);
    // Plot data for each axis in milli degrees per second
    Serial.print("RotationX="); 

    Serial.print(rotation[0]);

    Serial.print("mdps, RotationY="); 

    Serial.print(rotation[1]); 

    Serial.print("mdps, RotationZ="); 

    Serial.print(rotation[2]); 
    Serial.println("mdps");
  }
 
}


void loop() {

  
  IMU_update(200);

}

PICO2端代码:

int val;



void setup() {



  Serial1.setRX(17);

  Serial1.setTX(16);

  Serial1.begin(115200); // opensserial port, sets data rate to 9600 bps  

  while(Serial.read()>= 0){}//clear serialbuffer

  pinMode(25,OUTPUT);



}



void loop() {



   if (Serial1.available() > 0) {

    delay(100); // 等待数据传完

    int numdata = Serial1.available();

    val=Serial1.read();

    Serial1.println(val);

    if(val==49)

    {

      Serial.println("Test OK");

      Serial.println(val);



     // delay(2000);

      digitalWrite(25, LOW);

    }

    if(val==50)

    {

      Serial.println("Test OK!!!");

      Serial.println(val);



      digitalWrite(25, HIGH);



    }

    while(Serial1.read()>=0){} //清空串口缓存

  }

     




}

上位机打印的IMU数据:

  总结:

  实现IMU的控制与数据读取还是十分简单的,只需调用官方Arduino库即可,这大大降低了开发者的开发难度。

  演示视频:

   

3c7aacbe69bae7d77d331d5a7bb42dd4

 

最新回复

IMU厂商,你这都是大厂啊     详情 回复 发表于 前天 09:35
点赞 关注
 
 

回复
举报

9

帖子

1

TA的资源

一粒金砂(中级)

沙发
 
视频中应该是调用意法半导体官方的arduino库
链接已隐藏,如需查看请登录或者注册
 
 
 

回复

6168

帖子

6

TA的资源

版主

板凳
 

IMU厂商,你这都是大厂啊  

个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

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

随便看看
查找数据手册?

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
快速回复 返回顶部 返回列表