在 Arduino 上使用 SPI 从 IMU 记录原始数据时出现随机尖峰
Random Spikes while logging raw data from IMU using SPI on Arduino
我需要对 LSM9DS1 IMU 进行噪声表征。为此,我需要在静态条件下长时间(大约 10 小时)从传感器获取原始数据。
我准备了一个由 Arduino Uno 和使用 SPI 协议连接到它的 IMU 组成的日志系统。该系统运行良好,但是,即使 IMU 处于静态状态,我也会在加速度计和陀螺仪上出现随机尖峰。这些尖峰似乎总是与平均值相差 +/- 250。
下图显示了加速度计 X 轴上的这些尖峰。
IMU 设置为以 50 Hz 的频率提供数据,我也以相同的频率读取数据。以下是我基于 Sparkfun 提供的 LSM9DS1 库的 Arduino 代码:
#include <Wire.h>
#include <SPI.h>
#include <SparkFunLSM9DS1.h>
LSM9DS1 imu;
#define LSM9DS1_M_CS 10 // Can be any digital pin
#define LSM9DS1_AG_CS 9 // Can be any other digital pin
void setup()
{
Serial.begin(115200);
imu.settings.device.commInterface = IMU_MODE_SPI;
imu.settings.device.mAddress = LSM9DS1_M_CS;
imu.settings.device.agAddress = LSM9DS1_AG_CS;
if (!imu.begin())
{
Serial.println("Failed to communicate with LSM9DS1.");
while (1);
}
imu.enableFIFO(false);
imu.setFIFO(FIFO_OFF,0x00);
}
void loop()
{
Serial.print(micros());
Serial.print(" ");
printAccel();
printGyro();
delay(20);
}
void printGyro()
{
imu.readGyro();
Serial.print(imu.gx);
Serial.print(" ");
Serial.print(imu.gy);
Serial.print(" ");
Serial.println(imu.gz);
}
void printAccel()
{
imu.readAccel();
Serial.print(imu.ax);
Serial.print(" ");
Serial.print(imu.ay);
Serial.print(" ");
Serial.print(imu.az);
Serial.print(" ");
}
"spikes" 似乎能量很低,可能时不时会出现一次虚假阅读。您当然可以尝试弄清楚到底是什么导致了它们(可能就像有人砰地关上了门一样),但我认为这更多是硬件调试问题。
我想最终你会想要过滤掉所有这些噪音。您需要多复杂的数字滤波器取决于您的 "measurements" 与测量中的随机噪声相比有多快。
最简单的过滤器之一如下,其中 filterValue 是 "running" 值,senseValue 是当前原始测量值,scaleFactor 是一个小于 1 的数字(例如 0.1 或 0.01)。数字越小,过滤的越多,但您看到的 "lag" 也越多。
filterValue = filterValue + scaleFactor * (senseValue - filterValue);
我想一旦你合理地过滤数据,那些"spikes"就会消失。
由于您存储了数据,因此您可以 运行 通过过滤器查看它的外观。
我需要对 LSM9DS1 IMU 进行噪声表征。为此,我需要在静态条件下长时间(大约 10 小时)从传感器获取原始数据。
我准备了一个由 Arduino Uno 和使用 SPI 协议连接到它的 IMU 组成的日志系统。该系统运行良好,但是,即使 IMU 处于静态状态,我也会在加速度计和陀螺仪上出现随机尖峰。这些尖峰似乎总是与平均值相差 +/- 250。
下图显示了加速度计 X 轴上的这些尖峰。
IMU 设置为以 50 Hz 的频率提供数据,我也以相同的频率读取数据。以下是我基于 Sparkfun 提供的 LSM9DS1 库的 Arduino 代码:
#include <Wire.h>
#include <SPI.h>
#include <SparkFunLSM9DS1.h>
LSM9DS1 imu;
#define LSM9DS1_M_CS 10 // Can be any digital pin
#define LSM9DS1_AG_CS 9 // Can be any other digital pin
void setup()
{
Serial.begin(115200);
imu.settings.device.commInterface = IMU_MODE_SPI;
imu.settings.device.mAddress = LSM9DS1_M_CS;
imu.settings.device.agAddress = LSM9DS1_AG_CS;
if (!imu.begin())
{
Serial.println("Failed to communicate with LSM9DS1.");
while (1);
}
imu.enableFIFO(false);
imu.setFIFO(FIFO_OFF,0x00);
}
void loop()
{
Serial.print(micros());
Serial.print(" ");
printAccel();
printGyro();
delay(20);
}
void printGyro()
{
imu.readGyro();
Serial.print(imu.gx);
Serial.print(" ");
Serial.print(imu.gy);
Serial.print(" ");
Serial.println(imu.gz);
}
void printAccel()
{
imu.readAccel();
Serial.print(imu.ax);
Serial.print(" ");
Serial.print(imu.ay);
Serial.print(" ");
Serial.print(imu.az);
Serial.print(" ");
}
"spikes" 似乎能量很低,可能时不时会出现一次虚假阅读。您当然可以尝试弄清楚到底是什么导致了它们(可能就像有人砰地关上了门一样),但我认为这更多是硬件调试问题。
我想最终你会想要过滤掉所有这些噪音。您需要多复杂的数字滤波器取决于您的 "measurements" 与测量中的随机噪声相比有多快。
最简单的过滤器之一如下,其中 filterValue 是 "running" 值,senseValue 是当前原始测量值,scaleFactor 是一个小于 1 的数字(例如 0.1 或 0.01)。数字越小,过滤的越多,但您看到的 "lag" 也越多。
filterValue = filterValue + scaleFactor * (senseValue - filterValue);
我想一旦你合理地过滤数据,那些"spikes"就会消失。
由于您存储了数据,因此您可以 运行 通过过滤器查看它的外观。