从BNO055传感器获取IMU数据-2

18 篇文章 1 订阅

在前面的文章 从BNO055传感器获取IMU数据-1 中介绍了BNO055传感器,今天继续讲解应用示例。

传感器与Arduino接口

我从某宝购买了固定在带有支持组件的开发板上的 BNO055 传感器。从 Digi-Key 或贸泽购买 BNO055 并将其焊接到 7.5×4.4mm 28 引脚 LGA 至 DIP 转换器上,以便在无焊试验板上进行原型设计,可以节省一点钱。但是对于运输后的边际成本节省,我不推荐它。

要开始使用 BNO055 与 Arduino 接口,请按照以下步骤操作:

  1. 连接电源、接地、SDA 和 SCL
  2. 打开Arduino IDE,然后单击Sketch→Include Library→Manage Libraries
  3. 搜索并安装“Adafruit BNO055”和“Adafruit Sensor”
  4. 打开并编辑文件→示例→Adafruit BNO055→Raw Data以注释掉欧拉角部分并取消注释四元数部分,或复制并粘贴下面的代码片段。
#include 
#include 
#include 
#include 

/*
This program is an abridged version of Adafruit BNO055 rawdata.ino available after installing the Adafruit BNO055 library
File→Examples→Adafruit BNO055→Raw Data
  Connections on Arduino Uno
  =========================================================================
  SCL to analog 5 | SDA to analog 4 | VDD to 3.3V DC | GND to common ground
*/

#define BNO055_SAMPLERATE_DELAY_MS (100)          // Delay between data requests

Adafruit_BNO055 bno = Adafruit_BNO055();          // Create sensor object bno based on Adafruit_BNO055 library

void setup(void)
{
  Serial.begin(115200);                           // Begin serial port communication
  if(!bno.begin())                                // Initialize sensor communication
  {  
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");  
  }
  delay(1000);
  bno.setExtCrystalUse(true);                     // Use the crystal on the development board
}

void loop(void)
{
  imu::Quaternion quat = bno.getQuat();           // Request quaternion data from BNO055

  Serial.print(quat.w(), 4);  Serial.print("\t"); // Print quaternion w
  Serial.print(quat.x(), 4);  Serial.print("\t"); // Print quaternion x
  Serial.print(quat.y(), 4);  Serial.print("\t"); // Print quaternion y
  Serial.print(quat.z(), 4);  Serial.println();   // Print quaternion z

  delay(BNO055_SAMPLERATE_DELAY_MS);              // Pause before capturing new data
}

该程序只需通过I2C与BNO055通信,并通过UART端口将数据流回计算机。四元数数据作为制表符分隔的数据发送回,每个四元数后带有换行符。

请记住,在校准传感器之前,数据无效。

四元数数据样本

对于以下示例,我从 BNO055 请求四元数数据,因为它以随机方向放置在办公桌附近。你的以通过在单词quaternion后面的括号中输入逗号分隔值来手动解释 WolframAlpha.com 数据(例如,“quaternion(0.403, 0.414, 0.085, 0.812)”)

WXYZ
0.403442380.413635250.085083010.81176757

上面的数字是一个四元数,描述了传感器相对于参考方向的当前方向。

来自 WolframAlpha.com 的图像显示对象的默认和实际方向

来自 WolframAlpha.com 的图像显示了旋转轴和从默认位置到达当前位置所需的旋转量

当然没有必要每次在互联网上查看你的四元数数据,但可以选择性仔细检查数据是很好的实践,尤其是在入门学习阶段。

使用 Mathematica 捕获数据

Mathematica是一个多功能的计算机程序,几乎可以处理你能想象到的任何数据。对于那些感兴趣的人,我整理了几行代码,演示如何从设备接收数据以及如何使用Mathematica通过一些基于四元数的函数来评估数据。下面的代码是为Windows编写的,因此Linux和Mac用户可能必须更改输入设备行(以bConnect开头的行)。

Mathematica 笔记本的屏幕截图,源码可通过下面的下载链接获得

链接: https://pan.baidu.com/s/1AI1Npdj_jgKbg5o0esHtMQ?pwd=mp63 提取码: mp63 复制这段内容后打开百度网盘手机App,操作更方便哦

Mathematica允许实时和事后收集和处理数据。对于此演示,我选择了一个程序,该程序从串行缓冲区收集数据,将其转换为旋转矩阵,并使用旋转矩阵重新定向参考球体中的箭头。

首先单击“连接Arduino”,然后单击“来自缓冲区的数据”。我没有合并任何数据验证或错误检查,因此如果数据区域为空白或格式错误,唯一的选择是重新收集数据。

Mathematica能够在数据通过串行端口到达时读取和处理数据,但对于此演示,存储在缓冲区中的30个左右的测量值应该足以看到程序是如何工作的。

从BNO055发送的数据在Mathematica中进行分析,并用于重新定向参考球中的箭头

控制两轴云台

BNO055非常适合机器人使用。作为示例应用,我将使用 BNO055 控制安装在基于伺服的两轴云台上的激光器。该代码应该允许无缝引入第三个旋转轴,供任何有幸拥有旋转轴的读者使用。

像以前一样连接BNO055并添加伺服器,连接到数字引脚9-11。如果您使用云台来固定相机,请考虑升级到 Alorium XLR8 板。伺服依赖于精确的计时,如果Arduino正在处理竞争任务,则可能导致抖动。XLR8是由FPGA制成的Arduino的直接替代品。它有一个库,可以从单独的“XLR8tor”(加速器)块控制伺服系统,以实现稳定和流畅的伺服运动。

电路的布线概述

Arduino Uno R3 替代品:XLR8 vs Sparkfun “Redboard” Arduino Uno R3

//---- Included Libraries ----//
#include                            // I²C library
#include                            // trig functions
#include                 // Base library for sensors
#include                 // BNO055 specific library
#include                // Vector, Matrix, and IMUMath library
//#include                         // Standard Servo library
#include                       // XLR8 servo library
#include                       // XLR8 accelerated floating point math

#define BNO055_SAMPLERATE_DELAY_MS (50)     // Set pause between samples

//---- Variable Declaration ----//

boolean debug = true;                       // true/false = extra/no information over serial

int rollPin  = 9;                           // Digital pin for roll
int yawPin   = 10;                          // Digital pin for yaw
int pitchPin = 11;                          // Digital pin for pitch

float roll, pitch, yaw;                     // Variable to hold roll, pitch, yaw information

Adafruit_BNO055 bno = Adafruit_BNO055();    // Use object bno to hold information

Servo rollServo;                            // Create servo rollServo
Servo pitchServo;                           // Create servo pitchServo
Servo yawServo;                             // Create servo yawServo

void setup(void) {

  rollServo.attach(rollPin);                // The rollServo is connected at rollPin
  pitchServo.attach(pitchPin);              // The pitchServo is connected at pitchPin
  yawServo.attach(yawPin);                  // The yawServo is connected at yawPin

  Serial.begin(115200);                     // Create serial connection at 115,000 Baud

  if (!bno.begin())                         // Attempt communication with sensor
  {
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
  }

  delay(100);                               // Wait 0.1 seconds to allow it to initialize
  bno.setExtCrystalUse(true);               // Tell sensor to use external crystal
}

//---- Main Program Loop ----//
void loop() {

  //---- Request Euler Angles from Sensor ----//
  imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER);

  if (debug) {                             // If debug is true, send information over serial
    Serial.print("Measured Euler Roll-Pitch-Yaw");
    Serial.print("\t   yaw: "); Serial.print(euler.x()); Serial.print("\t");
    Serial.print("\t pitch: "); Serial.print(euler.z()); Serial.print("\t");
    Serial.print("\t  roll: "); Serial.print(euler.y()); Serial.println();
  }
  /* Remap information from the sensor over the 0° - 180° range of the servo
     The Yaw values are between 0° to +360°
     The Roll values are between -90° and +90°
     The Pitch values are between -180° and +180°
  */
  int servoYaw   = map(euler.x(),   0, 360, 0, 180);
  int servoRoll =  map(euler.y(),  -90, 90, 0, 180);
  int servoPitch = map(euler.z(), -180, 180, 0, 180);

  if (debug) {                             // If debug is true, send information over serial
    Serial.print("Measured Euler Roll-Pitch-Yaw");
    Serial.print("\t   Yaw Servo: "); Serial.print(servoYaw);   Serial.print("\t");
    Serial.print("\t Pitch Servo: "); Serial.print(servoPitch); Serial.print("\t");
    Serial.print("\t  Roll Servo: "); Serial.print(servoRoll);  Serial.println();
  }
  // If debug is true, send information over serial
  if (debug) {
    Serial.println("Calculated Servo Roll-Pitch-Yaw");
    Serial.print("\t roll:");  Serial.print(servoRoll, DEC);  Serial.print("\t");
    Serial.print("\t pitch:"); Serial.print(servoPitch, DEC); Serial.print("\t");
    Serial.print("\t yaw:");   Serial.print(servoYaw, DEC);   Serial.println();
  }

  rollServo.write(servoRoll);              // Send mapped value to rollServo
  pitchServo.write(servoPitch);            // Send mapped value to rollServo
  yawServo.write(servoYaw);                // Send mapped value to rollServo

  delay(BNO055_SAMPLERATE_DELAY_MS);       // Wait before rerunning loop
}

源码下载👇

链接: https://pan.baidu.com/s/1NmL1emNqXAdRGV0XEq8u5Q?pwd=wdu1 提取码: wdu1 复制这段内容后打开百度网盘手机App,操作更方便哦

视频演示:

Capturing IMU Data with a BNO055 Absolute Orientation Sensor [HUVFAYmNjh8]

总结

BNO055是一款易于使用的惯性测量单元,可集成到各种应用中,从机器人稳定(四轴飞行器,倒立摆等)到相机稳定和导航(包括航位推算)。

与其他输出原始测量数据的 9 自由度系统不同,BNO055 为主机微控制器过滤和合成数据,从而释放处理器带宽并消除编程中的猜测。

公众号 | FunIO
微信搜一搜 “funio”,发现更多精彩内容。
个人博客 | blog.boringhex.top

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个示例代码,可以连接传感器读取实时IMU四元数数据,并将其转换为欧拉角,并执行差值运算: ```python import math import numpy as np import time import board import busio import adafruit_bno055 # 初始四元数 q0 = 1 q1 = 0 q2 = 0 q3 = 0 # 初始欧拉角 roll0 = 0 pitch0 = 0 yaw0 = 0 # 差值权重 alpha = 0.5 # 初始化传感器 i2c = busio.I2C(board.SCL, board.SDA) sensor = adafruit_bno055.BNO055(i2c) # 循环读取传感器数据 while True: # 读取实时四元数数据 q0_new, q1_new, q2_new, q3_new = sensor.quaternion # 四元数转换为欧拉角 roll = math.atan2(2 * (q0_new * q1_new + q2_new * q3_new), 1 - 2 * (q1_new**2 + q2_new**2)) pitch = math.asin(2 * (q0_new * q2_new - q3_new * q1_new)) yaw = math.atan2(2 * (q0_new * q3_new + q1_new * q2_new), 1 - 2 * (q2_new**2 + q3_new**2)) # 与初始数据进行差值运算 roll_diff = roll - roll0 pitch_diff = pitch - pitch0 yaw_diff = yaw - yaw0 roll0 += alpha * roll_diff pitch0 += alpha * pitch_diff yaw0 += alpha * yaw_diff # 输出结果 print("roll0:", roll0) print("pitch0:", pitch0) print("yaw0:", yaw0) # 等待一段时间后继续循环 time.sleep(0.1) ``` 此代码中,首先定义了初始四元数 `q0, q1, q2, q3` 和初始欧拉角 `roll0, pitch0, yaw0`,然后定义了差值权重 `alpha`。 接下来,初始化传感器,并在一个循环中不断读取实时四元数数据,将其转换为欧拉角,并执行差值运算,更新初始欧拉角值。 最后,输出更新后的欧拉角值,并等待一段时间后继续循环。 注意,此代码仅为示例代码,实际应用中需要根据具体情况进行修改和优化。同时,需要根据传感器型号和连接方式进行相应的修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值