使用缓冲区和溢出缓冲区将IMU数据写入csv文件?

时间:2019-03-22 19:31:45

标签: c++ mbed nucleo imu

我一直在尝试为通过I2C连接到mbed板的LSM9DS1 IMU实现C ++互补滤波器,但是时序问题使我无法正确获得角速率集成。这是因为在我的代码中,我假设我的采样率为100Hz,但由于我要实时显示值所使用的printf()语句,这并不是精确的数据采样率。这导致我的滤波器的输出角度在将IMU放回其原始位置时漂移/不回到原始值。

建议我按照以下步骤进行操作,以避免代码中的延迟可能破坏我的时间敏感应用程序:

  • 在程序的每次迭代中,将原始IMU数据添加到缓冲区中
  • 当缓冲区快满时,请使用中断将所有数据写入 .csv文件的缓冲区
  • 当/如果缓冲区溢出,则将剩余数据添加到新的“溢出”中 缓冲”
  • 清空第一个缓冲区,并用溢出中存储的数据重新填充它 缓冲区等等
  • 通过手动处理数据来分别处理过滤计算 从.csv文件中收集完所有文件后,以避免计时 问题,并查看输出是否符合预期

整个缓冲区/溢出缓冲区的来回交互确实使我感到困惑,有人可以帮助我阐明如何从技术上实现上述步骤吗?预先感谢!

编辑:

#include "LSM9DS1.h"
#define DT 1/100

void runFilter()
{
    // calculate Euler angles from accelerometer and magnetometer (_roll, 
    // _pitch,_yaw)
    calcAttitude(imu.ax, imu.ay, imu.az, -imu.my, -imu.mx, imu.mz);

    _gyroAngleX += (_rateX*DT);
    _gyroAngleY += (_rateY*DT);
    _gyroAngleZ += (_rateZ*DT);

    _xfilt = 0.98f*(_gyroAngleX) + 0.02f*_roll;
    _yfilt = 0.98f*(_gyroAngleY) + 0.02f*_pitch;
    _zfilt = 0.98f*(_gyroAngleZ) + 0.02f*_yaw;

    printf("%.2f, %.2f, %.2f \n", _xfilt, _yfilt, _zfilt);
}

在main.cpp中:

int main()
{
    init(); // Initialise IMU
    while(1) {
        readValues(); // Read data from the IMUs
        runFilter(); 
    }
 }

1 个答案:

答案 0 :(得分:1)

正如Kentaro在评论中还提到的那样,请为printf使用一个单独的线程,并使用Mbed OS EventQueue将printf语句延迟到该线程。

EventQueue queue;
Thread event_thread(osPriorityLow);

int main() {
    event_thread.start(callback(&queue, &EventQueue::dispatch_forever));

    // after sampling
    queue.call(&printf, "%.2f, %.2f, %.2f \n", _xfilt, _yfilt, _zfilt);

但是,您可能仍然会遇到速度问题。一些一般性提示:

  1. 使用开发板可以处理的最高波特率。
  2. RawSerial(使用printf)上使用Serial对象,以避免声明互斥体。
  3. 不写入UART,而是写入文件(例如,将FATFileSystem挂载到SD卡)。这样会更快。