[ESP8266/ESP32]BMX60 旋转兔子 精华

836浏览
查看: 836|回复: 1

[ESP8266/ESP32] BMX60 旋转兔子

[复制链接]
一直以来我想通过传感器让现实世界中的物体控制电脑中的物体姿态,最近入手了DFRobotBMX160九轴加速度传感器模块【参考1】。

BMX60 旋转兔子图1

所谓9轴指的是三个加速度轴,三个地测轴和三个陀螺仪轴。简单的介绍一下需要了解的物理知识:首先,如果物体发生运动,那么在三个轴方向会出现加速度,那么我们可以知道它运动的指向,此外比较特别的是因为重力影响,所以一直会存在一个加速度G;接下来因为地磁的存在(指南针的基本原理),我们可以通过地磁轴得到相对于地磁的方向;最后陀螺因为惯性,它会一直保持指向,因此陀螺仪的轴可以用来反映当前时间和上一个时间姿态区别,得到诸如角速度这种方向。
很明显,如果单纯得到上面的9个参数,我们仍然难以用其中的一组描述物体当前的状态,因此,需要经过算法处理得到当前的状态。这个过程叫做“姿态解算”,同样也叫做姿态分析、姿态估计、姿态融合。姿态解算是根据IMU(惯性测量单元)数据(陀螺仪、加速度计、地磁计等)求解出飞行器的空中姿态,所以也叫做IMU数据融合。【参考2
因为本人能力有限,无力应对复杂的数学,因此这里通过硬件和现成的库来解决。
DFRobotBMX160引脚定义如下:

        
丝印
      
功能描述
  
   
VCC
  
电源正极

   
GND
  
电源负极

   
SCL
  
I2C时钟线

   
SDA
  
I2C数据线

   
CSB
  
BMX160协议选择引脚

   
INIT1
  
BMX160外部中断1

   
INIT2
  
BMX160外部中断2

   
ADDR
  
I2C地址选择

需要特别注意的是 CSB 是一个 SPI I2C 选择引脚,这次我们使用I2C,因此只需要链接 VCC GND  SCL SDA 引脚即可。我是用的是 ESP32 FireBeetle 进行测试:

BMX60 旋转兔子图2

连接好之后推荐使用 DFRobot BMX160库先进行测试【参考4】,确保串口能看到输出。
硬件部分非常简单,接下来要进行软件方面的编写。同样,还需要了解一些关于姿态描述的基本知识。描述姿态的主要方法有两种:欧拉角和四元数。下图是欧拉角的直观描述。三个参数分别是航向角、俯仰角和横滚角。


BMX60 旋转兔子图3

需要注意的是对于欧拉角有两种:动态和静态欧拉角。动态欧拉角指的是轴跟着物体姿态旋转,比如,下图中物体圆转之后蓝色XYZ坐标系发生了变化,变成了红色的XYZ,如果再次旋转,那么航向角、俯仰角和横滚角都是要相对于红色XYZ的。静态欧拉角的话,就是一直使用蓝色 XYZ。从资料上看,通常我们提到的欧拉角都是动态欧拉角。但是很多三维设计软件使用的是静态欧拉角。

BMX60 旋转兔子图4


欧拉角非常直观容易理解。但是在使用中,这种描述方法会存在“万向节死锁(gimballock)”的问题。就是说在一些特别的角度,两个轴重合了,然后再也不会分开,继续旋转时欧拉角只有2个参数会变。B站有很多视频讲述这个问题有兴趣的朋友可以看看。
为了解决这个问题,引入了四元数的概念。四元数没有欧拉角那么直观,也非常难以理解。
这次的目标是使用 Adafruit 提供的库和网站来直观的实现旋转一只兔子。
首先安装 BMX160 Adafruit_Sensor库;之后,烧录下面的程序:

  1. #include <Wire.h>
  2. #include <Adafruit_Sensor.h>
  3. #include <Mahony_BMX160.h>
  4. #include <Madgwick_BMX160.h>
  5. #include <DPEng_BMX160.h>
  6. // Create sensor instance.
  7. DPEng_BMX160 dpEng = DPEng_BMX160(0x160A, 0x160B, 0x160C);
  8. // Mag calibration values are calculated via ahrs_calibration example sketch results.
  9. // These values must be determined for each baord/environment.
  10. // See the image in this sketch folder for the values used
  11. // below.
  12. // Offsets applied to raw x/y/z mag values
  13. float mag_offsets[3]            = { 9.83F, 4.42F, -6.97F };
  14. // Soft iron error compensation matrix
  15. float mag_softiron_matrix[3][3] = { {  0.586,  0.006,  0.001 },
  16.                                     {  0.006,  0.601, -0.002 },
  17.                                     {  0.001,  -0.002,  2.835 } };
  18. float mag_field_strength        = 56.33F;
  19. // Offsets applied to compensate for gyro zero-drift error for x/y/z
  20. float gyro_zero_offsets[3]      = { 0.0F, 0.0F, 0.0F };
  21. // Mahony is lighter weight as a filter and should be used
  22. // on slower systems
  23. Mahony_BMX160 filter;
  24. //Madgwick_BMX160 filter;
  25. void setup()
  26. {
  27.   Serial.begin(115200);
  28.   // Wait for the Serial Monitor to open (comment out to run without Serial Monitor)
  29.   // while(!Serial);
  30.   Serial.println(F("DPEng AHRS Fusion Example")); Serial.println("");
  31.   // Initialize the sensors.
  32.   if(!dpEng.begin(BMX160_ACCELRANGE_4G, GYRO_RANGE_250DPS))
  33.   {
  34.     /* There was a problem detecting the BMX160 ... check your connections */
  35.     Serial.println("Ooops, no BMX160 detected ... Check your wiring!");
  36.     while(1);
  37.   }
  38.   
  39.   filter.begin();
  40. }
  41. void loop(void)
  42. {
  43.   sensors_event_t accel_event;
  44.   sensors_event_t gyro_event;
  45.   sensors_event_t mag_event;
  46.   // Get new data samples
  47.   dpEng.getEvent(&accel_event, &gyro_event, &mag_event);
  48.   // Apply mag offset compensation (base values in uTesla)
  49.   float x = mag_event.magnetic.x - mag_offsets[0];
  50.   float y = mag_event.magnetic.y - mag_offsets[1];
  51.   float z = mag_event.magnetic.z - mag_offsets[2];
  52.   // Apply mag soft iron error compensation
  53.   float mx = x * mag_softiron_matrix[0][0] + y * mag_softiron_matrix[0][1] + z * mag_softiron_matrix[0][2];
  54.   float my = x * mag_softiron_matrix[1][0] + y * mag_softiron_matrix[1][1] + z * mag_softiron_matrix[1][2];
  55.   float mz = x * mag_softiron_matrix[2][0] + y * mag_softiron_matrix[2][1] + z * mag_softiron_matrix[2][2];
  56.   // Apply gyro zero-rate error compensation
  57.   float gx = gyro_event.gyro.x + gyro_zero_offsets[0];
  58.   float gy = gyro_event.gyro.y + gyro_zero_offsets[1];
  59.   float gz = gyro_event.gyro.z + gyro_zero_offsets[2];
  60.   // Update the filter
  61.   filter.update(gx, gy, gz,
  62.                 accel_event.acceleration.x, accel_event.acceleration.y, accel_event.acceleration.z,
  63.                 mx, my, mz,
  64.                                 mag_event.timestamp);
  65.   // Print the orientation filter output
  66.   // Note: To avoid gimbal lock you should read quaternions not Euler
  67.   // angles, but Euler angles are used here since they are easier to
  68.   // understand looking at the raw values. See the ble fusion sketch for
  69.   // and example of working with quaternion data.
  70.   float roll = filter.getRoll();
  71.   float pitch = filter.getPitch();
  72.   float heading = filter.getYaw();
  73.   //Serial.print(millis());
  74.   Serial.print("Orientation: ");
  75.   Serial.print(heading);
  76.   Serial.print(",");
  77.   Serial.print(pitch);
  78.   Serial.print(",");
  79.   Serial.println(roll);
  80.   delay(100);
  81. }
复制代码
在串口管理器中看到输出表明工作正常之后就可以进行下一步。

BMX60 旋转兔子图5

我们需要网页读取串口数据,在 Chrome 上地址栏输入 chrome://flags,打开 Experimental Web Platformfeatures

BMX60 旋转兔子图6

之后,打开 https://adafruit.github.io/Adafruit_WebSerial_3DModelViewer/页面,设置波特率为 115200 , 同时选择“EulerAngles”:

BMX60 旋转兔子图7

接下来选择使用的串口(记得要关闭 Arduino 的串口,否则无法打开)

BMX60 旋转兔子图8

然后你就可以随心所欲的旋转,屏幕上的兔子会跟着你的板卡转动。

BMX60 旋转兔子图9

参考:





FriFebruary-202402026961..png
FriFebruary-202402025190..png

zoologist  高级技匠
 楼主|

发表于 2024-2-2 09:53:57

回复

使用道具 举报

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

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail